diff options
204 files changed, 5571 insertions, 3765 deletions
@@ -640,6 +640,10 @@ S: 25-29 St Giles S: Oxford S: United Kingdom +N: Bingbu Cao +E: bingbu.cao@amd.com +D: Ipu6, ipu7 and camera sensor drivers + N: Luiz Fernando N. Capitulino E: lcapitulino@mandriva.com.br E: lcapitulino@gmail.com @@ -3338,6 +3342,9 @@ E: rpurdie@rpsys.net D: Backlight subsystem maintainer S: United Kingdom +N: Tian Shu Qiu +D: Ipu6, ipu7 and camera sensor drivers + N: Daniel Quinlan E: quinlan@pathname.com W: https://www.pathname.com/~quinlan/ diff --git a/Documentation/admin-guide/media/em28xx-cardlist.rst b/Documentation/admin-guide/media/em28xx-cardlist.rst index 7dac07986d91..741aa7f7c882 100644 --- a/Documentation/admin-guide/media/em28xx-cardlist.rst +++ b/Documentation/admin-guide/media/em28xx-cardlist.rst @@ -446,3 +446,7 @@ EM28xx cards list - MyGica UTV3 Analog USB2.0 TV Box - em2860 - eb1a:2860 + * - 113 + - StarTech SVID2USB232 + - em28281 + - eb1a:8286 diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx355.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx355.yaml index 6050d7e7dcfe..d9cdfda699bf 100644 --- a/Documentation/devicetree/bindings/media/i2c/sony,imx355.yaml +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx355.yaml @@ -50,8 +50,15 @@ properties: properties: data-lanes: - minItems: 4 - maxItems: 4 + oneOf: + - items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + - items: + - const: 1 + - const: 2 required: - link-frequencies diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx678.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx678.yaml new file mode 100644 index 000000000000..098f72544216 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx678.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2026 Ideas on Board Oy +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/sony,imx678.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sony IMX678 Sensor + +maintainers: + - Jai Luthra <jai.luthra@ideasonboard.com> + +description: + Sony IMX678 diagonal 8.86 mm (Type 1/1.8) CMOS active pixel type solid-state + image sensor with a square pixel array and 8.40M (3856x2180) effective pixels. + +allOf: + - $ref: /schemas/media/video-interface-devices.yaml# + +properties: + compatible: + items: + - enum: + - sony,imx678-aamr + - sony,imx678-aaqr + - const: sony,imx678 + description: + The IMX678 sensor exists in a colour variant (IMX678-AAQR) and a mono + variant (IMX678-AAMR). The variant-specific compatible describes the + exact sensor variant, with the generic IMX678 compatible as a fallback. + + reg: + maxItems: 1 + + clocks: + description: | + Input clock (INCK). Only the rates listed in the datasheet are supported: + 13.5, 18, 24, 27, 36, 37.125, 72, and 74.25 MHz. + maxItems: 1 + + avdd-supply: + description: Analog power supply (3.3V) + + ovdd-supply: + description: Interface power supply (1.8V) + + dvdd-supply: + description: Digital power supply (1.1V) + + reset-gpios: + description: Sensor RESETN (XCLR) GPIO + maxItems: 1 + + port: + $ref: /schemas/graph.yaml#/$defs/port-base + additionalProperties: false + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + oneOf: + - items: + - const: 1 + - const: 2 + - items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + - items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + - const: 5 + - const: 6 + - const: 7 + - const: 8 + + required: + - data-lanes + - link-frequencies + + required: + - endpoint + +required: + - compatible + - reg + - clocks + - avdd-supply + - ovdd-supply + - dvdd-supply + - port + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + camera@1a { + compatible = "sony,imx678-aaqr", "sony,imx678"; + reg = <0x1a>; + clocks = <&imx678_clk>; + + avdd-supply = <&camera_avdd_3v3>; + ovdd-supply = <&camera_ovdd_1v8>; + dvdd-supply = <&camera_dvdd_1v1>; + + reset-gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + + port { + imx678: endpoint { + remote-endpoint = <&cam>; + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <720000000>; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/media/i2c/st,vd55g1.yaml b/Documentation/devicetree/bindings/media/i2c/st,vd55g1.yaml index 060ac6829b66..58b1f9e85a9d 100644 --- a/Documentation/devicetree/bindings/media/i2c/st,vd55g1.yaml +++ b/Documentation/devicetree/bindings/media/i2c/st,vd55g1.yaml @@ -27,9 +27,10 @@ properties: compatible: enum: - st,vd55g1 + - st,vd55g4 - st,vd65g4 description: - VD55G1 is the monochrome variant, while VD65G4 is the color one. + VD55G1 and VD55G4 are monochrome variants, while VD65G4 is a color one. reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml index dedc5a4b81ec..43d84296e70d 100644 --- a/Documentation/devicetree/bindings/media/rc.yaml +++ b/Documentation/devicetree/bindings/media/rc.yaml @@ -122,10 +122,10 @@ properties: - rc-proteus-2309 - rc-purpletv - rc-pv951 - - rc-rc5-tv - rc-rc6-mce - rc-real-audio-220-32-keys - rc-reddo + - rc-siemens-gigaset-rc20 - rc-snapstream-firefly - rc-streamzap - rc-su3000 @@ -147,11 +147,11 @@ properties: - rc-tt-1500 - rc-twinhan-dtv-cab-ci - rc-twinhan1027 + - rc-vega-s9x - rc-videomate-k100 - rc-videomate-s350 - rc-videomate-tv-pvr - rc-videostrong-kii-pro - - rc-vega-s9x - rc-wetek-hub - rc-wetek-play2 - rc-winfast diff --git a/Documentation/driver-api/media/maintainer-entry-profile.rst b/Documentation/driver-api/media/maintainer-entry-profile.rst index c5c00c66d85c..7806d83128d4 100644 --- a/Documentation/driver-api/media/maintainer-entry-profile.rst +++ b/Documentation/driver-api/media/maintainer-entry-profile.rst @@ -432,6 +432,10 @@ The Media Driver Maintainers responsible for specific areas are: - Qualcomm drivers + - Ricardo Ribalda <ribalda@chromium.org> + + - Media-CI + Submit Checklist Addendum ------------------------- diff --git a/Documentation/userspace-api/media/cec/cec-ioc-adap-g-log-addrs.rst b/Documentation/userspace-api/media/cec/cec-ioc-adap-g-log-addrs.rst index f3293a589dd6..8397bf573798 100644 --- a/Documentation/userspace-api/media/cec/cec-ioc-adap-g-log-addrs.rst +++ b/Documentation/userspace-api/media/cec/cec-ioc-adap-g-log-addrs.rst @@ -185,6 +185,13 @@ logical address types are already defined will return with error ``EBUSY``. are CEC devices that can only handle CDC messages. All other messages are ignored. + * .. _`CEC-LOG-ADDRS-FL-CONFIG-FAILED`: + + - ``CEC_LOG_ADDRS_FL_CONFIG_FAILED`` + - 8 + - If this flag is set, then the CEC device failed to claim a free logical + address and is in the unconfigured state. This can never happen if + ``CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK`` was set as well. .. tabularcolumns:: |p{7.8cm}|p{1.0cm}|p{8.5cm}| diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index b8698b85bd80..d78328152b75 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -72,12 +72,6 @@ partial array, all elements have to be set or retrieved. The total size is calculated as ``elems`` * ``elem_size``. These values can be obtained by calling :ref:`VIDIOC_QUERY_EXT_CTRL <VIDIOC_QUERYCTRL>`. -To change the value of a set of controls applications initialize the -``id``, ``size``, ``reserved2`` and ``value/value64/string/ptr`` fields -of each struct :c:type:`v4l2_ext_control` and call -the :ref:`VIDIOC_S_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` ioctl. The controls will only be set if *all* -control values are valid. - To check if a set of controls have correct values applications initialize the ``id``, ``size``, ``reserved2`` and ``value/value64/string/ptr`` fields of each struct @@ -86,6 +80,15 @@ initialize the ``id``, ``size``, ``reserved2`` and values are automatically adjusted to a valid value or if an error is returned. +To change the value of a set of controls applications initialize the +``id``, ``size``, ``reserved2`` and ``value/value64/string/ptr`` fields +of each struct :c:type:`v4l2_ext_control` and call +the :ref:`VIDIOC_S_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` ioctl. +:ref:`VIDIOC_S_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` will implicitly call +:ref:`VIDIOC_TRY_EXT_CTRLS <VIDIOC_G_EXT_CTRLS>` first and return an +error if that fails. So the controls will only be set if *all* +control values are valid. + When the ``id`` or ``which`` is invalid drivers return an ``EINVAL`` error code. When the value is out of bounds drivers can choose to take the closest valid value or return an ``ERANGE`` error code, whatever seems more diff --git a/MAINTAINERS b/MAINTAINERS index 8b43b860ec69..e33bfaddaaee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3956,7 +3956,7 @@ F: Documentation/devicetree/bindings/leds/ams,as3668.yaml F: drivers/leds/leds-as3668.c ASAHI KASEI AK7375 LENS VOICE COIL DRIVER -M: Tianshu Qiu <tian.shu.qiu@intel.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -13150,9 +13150,7 @@ F: drivers/iommu/intel/ INTEL IPU3 CSI-2 CIO2 DRIVER M: Yong Zhi <yong.zhi@intel.com> M: Sakari Ailus <sakari.ailus@linux.intel.com> -M: Bingbu Cao <bingbu.cao@intel.com> M: Dan Scally <dan.scally@ideasonboard.com> -R: Tianshu Qiu <tian.shu.qiu@intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -13161,8 +13159,6 @@ F: drivers/media/pci/intel/ipu3/ INTEL IPU3 CSI-2 IMGU DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> -R: Bingbu Cao <bingbu.cao@intel.com> -R: Tianshu Qiu <tian.shu.qiu@intel.com> L: linux-media@vger.kernel.org S: Maintained F: Documentation/admin-guide/media/ipu3.rst @@ -13172,8 +13168,6 @@ F: drivers/staging/media/ipu3/ INTEL IPU6 INPUT SYSTEM DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> -M: Bingbu Cao <bingbu.cao@intel.com> -R: Tianshu Qiu <tian.shu.qiu@intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -13182,7 +13176,6 @@ F: drivers/media/pci/intel/ipu6/ INTEL IPU7 INPUT SYSTEM DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> -R: Bingbu Cao <bingbu.cao@intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -13394,6 +13387,7 @@ INTEL SKYLAKE INT3472 ACPI DEVICE DRIVER M: Daniel Scally <dan.scally@ideasonboard.com> M: Sakari Ailus <sakari.ailus@linux.intel.com> S: Maintained +T: git git://linuxtv.org/media.git F: drivers/platform/x86/intel/int3472/ F: include/linux/platform_data/x86/int3472.h @@ -13484,7 +13478,6 @@ F: drivers/net/wireless/intel/iwlwifi/ INTEL VISION SENSING CONTROLLER DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> -R: Bingbu Cao <bingbu.cao@intel.com> R: Lixu Zhang <lixu.zhang@intel.com> L: linux-media@vger.kernel.org S: Maintained @@ -19930,7 +19923,8 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,os05b10.yaml F: drivers/media/i2c/os05b10.c OMNIVISION OV01A10 SENSOR DRIVER -M: Bingbu Cao <bingbu.cao@intel.com> +M: Bingbu Cao <bingbu.cao@amd.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -20023,9 +20017,8 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov2735.yaml F: drivers/media/i2c/ov2735.c OMNIVISION OV2740 SENSOR DRIVER -M: Tianshu Qiu <tian.shu.qiu@intel.com> -R: Sakari Ailus <sakari.ailus@linux.intel.com> -R: Bingbu Cao <bingbu.cao@intel.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> +R: Bingbu Cao <bingbu.cao@amd.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -20167,8 +20160,8 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov9650.txt F: drivers/media/i2c/ov9650.c OMNIVISION OV9734 SENSOR DRIVER -M: Tianshu Qiu <tian.shu.qiu@intel.com> -R: Bingbu Cao <bingbu.cao@intel.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> +R: Bingbu Cao <bingbu.cao@amd.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -25265,7 +25258,8 @@ F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml F: drivers/media/i2c/imx296.c SONY IMX319 SENSOR DRIVER -M: Bingbu Cao <bingbu.cao@intel.com> +M: Bingbu Cao <bingbu.cao@amd.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -25287,7 +25281,9 @@ F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml F: drivers/media/i2c/imx335.c SONY IMX355 SENSOR DRIVER -M: Tianshu Qiu <tian.shu.qiu@intel.com> +M: Sakari Ailus <sakari.ailus@linux.intel.com> +M: Dave Stevenson <dave.stevenson@raspberrypi.com> +R: David Heidelberg <david@ixit.cz> L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media.git @@ -25308,6 +25304,19 @@ T: git git://linuxtv.org/media.git F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml F: drivers/media/i2c/imx415.c +SONY IMX471 SENSOR DRIVER +M: Kate Hsuan <hpa@redhat.com> +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/i2c/imx471.c + +SONY IMX678 SENSOR DRIVER +M: Jai Luthra <jai.luthra@ideasonboard.com> +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/i2c/sony,imx678.yaml +F: drivers/media/i2c/imx678.c + SONY MEMORYSTICK SUBSYSTEM M: Maxim Levitsky <maximlevitsky@gmail.com> M: Alex Dubov <oakad@yahoo.com> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9a7ac2eb9ce0..21937912a1a5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -862,6 +862,7 @@ static const char * const acpi_honor_dep_ids[] = { "INTC10DE", /* CVS (LNL) driver must be loaded to allow camera streaming */ "INTC10E0", /* CVS (ARL) driver must be loaded to allow camera streaming */ "INTC10E1", /* CVS (PTL) driver must be loaded to allow camera streaming */ + "INTC10FA", /* CVS (NVL) driver must be loaded to allow camera streaming */ "RSCV0001", /* RISC-V PLIC */ "RSCV0002", /* RISC-V APLIC */ "RSCV0005", /* RISC-V SBI MPXY MBOX */ diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index a90cb84a4b4d..ee8a200b9803 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -80,9 +80,9 @@ void cec_queue_event_fh(struct cec_fh *fh, const struct cec_event *new_ev, u64 ts) { static const u16 max_events[CEC_NUM_EVENTS] = { - 1, 1, 800, 800, 8, 8, 8, 8 + 3, 1, 800, 800, 8, 8, 8, 8 }; - struct cec_event_entry *entry; + struct cec_event_entry *new_entry, *entry; unsigned int ev_idx = new_ev->event - 1; if (WARN_ON(ev_idx >= ARRAY_SIZE(fh->events))) @@ -92,36 +92,57 @@ void cec_queue_event_fh(struct cec_fh *fh, ts = ktime_get_ns(); mutex_lock(&fh->lock); - if (ev_idx < CEC_NUM_CORE_EVENTS) - entry = &fh->core_events[ev_idx]; - else - entry = kmalloc_obj(*entry); - if (entry) { + new_entry = kmalloc_obj(*new_entry); + if (new_entry) { if (new_ev->event == CEC_EVENT_LOST_MSGS && fh->queued_events[ev_idx]) { + entry = list_first_entry(&fh->events[ev_idx], + struct cec_event_entry, list); entry->ev.lost_msgs.lost_msgs += new_ev->lost_msgs.lost_msgs; + kfree(new_entry); goto unlock; } - entry->ev = *new_ev; - entry->ev.ts = ts; + + new_entry->ev = *new_ev; + new_entry->ev.ts = ts; + + /* + * If the physical address becomes invalid (HPD went low), + * then just flush all pending STATE_CHANGE events since + * those are all obsoleted. + * + * This ensures you will not see stale STATE_CHANGE events. + */ + if (new_ev->event == CEC_EVENT_STATE_CHANGE && + new_ev->state_change.phys_addr == CEC_PHYS_ADDR_INVALID && + fh->queued_events[ev_idx]) { + /* drop all events */ + while (!list_empty(&fh->events[ev_idx])) { + entry = list_first_entry(&fh->events[ev_idx], + struct cec_event_entry, list); + list_del(&entry->list); + kfree(entry); + fh->total_queued_events--; + fh->queued_events[ev_idx]--; + } + new_entry->ev.flags |= CEC_EVENT_FL_DROPPED_EVENTS; + } if (fh->queued_events[ev_idx] < max_events[ev_idx]) { /* Add new msg at the end of the queue */ - list_add_tail(&entry->list, &fh->events[ev_idx]); + list_add_tail(&new_entry->list, &fh->events[ev_idx]); fh->queued_events[ev_idx]++; fh->total_queued_events++; goto unlock; } - if (ev_idx >= CEC_NUM_CORE_EVENTS) { - list_add_tail(&entry->list, &fh->events[ev_idx]); - /* drop the oldest event */ - entry = list_first_entry(&fh->events[ev_idx], - struct cec_event_entry, list); - list_del(&entry->list); - kfree(entry); - } + list_add_tail(&new_entry->list, &fh->events[ev_idx]); + /* drop the oldest event */ + entry = list_first_entry(&fh->events[ev_idx], + struct cec_event_entry, list); + list_del(&entry->list); + kfree(entry); } /* Mark that events were lost */ entry = list_first_entry_or_null(&fh->events[ev_idx], @@ -608,6 +629,13 @@ void cec_transmit_done_ts(struct cec_adapter *adap, u8 status, attempts_made = 1; mutex_lock(&adap->lock); + if (adap->error_inj_tx_timeouts) { + dprintk(2, "%s: error_inj_tx_timeouts %u\n", + __func__, adap->error_inj_tx_timeouts); + adap->error_inj_tx_timeouts--; + mutex_unlock(&adap->lock); + return; + } data = adap->transmitting; if (!data) { /* @@ -965,7 +993,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, */ mutex_unlock(&adap->lock); err = wait_for_completion_killable(&data->c); - cancel_delayed_work_sync(&data->work); + disable_delayed_work_sync(&data->work); mutex_lock(&adap->lock); if (err) @@ -1317,7 +1345,7 @@ static int cec_config_log_addr(struct cec_adapter *adap, { struct cec_log_addrs *las = &adap->log_addrs; struct cec_msg msg = { }; - const unsigned int max_retries = 2; + const unsigned int max_attempts = 3; unsigned int i; int err; @@ -1328,7 +1356,7 @@ static int cec_config_log_addr(struct cec_adapter *adap, msg.len = 1; msg.msg[0] = (log_addr << 4) | log_addr; - for (i = 0; i < max_retries; i++) { + for (i = 0; i < max_attempts; i++) { err = cec_transmit_msg_fh(adap, &msg, NULL, true); /* @@ -1345,31 +1373,24 @@ static int cec_config_log_addr(struct cec_adapter *adap, if (err) return err; - /* - * The message was aborted or timed out due to a disconnect or - * unconfigure, just bail out. - */ - if (msg.tx_status & - (CEC_TX_STATUS_ABORTED | CEC_TX_STATUS_TIMEOUT)) - return -EINTR; if (msg.tx_status & CEC_TX_STATUS_OK) return 0; if (msg.tx_status & CEC_TX_STATUS_NACK) break; /* - * Retry up to max_retries times if the message was neither + * Do up to max_attempts if the message was neither * OKed or NACKed. This can happen due to e.g. a Lost * Arbitration condition. */ } /* - * If we are unable to get an OK or a NACK after max_retries attempts + * If we are unable to get an OK or a NACK after max_attempts * (and note that each attempt already consists of four polls), then * we assume that something is really weird and that it is not a * good idea to try and claim this logical address. */ - if (i == max_retries) { + if (i == max_attempts) { dprintk(0, "polling for LA %u failed with tx_status=0x%04x\n", log_addr, msg.tx_status); return 0; @@ -1468,6 +1489,7 @@ static int cec_config_thread_func(void *arg) dprintk(1, "physical address: %x.%x.%x.%x, claim %d logical addresses\n", cec_phys_addr_exp(adap->phys_addr), las->num_log_addrs); las->log_addr_mask = 0; + las->flags &= ~CEC_LOG_ADDRS_FL_CONFIG_FAILED; if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED) goto configured; @@ -1600,6 +1622,8 @@ configured: unconfigure: for (i = 0; i < las->num_log_addrs; i++) las->log_addr[i] = CEC_LOG_ADDR_INVALID; + if (adap->phys_addr != CEC_PHYS_ADDR_INVALID) + las->flags |= CEC_LOG_ADDRS_FL_CONFIG_FAILED; cec_adap_unconfigure(adap); adap->is_configuring = false; adap->must_reconfigure = false; @@ -1717,7 +1741,6 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) cec_phys_addr_exp(phys_addr)); if (becomes_invalid || !is_invalid) { adap->phys_addr = CEC_PHYS_ADDR_INVALID; - cec_post_state_event(adap); cec_adap_unconfigure(adap); if (becomes_invalid) { cec_adap_enable(adap); @@ -2219,9 +2242,13 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, * Unprocessed messages are aborted if userspace isn't doing * any processing either. */ + mutex_lock(&adap->lock); if (!is_broadcast && !is_reply && !adap->follower_cnt && - !adap->cec_follower && msg->msg[1] != CEC_MSG_FEATURE_ABORT) + !adap->cec_follower && msg->msg[1] != CEC_MSG_FEATURE_ABORT) { + mutex_unlock(&adap->lock); return cec_feature_abort(adap, msg); + } + mutex_unlock(&adap->lock); break; } @@ -2234,10 +2261,12 @@ skip_processing: * Send to the exclusive follower if there is one, otherwise send * to all followers. */ + mutex_lock(&adap->lock); if (adap->cec_follower) cec_queue_msg_fh(adap->cec_follower, msg); else cec_queue_msg_followers(adap, msg); + mutex_unlock(&adap->lock); return 0; } diff --git a/drivers/media/cec/core/cec-api.c b/drivers/media/cec/core/cec-api.c index 103ded79526f..a491d7fc8a71 100644 --- a/drivers/media/cec/core/cec-api.c +++ b/drivers/media/cec/core/cec-api.c @@ -345,8 +345,7 @@ static long cec_dqevent(struct cec_adapter *adap, struct cec_fh *fh, if (copy_to_user(parg, &ev->ev, sizeof(ev->ev))) err = -EFAULT; - if (ev_idx >= CEC_NUM_CORE_EVENTS) - kfree(ev); + kfree(ev); fh->queued_events[ev_idx]--; fh->total_queued_events--; @@ -673,7 +672,7 @@ static int cec_release(struct inode *inode, struct file *filp) list_del(&entry->list); kfree(entry); } - for (i = CEC_NUM_CORE_EVENTS; i < CEC_NUM_EVENTS; i++) { + for (i = 0; i < CEC_NUM_EVENTS; i++) { while (!list_empty(&fh->events[i])) { struct cec_event_entry *entry = list_first_entry(&fh->events[i], diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c index 0fcd3b5e60c8..230f8a413e74 100644 --- a/drivers/media/cec/core/cec-core.c +++ b/drivers/media/cec/core/cec-core.c @@ -5,16 +5,33 @@ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/bitops.h> +#include <linux/bug.h> +#include <linux/cdev.h> +#include <linux/container_of.h> #include <linux/debugfs.h> -#include <linux/errno.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/fs.h> #include <linux/init.h> -#include <linux/kernel.h> -#include <linux/kmod.h> -#include <linux/mm.h> +#include <linux/kobject.h> +#include <linux/kthread.h> +#include <linux/list.h> +#include <linux/minmax.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/printk.h> +#include <linux/seq_file.h> #include <linux/slab.h> +#include <linux/sprintf.h> #include <linux/string.h> +#include <linux/time.h> #include <linux/types.h> +#include <linux/wait.h> + +#include <asm/page.h> #include "cec-priv.h" @@ -93,7 +110,7 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode, minor = find_first_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES); if (minor == CEC_NUM_DEVICES) { mutex_unlock(&cec_devnode_lock); - pr_err("could not get a free minor\n"); + pr_err("Could not get a free minor\n"); return -ENFILE; } @@ -104,19 +121,19 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode, devnode->dev.bus = &cec_bus_type; devnode->dev.devt = MKDEV(MAJOR(cec_dev_t), minor); devnode->dev.release = cec_devnode_release; - dev_set_name(&devnode->dev, "cec%d", devnode->minor); + dev_set_name(&devnode->dev, "%s%d", CEC_NAME, devnode->minor); device_initialize(&devnode->dev); /* Part 2: Initialize and register the character device */ cdev_init(&devnode->cdev, &cec_devnode_fops); devnode->cdev.owner = owner; - kobject_set_name(&devnode->cdev.kobj, "cec%d", devnode->minor); + kobject_set_name(&devnode->cdev.kobj, "%s%d", CEC_NAME, devnode->minor); devnode->registered = true; ret = cdev_device_add(&devnode->cdev, &devnode->dev); if (ret) { devnode->registered = false; - pr_err("%s: cdev_device_add failed\n", __func__); + pr_err("cdev_device_add() failed\n"); goto clr_bit; } @@ -205,19 +222,35 @@ static int cec_error_inj_show(struct seq_file *sf, void *unused) return call_op(adap, error_inj_show, sf); } +DEFINE_SHOW_STORE_ATTRIBUTE(cec_error_inj); -static int cec_error_inj_open(struct inode *inode, struct file *file) +static ssize_t cec_error_inj_tx_timeouts_write(struct file *file, + const char __user *ubuf, size_t count, loff_t *ppos) { - return single_open(file, cec_error_inj_show, inode->i_private); + struct seq_file *sf = file->private_data; + struct cec_adapter *adap = sf->private; + int ret; + + if (count > 5) + return -EINVAL; + + mutex_lock(&adap->lock); + ret = kstrtou32_from_user(ubuf, count, 0, &adap->error_inj_tx_timeouts); + if (ret) + adap->error_inj_tx_timeouts = 0; + mutex_unlock(&adap->lock); + return ret ? : count; } -static const struct file_operations cec_error_inj_fops = { - .open = cec_error_inj_open, - .write = cec_error_inj_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +static int cec_error_inj_tx_timeouts_show(struct seq_file *sf, void *unused) +{ + struct cec_adapter *adap = sf->private; + + seq_printf(sf, "%u", adap->error_inj_tx_timeouts); + return 0; +} + +DEFINE_SHOW_STORE_ATTRIBUTE(cec_error_inj_tx_timeouts); #endif struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, @@ -263,12 +296,11 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, mutex_init(&adap->devnode.lock_fhs); mutex_init(&adap->devnode.lock); - adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name); + adap->kthread = kthread_run(cec_thread_func, adap, "%s-%s", CEC_NAME, name); if (IS_ERR(adap->kthread)) { - pr_err("cec-%s: kernel_thread() failed\n", name); + pr_err("%s: kthread_run() failed\n", name); res = PTR_ERR(adap->kthread); - kfree(adap); - return ERR_PTR(res); + goto err_free_adap; } #ifdef CONFIG_MEDIA_CEC_RC @@ -278,11 +310,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, /* Prepare the RC input device */ adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); if (!adap->rc) { - pr_err("cec-%s: failed to allocate memory for rc_dev\n", - name); + pr_err("%s: failed to allocate memory for rc_dev\n", name); kthread_stop(adap->kthread); - kfree(adap); - return ERR_PTR(-ENOMEM); + res = -ENOMEM; + goto err_free_adap; } snprintf(adap->input_phys, sizeof(adap->input_phys), @@ -298,9 +329,18 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->allowed_protocols = RC_PROTO_BIT_CEC; adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; - adap->rc->timeout = MS_TO_US(550); + adap->rc->timeout = 550 * USEC_PER_MSEC; #endif return adap; + +err_free_adap: + mutex_destroy(&adap->devnode.lock); + mutex_destroy(&adap->devnode.lock_fhs); + + mutex_destroy(&adap->lock); + + kfree(adap); + return ERR_PTR(res); } EXPORT_SYMBOL_GPL(cec_allocate_adapter); @@ -326,8 +366,7 @@ int cec_register_adapter(struct cec_adapter *adap, res = rc_register_device(adap->rc); if (res) { - pr_err("cec-%s: failed to prepare input device\n", - adap->name); + pr_err("%s: failed to prepare input device\n", adap->name); rc_free_device(adap->rc); adap->rc = NULL; return res; @@ -356,6 +395,9 @@ int cec_register_adapter(struct cec_adapter *adap, debugfs_create_devm_seqfile(&adap->devnode.dev, "status", adap->cec_dir, cec_adap_status); + debugfs_create_file("error-inj-tx-timeouts", 0644, adap->cec_dir, adap, + &cec_error_inj_tx_timeouts_fops); + if (!adap->ops->error_inj_show || !adap->ops->error_inj_parse_line) return 0; debugfs_create_file("error-inj", 0644, adap->cec_dir, adap, @@ -371,9 +413,7 @@ void cec_unregister_adapter(struct cec_adapter *adap) return; #ifdef CONFIG_MEDIA_CEC_RC - /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); - adap->rc = NULL; #endif debugfs_remove_recursive(adap->cec_dir); #ifdef CONFIG_CEC_NOTIFIER @@ -387,14 +427,23 @@ void cec_delete_adapter(struct cec_adapter *adap) { if (IS_ERR_OR_NULL(adap)) return; + if (adap->kthread_config) kthread_stop(adap->kthread_config); kthread_stop(adap->kthread); + if (adap->ops->adap_free) adap->ops->adap_free(adap); + #ifdef CONFIG_MEDIA_CEC_RC rc_free_device(adap->rc); #endif + + mutex_destroy(&adap->devnode.lock); + mutex_destroy(&adap->devnode.lock_fhs); + + mutex_destroy(&adap->lock); + kfree(adap); } EXPORT_SYMBOL_GPL(cec_delete_adapter); @@ -407,14 +456,14 @@ static int __init cec_devnode_init(void) int ret = alloc_chrdev_region(&cec_dev_t, 0, CEC_NUM_DEVICES, CEC_NAME); if (ret < 0) { - pr_warn("cec: unable to allocate major\n"); + pr_warn("Unable to allocate major\n"); return ret; } #ifdef CONFIG_DEBUG_FS - top_cec_dir = debugfs_create_dir("cec", NULL); + top_cec_dir = debugfs_create_dir(CEC_NAME, NULL); if (IS_ERR_OR_NULL(top_cec_dir)) { - pr_warn("cec: Failed to create debugfs cec dir\n"); + pr_warn("Failed to create debugfs " CEC_NAME " dir\n"); top_cec_dir = NULL; } #endif @@ -423,7 +472,7 @@ static int __init cec_devnode_init(void) if (ret < 0) { debugfs_remove_recursive(top_cec_dir); unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES); - pr_warn("cec: bus_register failed\n"); + pr_warn("bus_register() failed\n"); return -EIO; } diff --git a/drivers/media/cec/core/cec-pin.c b/drivers/media/cec/core/cec-pin.c index 6e1c39102832..6a0ee32e8401 100644 --- a/drivers/media/cec/core/cec-pin.c +++ b/drivers/media/cec/core/cec-pin.c @@ -115,7 +115,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force) return; pin->adap->cec_pin_is_high = v; - if (atomic_read(&pin->work_pin_num_events) < CEC_NUM_PIN_EVENTS) { + if (atomic_read_acquire(&pin->work_pin_num_events) < CEC_NUM_PIN_EVENTS) { u8 ev = v; if (pin->work_pin_events_dropped) { @@ -126,7 +126,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force) pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get(); pin->work_pin_events_wr = (pin->work_pin_events_wr + 1) % CEC_NUM_PIN_EVENTS; - atomic_inc(&pin->work_pin_num_events); + atomic_inc_return_release(&pin->work_pin_num_events); } else { pin->work_pin_events_dropped = true; pin->work_pin_events_dropped_cnt++; @@ -692,7 +692,6 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) v = cec_pin_read(pin); if (!v) break; - pin->state = CEC_ST_RX_START_BIT_HIGH; delta = ktime_us_delta(ts, pin->ts); /* Start bit low is too short, go back to idle */ if (delta < CEC_TIM_START_BIT_LOW_MIN - CEC_TIM_IDLE_SAMPLE) { @@ -703,7 +702,16 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts) cec_pin_to_idle(pin); break; } + pin->state = CEC_ST_RX_START_BIT_HIGH; if (rx_arb_lost(pin, &poll)) { + /* + * Normally rx_toggle is toggled in cec_pin_to_idle() + * when we're in an RX state, but here we switch to TX + * mode, so cec_pin_to_idle() sees a TX mode and never + * toggles rx_toggle. So toggle it here as a special + * corner case. + */ + pin->rx_toggle ^= 1; cec_msg_init(&pin->tx_msg, poll >> 4, poll & 0xf); pin->tx_generated_poll = true; pin->tx_extra_bytes = 0; @@ -1101,7 +1109,7 @@ static int cec_pin_thread_func(void *_adap) pin->work_tx_ts); } - while (atomic_read(&pin->work_pin_num_events)) { + while (atomic_read_acquire(&pin->work_pin_num_events)) { unsigned int idx = pin->work_pin_events_rd; u8 v = pin->work_pin_events[idx]; @@ -1110,7 +1118,7 @@ static int cec_pin_thread_func(void *_adap) v & CEC_PIN_EVENT_FL_DROPPED, pin->work_pin_ts[idx]); pin->work_pin_events_rd = (idx + 1) % CEC_NUM_PIN_EVENTS; - atomic_dec(&pin->work_pin_num_events); + atomic_dec_return_release(&pin->work_pin_num_events); } switch (atomic_xchg(&pin->work_irq_change, diff --git a/drivers/media/cec/platform/meson/ao-cec-g12a.c b/drivers/media/cec/platform/meson/ao-cec-g12a.c index 41f5b8669cb0..2c914f0008b5 100644 --- a/drivers/media/cec/platform/meson/ao-cec-g12a.c +++ b/drivers/media/cec/platform/meson/ao-cec-g12a.c @@ -405,6 +405,7 @@ static int meson_ao_cec_g12a_write(void *context, unsigned int addr, } static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = { + .name = "core", .reg_bits = 8, .val_bits = 8, .reg_read = meson_ao_cec_g12a_read, diff --git a/drivers/media/cec/platform/seco/seco-cec.c b/drivers/media/cec/platform/seco/seco-cec.c index 97ed9654c78a..654c70503dd5 100644 --- a/drivers/media/cec/platform/seco/seco-cec.c +++ b/drivers/media/cec/platform/seco/seco-cec.c @@ -7,14 +7,15 @@ * Copyright (C) 2018, Aidilab Srl. */ -#include <linux/module.h> #include <linux/acpi.h> #include <linux/delay.h> #include <linux/dmi.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/time.h> /* CEC Framework */ #include <media/cec-notifier.h> @@ -356,7 +357,7 @@ static int secocec_ir_probe(void *priv) cec->ir->allowed_protocols = RC_PROTO_BIT_RC5; cec->ir->priv = cec; cec->ir->map_name = RC_MAP_HAUPPAUGE; - cec->ir->timeout = MS_TO_US(100); + cec->ir->timeout = 100 * USEC_PER_MSEC; /* Clear the status register */ status = smb_rd16(SECOCEC_STATUS_REG_1, &val); diff --git a/drivers/media/cec/platform/stm32/stm32-cec.c b/drivers/media/cec/platform/stm32/stm32-cec.c index 1ec0cece0a5b..29418966a98e 100644 --- a/drivers/media/cec/platform/stm32/stm32-cec.c +++ b/drivers/media/cec/platform/stm32/stm32-cec.c @@ -132,7 +132,8 @@ static void stm32_rx_done(struct stm32_cec *cec, u32 status) u32 val; regmap_read(cec->regmap, CEC_RXDR, &val); - cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF; + if (cec->rx_msg.len < CEC_MAX_MSG_SIZE) + cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF; } if (cec->irq_status & RXEND) { @@ -193,18 +194,24 @@ static int stm32_cec_adap_enable(struct cec_adapter *adap, bool enable) static int stm32_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) { struct stm32_cec *cec = adap->priv; - u32 oar = (1 << logical_addr) << 16; u32 val; + int ret; /* Poll every 100µs the register CEC_CR to wait end of transmission */ - regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM), - 100, CEC_XFER_TIMEOUT_MS * 1000); + ret = regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM), + 100, CEC_XFER_TIMEOUT_MS * 1000); + if (ret) + return ret; + regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0); - if (logical_addr == CEC_LOG_ADDR_INVALID) + if (logical_addr == CEC_LOG_ADDR_INVALID) { regmap_update_bits(cec->regmap, CEC_CFGR, OAR, 0); - else + } else { + u32 oar = BIT(logical_addr) << 16; + regmap_update_bits(cec->regmap, CEC_CFGR, oar, oar); + } regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN); diff --git a/drivers/media/cec/platform/tegra/tegra_cec.c b/drivers/media/cec/platform/tegra/tegra_cec.c index 3ed50097262f..e22a4625f192 100644 --- a/drivers/media/cec/platform/tegra/tegra_cec.c +++ b/drivers/media/cec/platform/tegra/tegra_cec.c @@ -24,6 +24,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/seq_file.h> #include <linux/clk/tegra.h> #include <media/cec-notifier.h> @@ -47,6 +48,7 @@ struct tegra_cec { u32 tx_buf[CEC_MAX_MSG_SIZE]; u8 tx_buf_cur; u8 tx_buf_cnt; + u32 rx_total_low_drives; }; static inline u32 cec_read(struct tegra_cec *cec, u32 reg) @@ -116,6 +118,13 @@ static irqreturn_t tegra_cec_irq_handler(int irq, void *data) return IRQ_WAKE_THREAD; } + if (status & TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED) { + dev_warn_ratelimited(dev, "RX bus error detected, generated low drive\n"); + cec->rx_total_low_drives++; + cec_write(cec, TEGRA_CEC_INT_STAT, + TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED); + } + if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) || (status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) { tegra_cec_error_recovery(cec); @@ -241,9 +250,21 @@ static int tegra_cec_adap_enable(struct cec_adapter *adap, bool enable) TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED | TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED | TEGRA_CEC_INT_MASK_RX_REGISTER_FULL | + TEGRA_CEC_INT_MASK_RX_BUS_ERROR_DETECTED | TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED); - cec_write(cec, TEGRA_CEC_HW_CONTROL, TEGRA_CEC_HWCTRL_TX_RX_MODE); + /* + * TX_NAK_MODE ensures that the whole message is transmitted even + * if each byte is NACKed. Without this flag the retransmit of the + * messages after a NACK can be corrupt. This is a bug in the hardware. + * + * While less efficient, in practice you rarely transmit messages + * that can be NACKed, with the exception of POLL messages which + * are just one byte anyway. + */ + cec_write(cec, TEGRA_CEC_HW_CONTROL, + TEGRA_CEC_HWCTRL_TX_RX_MODE | + TEGRA_CEC_HWCTRL_TX_NAK_MODE); return 0; } @@ -307,11 +328,20 @@ static int tegra_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, return 0; } +static void tegra_cec_adap_status(struct cec_adapter *adap, struct seq_file *file) +{ + struct tegra_cec *cec = adap->priv; + + seq_printf(file, "receive low drive count: %u\n", + cec->rx_total_low_drives); +} + static const struct cec_adap_ops tegra_cec_ops = { .adap_enable = tegra_cec_adap_enable, .adap_log_addr = tegra_cec_adap_log_addr, .adap_transmit = tegra_cec_adap_transmit, .adap_monitor_all_enable = tegra_cec_adap_monitor_all_enable, + .adap_status = tegra_cec_adap_status, }; static int tegra_cec_probe(struct platform_device *pdev) @@ -458,6 +488,7 @@ static const struct of_device_id tegra_cec_of_match[] = { { .compatible = "nvidia,tegra210-cec", }, {}, }; +MODULE_DEVICE_TABLE(of, tegra_cec_of_match); static struct platform_driver tegra_cec_driver = { .driver = { diff --git a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c index 3381d86096a1..3c6ce6f3d93e 100644 --- a/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c +++ b/drivers/media/cec/usb/extron-da-hd-4k-plus/extron-da-hd-4k-plus.c @@ -657,7 +657,8 @@ static void extron_process_received(struct extron_port *port, const char *data) if (!port || port->disconnected) return; - if (len < 5 || (len - 2) % 3 || data[len - 2] != '*') + if (len < 5 || ((len - 2) / 3 > sizeof(msg.msg)) || + (len - 2) % 3 || data[len - 2] != '*') goto malformed; while (*data != '*') { diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index 931e5dc453b9..e1d5c220f738 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -2346,9 +2346,11 @@ static void tpg_fill_params_extras(const struct tpg_data *tpg, (params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); } -static void tpg_fill_plane_extras(const struct tpg_data *tpg, - const struct tpg_draw_params *params, - unsigned p, unsigned h, u8 *vbuf) +/* noinline to work around clang KASAN issues */ +static noinline_for_stack void +tpg_fill_plane_extras(const struct tpg_data *tpg, + const struct tpg_draw_params *params, + unsigned p, unsigned h, u8 *vbuf) { unsigned twopixsize = params->twopixsize; unsigned img_width = params->img_width; @@ -2483,9 +2485,9 @@ static void tpg_fill_plane_extras(const struct tpg_data *tpg, } } -static void tpg_fill_plane_pattern(const struct tpg_data *tpg, - const struct tpg_draw_params *params, - unsigned p, unsigned h, u8 *vbuf) +static noinline_for_stack void +tpg_fill_plane_pattern(const struct tpg_data *tpg, const struct tpg_draw_params *params, + unsigned p, unsigned h, u8 *vbuf) { unsigned twopixsize = params->twopixsize; unsigned img_width = params->img_width; diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 4baded4fd3b8..5a1ee5eb9c0f 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -635,19 +635,6 @@ struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp) } EXPORT_SYMBOL_GPL(vb2_find_buffer); -/* - * vb2_querybuf() - query video buffer information - * @q: vb2 queue - * @b: buffer struct passed from userspace to vidioc_querybuf handler - * in driver - * - * Should be called from vidioc_querybuf ioctl handler in driver. - * This function will verify the passed v4l2_buffer structure and fill the - * relevant information for the userspace. - * - * The return values from this function are intended to be directly returned - * from vidioc_querybuf handler in driver. - */ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) { struct vb2_buffer *vb; diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index d082b6c57c76..0286da57f382 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -30,6 +30,7 @@ #include <linux/kthread.h> #include <linux/ktime.h> #include <linux/compat.h> +#include <linux/lockdep.h> #include <asm/processor.h> #include <media/dvb_frontend.h> @@ -2760,77 +2761,25 @@ static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *w return 0; } -static int dvb_frontend_open(struct inode *inode, struct file *file) +static int __dvb_frontend_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; - struct dvb_adapter *adapter = fe->dvb; int ret; - dev_dbg(fe->dvb->device, "%s:\n", __func__); - if (fe->exit == DVB_FE_DEVICE_REMOVED) - return -ENODEV; - - if (adapter->mfe_shared == 2) { - mutex_lock(&adapter->mfe_lock); - if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - if (adapter->mfe_dvbdev && - !adapter->mfe_dvbdev->writers) { - mutex_unlock(&adapter->mfe_lock); - return -EBUSY; - } - adapter->mfe_dvbdev = dvbdev; - } - } else if (adapter->mfe_shared) { - mutex_lock(&adapter->mfe_lock); - - if (!adapter->mfe_dvbdev) - adapter->mfe_dvbdev = dvbdev; - - else if (adapter->mfe_dvbdev != dvbdev) { - struct dvb_device - *mfedev = adapter->mfe_dvbdev; - struct dvb_frontend - *mfe = mfedev->priv; - struct dvb_frontend_private - *mfepriv = mfe->frontend_priv; - int mferetry = (dvb_mfe_wait_time << 1); - - mutex_unlock(&adapter->mfe_lock); - while (mferetry-- && (mfedev->users != -1 || - mfepriv->thread)) { - if (msleep_interruptible(500)) { - if (signal_pending(current)) - return -EINTR; - } - } - - mutex_lock(&adapter->mfe_lock); - if (adapter->mfe_dvbdev != dvbdev) { - mfedev = adapter->mfe_dvbdev; - mfe = mfedev->priv; - mfepriv = mfe->frontend_priv; - if (mfedev->users != -1 || - mfepriv->thread) { - mutex_unlock(&adapter->mfe_lock); - return -EBUSY; - } - adapter->mfe_dvbdev = dvbdev; - } - } - } - if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) - goto err0; - - /* If we took control of the bus, we need to force - reinitialization. This is because many ts_bus_ctrl() - functions strobe the RESET pin on the demod, and if the - frontend thread already exists then the dvb_init() routine - won't get called (which is what usually does initial - register configuration). */ + return ret; + + /* + * If we took control of the bus, we need to force + * reinitialization. This is because many ts_bus_ctrl() + * functions strobe the RESET pin on the demod, and if the + * frontend thread already exists then the dvb_init() routine + * won't get called (which is what usually does initial + * register configuration). + */ fepriv->reinitialise = 1; } @@ -2871,8 +2820,6 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) dvb_frontend_get(fe); - if (adapter->mfe_shared) - mutex_unlock(&adapter->mfe_lock); return ret; err3: @@ -2891,12 +2838,88 @@ err2: err1: if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) fe->ops.ts_bus_ctrl(fe, 0); -err0: - if (adapter->mfe_shared) - mutex_unlock(&adapter->mfe_lock); + + return ret; +} + +static int wait_dvb_frontend(struct dvb_adapter *adapter, + struct dvb_device *mfedev) +{ + struct dvb_frontend *mfe = mfedev->priv; + struct dvb_frontend_private *mfepriv = mfe->frontend_priv; + int mferetry = (dvb_mfe_wait_time << 1); + int ret = 0; + + lockdep_assert_held(&adapter->mfe_lock); + + if (mfedev->users == -1 && !mfepriv->thread) + return 0; + + mutex_unlock(&adapter->mfe_lock); + + while (mferetry-- && (mfedev->users != -1 || mfepriv->thread)) { + if (msleep_interruptible(500)) + if (signal_pending(current)) { + ret = -EINTR; + break; + } + } + + mutex_lock(&adapter->mfe_lock); + return ret; } +static int dvb_frontend_open(struct inode *inode, struct file *file) +{ + struct dvb_device *dvbdev = file->private_data; + struct dvb_frontend *fe = dvbdev->priv; + struct dvb_adapter *adapter = fe->dvb; + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + if (fe->exit == DVB_FE_DEVICE_REMOVED) + return -ENODEV; + + if (!adapter->mfe_shared) + return __dvb_frontend_open(inode, file); + + guard(mutex)(&adapter->mfe_lock); + + if (adapter->mfe_shared == 2) { + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { + if (adapter->mfe_dvbdev && + !adapter->mfe_dvbdev->writers) + return -EBUSY; + adapter->mfe_dvbdev = dvbdev; + } + return __dvb_frontend_open(inode, file); + } + + if (!adapter->mfe_dvbdev) { + adapter->mfe_dvbdev = dvbdev; + } else if (adapter->mfe_dvbdev != dvbdev) { + struct dvb_device *mfedev = adapter->mfe_dvbdev; + struct dvb_frontend *mfe = mfedev->priv; + struct dvb_frontend_private *mfepriv = mfe->frontend_priv; + int ret; + + ret = wait_dvb_frontend(adapter, mfedev); + if (ret) + return ret; + + if (adapter->mfe_dvbdev != dvbdev) { + mfedev = adapter->mfe_dvbdev; + mfe = mfedev->priv; + mfepriv = mfe->frontend_priv; + if (mfedev->users != -1 || mfepriv->thread) + return -EBUSY; + adapter->mfe_dvbdev = dvbdev; + } + } + + return __dvb_frontend_open(inode, file); +} + static int dvb_frontend_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c index 993280fefc2c..5fbb466cc8af 100644 --- a/drivers/media/dvb-frontends/helene.c +++ b/drivers/media/dvb-frontends/helene.c @@ -995,22 +995,22 @@ struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, const struct helene_config *config, struct i2c_adapter *i2c) { - struct helene_priv *priv = NULL; + struct helene_priv *pr = NULL; - priv = kzalloc_obj(struct helene_priv); - if (priv == NULL) + pr = kzalloc_obj(struct helene_priv); + if (!pr) return NULL; - priv->i2c_address = (config->i2c_address >> 1); - priv->i2c = i2c; - priv->set_tuner_data = config->set_tuner_priv; - priv->set_tuner = config->set_tuner_callback; - priv->xtal = config->xtal; + pr->i2c_address = (config->i2c_address >> 1); + pr->i2c = i2c; + pr->set_tuner_data = config->set_tuner_priv; + pr->set_tuner = config->set_tuner_callback; + pr->xtal = config->xtal; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (helene_x_pon(priv) != 0) { - kfree(priv); + if (helene_x_pon(pr) != 0) { + kfree(pr); return NULL; } @@ -1019,10 +1019,10 @@ struct dvb_frontend *helene_attach_s(struct dvb_frontend *fe, memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_s, sizeof(struct dvb_tuner_ops)); - fe->tuner_priv = priv; - dev_info(&priv->i2c->dev, - "Sony HELENE Sat attached on addr=%x at I2C adapter %p\n", - priv->i2c_address, priv->i2c); + fe->tuner_priv = pr; + dev_info(&pr->i2c->dev, + "Sony HELENE Sat attached on addr=%x at I2C adapter %p\n", + pr->i2c_address, pr->i2c); return fe; } EXPORT_SYMBOL_GPL(helene_attach_s); @@ -1031,22 +1031,22 @@ struct dvb_frontend *helene_attach(struct dvb_frontend *fe, const struct helene_config *config, struct i2c_adapter *i2c) { - struct helene_priv *priv = NULL; + struct helene_priv *pr = NULL; - priv = kzalloc_obj(struct helene_priv); - if (priv == NULL) + pr = kzalloc_obj(struct helene_priv); + if (!pr) return NULL; - priv->i2c_address = (config->i2c_address >> 1); - priv->i2c = i2c; - priv->set_tuner_data = config->set_tuner_priv; - priv->set_tuner = config->set_tuner_callback; - priv->xtal = config->xtal; + pr->i2c_address = (config->i2c_address >> 1); + pr->i2c = i2c; + pr->set_tuner_data = config->set_tuner_priv; + pr->set_tuner = config->set_tuner_callback; + pr->xtal = config->xtal; if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (helene_x_pon(priv) != 0) { - kfree(priv); + if (helene_x_pon(pr) != 0) { + kfree(pr); return NULL; } @@ -1055,10 +1055,10 @@ struct dvb_frontend *helene_attach(struct dvb_frontend *fe, memcpy(&fe->ops.tuner_ops, &helene_tuner_ops_t, sizeof(struct dvb_tuner_ops)); - fe->tuner_priv = priv; - dev_info(&priv->i2c->dev, - "Sony HELENE Ter attached on addr=%x at I2C adapter %p\n", - priv->i2c_address, priv->i2c); + fe->tuner_priv = pr; + dev_info(&pr->i2c->dev, + "Sony HELENE Ter attached on addr=%x at I2C adapter %p\n", + pr->i2c_address, pr->i2c); return fe; } EXPORT_SYMBOL_GPL(helene_attach); diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index c564485e3bbb..0330e7f0881a 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -906,9 +906,12 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count) goto err; mutex_unlock(&dev->v4l2_lock); + return 0; err: + rtl2832_sdr_free_urbs(dev); + rtl2832_sdr_free_stream_bufs(dev); rtl2832_sdr_cleanup_queued_bufs(dev, VB2_BUF_STATE_QUEUED); mutex_unlock(&dev->v4l2_lock); @@ -1477,14 +1480,22 @@ static void rtl2832_sdr_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "\n"); - mutex_lock(&dev->vb_queue_lock); + /* + * vb2_video_unregister_device() releases the vb2 queue, which + * triggers rtl2832_sdr_stop_streaming() if streaming is active. + * stop_streaming() uses dev->udev to free URBs and coherent DMA + * stream buffers via usb_free_coherent(), so it must run before + * dev->udev is cleared. vb2_video_unregister_device() locks + * vb_queue_lock internally and stop_streaming() locks v4l2_lock, + * so neither may be held by the caller. + */ + v4l2_device_disconnect(&dev->v4l2_dev); + vb2_video_unregister_device(&dev->vdev); + mutex_lock(&dev->v4l2_lock); - /* No need to keep the urbs around after disconnection */ dev->udev = NULL; - v4l2_device_disconnect(&dev->v4l2_dev); - video_unregister_device(&dev->vdev); mutex_unlock(&dev->v4l2_lock); - mutex_unlock(&dev->vb_queue_lock); + v4l2_device_put(&dev->v4l2_dev); module_put(pdev->dev.parent->driver->owner); } diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 5d173e0ecf42..5c52007f9cbe 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -259,6 +259,7 @@ config VIDEO_IMX335 config VIDEO_IMX355 tristate "Sony IMX355 sensor support" + select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the Sony IMX355 camera. @@ -269,6 +270,7 @@ config VIDEO_IMX355 config VIDEO_IMX412 tristate "Sony IMX412 sensor support" depends on OF + select V4L2_CCI_I2C help This is a Video4Linux2 sensor driver for the Sony IMX412 camera. @@ -287,6 +289,27 @@ config VIDEO_IMX415 To compile this driver as a module, choose M here: the module will be called imx415. +config VIDEO_IMX471 + tristate "Sony IMX471 sensor support" + select V4L2_CCI_I2C + help + This is a Video4Linux2 sensor driver for the Sony + IMX471 camera. + + To compile this driver as a module, choose M here: the + module will be called imx471. + +config VIDEO_IMX678 + tristate "Sony IMX678 sensor support" + depends on GPIOLIB + select V4L2_CCI_I2C + help + This is a Video4Linux2 sensor driver for the Sony + IMX678 camera. + + To compile this driver as a module, choose M here: the + module will be called imx678. + config VIDEO_MAX9271_LIB tristate diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index e45359efe0e4..d04bd5724552 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -61,6 +61,8 @@ obj-$(CONFIG_VIDEO_IMX335) += imx335.o obj-$(CONFIG_VIDEO_IMX355) += imx355.o obj-$(CONFIG_VIDEO_IMX412) += imx412.o obj-$(CONFIG_VIDEO_IMX415) += imx415.o +obj-$(CONFIG_VIDEO_IMX678) += imx678.o +obj-$(CONFIG_VIDEO_IMX471) += imx471.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o diff --git a/drivers/media/i2c/alvium-csi2.c b/drivers/media/i2c/alvium-csi2.c index dd991c2ee700..f51f9b987759 100644 --- a/drivers/media/i2c/alvium-csi2.c +++ b/drivers/media/i2c/alvium-csi2.c @@ -1290,7 +1290,7 @@ static int alvium_set_ctrl_auto_exposure(struct alvium_dev *alvium, bool on) struct device *dev = &alvium->i2c_client->dev; int ret; - ret = alvium_write_hshake(alvium, REG_BCRM_WHITE_BALANCE_AUTO_RW, + ret = alvium_write_hshake(alvium, REG_BCRM_EXPOSURE_AUTO_RW, on ? 0x02 : 0x00); if (ret) { dev_err(dev, "Fail to set autoexposure reg\n"); diff --git a/drivers/media/i2c/cvs/core.c b/drivers/media/i2c/cvs/core.c index fe9e59ac311c..d4a3b9c3bab1 100644 --- a/drivers/media/i2c/cvs/core.c +++ b/drivers/media/i2c/cvs/core.c @@ -31,6 +31,7 @@ #define PCI_DEVICE_ID_INTEL_IPU7 0x645d /* MTL / LNL */ #define PCI_DEVICE_ID_INTEL_IPU7P5 0xb05d /* ARL / PTL */ +#define PCI_DEVICE_ID_INTEL_IPU8 0xd719 /* NVL */ /* * IPU7 PCI device IDs not covered by ipu6_pci_tbl in ipu6-pci-table.h. @@ -39,6 +40,7 @@ static const struct pci_device_id icvs_ipu7_tbl[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU7) }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU7P5) }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU8) }, { } }; @@ -962,6 +964,7 @@ static const struct acpi_device_id intel_cvs_acpi_match[] = { { "INTC10DE" }, /* LNL */ { "INTC10E0" }, /* ARL */ { "INTC10E1" }, /* PTL */ + { "INTC10FA" }, /* NVL */ { } }; MODULE_DEVICE_TABLE(acpi, intel_cvs_acpi_match); diff --git a/drivers/media/i2c/gc0310.c b/drivers/media/i2c/gc0310.c index 7af4d66f42a0..754e82ad50ae 100644 --- a/drivers/media/i2c/gc0310.c +++ b/drivers/media/i2c/gc0310.c @@ -6,6 +6,7 @@ * Copyright (c) 2023-2025 Hans de Goede <hansg@kernel.org> */ +#include <linux/clk.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/gpio/consumer.h> @@ -84,6 +85,8 @@ #define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd) struct gc0310_device { + struct clk *clk; + struct v4l2_subdev sd; struct media_pad pad; @@ -635,7 +638,6 @@ static int gc0310_check_hwcfg(struct device *dev) }; struct fwnode_handle *ep_fwnode; unsigned long link_freq_bitmap; - u32 mclk; int ret; /* @@ -647,21 +649,6 @@ static int gc0310_check_hwcfg(struct device *dev) return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); - ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &mclk); - if (ret) { - fwnode_handle_put(ep_fwnode); - return dev_err_probe(dev, ret, - "reading clock-frequency property\n"); - } - - if (mclk != GC0310_MCLK_FREQ) { - fwnode_handle_put(ep_fwnode); - return dev_err_probe(dev, -EINVAL, - "external clock %u is not supported\n", - mclk); - } - ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &bus_cfg); fwnode_handle_put(ep_fwnode); if (ret) @@ -685,6 +672,7 @@ static int gc0310_check_hwcfg(struct device *dev) static int gc0310_probe(struct i2c_client *client) { struct gc0310_device *sensor; + unsigned long freq; int ret; ret = gc0310_check_hwcfg(&client->dev); @@ -695,6 +683,16 @@ static int gc0310_probe(struct i2c_client *client) if (!sensor) return -ENOMEM; + sensor->clk = devm_v4l2_sensor_clk_get(&client->dev, NULL); + if (IS_ERR(sensor->clk)) + return dev_err_probe(&client->dev, PTR_ERR(sensor->clk), + "failed to get clock\n"); + + freq = clk_get_rate(sensor->clk); + if (freq != GC0310_MCLK_FREQ) + return dev_err_probe(&client->dev, -EINVAL, + "external clock %lu is not supported\n", freq); + sensor->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(sensor->reset)) { return dev_err_probe(&client->dev, PTR_ERR(sensor->reset), diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index 27a5c212a527..8eb8588cb71b 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -9,74 +9,97 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/pm_runtime.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/unaligned.h> +#include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> #include <media/v4l2-fwnode.h> -#define IMX355_REG_MODE_SELECT 0x0100 +#define IMX355_REG_MODE_SELECT CCI_REG8(0x0100) #define IMX355_MODE_STANDBY 0x00 #define IMX355_MODE_STREAMING 0x01 /* Chip ID */ -#define IMX355_REG_CHIP_ID 0x0016 +#define IMX355_REG_CHIP_ID CCI_REG16(0x0016) #define IMX355_CHIP_ID 0x0355 +#define IMX355_REG_LANE_SEL CCI_REG8(0x0114) + +/* PLL registers that depend on the external clock frequency */ +#define IMX355_REG_EXTCLK_FREQ CCI_REG16(0x0136) +#define IMX355_REG_PLL_OP_PREDIV CCI_REG8(0x030d) +#define IMX355_REG_PLL_OP_MUL CCI_REG16(0x030e) +#define IMX355_REG_PLL_IVT_PCK_DIV CCI_REG8(0x0301) +#define IMX355_REG_PLL_IVT_SYSCK_DIV CCI_REG8(0x0303) +#define IMX355_PLL_OP_PREDIV 2 +#define IMX355_PLL_IVT_PCK_DIV 5 + /* V_TIMING internal */ -#define IMX355_REG_FLL 0x0340 +#define IMX355_REG_FLL CCI_REG16(0x0340) #define IMX355_FLL_MAX 0xffff +#define IMX355_VBLANK_MIN 20 + +#define IMX355_REG_LLP CCI_REG16(0x0342) +#define IMX355_LLP_MAX 0xffff + +#define IMX355_REG_X_ADD_START CCI_REG16(0x0344) +#define IMX355_REG_Y_ADD_START CCI_REG16(0x0346) +#define IMX355_REG_X_ADD_END CCI_REG16(0x0348) +#define IMX355_REG_Y_ADD_END CCI_REG16(0x034a) +#define IMX355_REG_X_OUT_SIZE CCI_REG16(0x034c) +#define IMX355_REG_Y_OUT_SIZE CCI_REG16(0x034e) /* Exposure control */ -#define IMX355_REG_EXPOSURE 0x0202 +#define IMX355_REG_EXPOSURE CCI_REG16(0x0202) #define IMX355_EXPOSURE_MIN 1 #define IMX355_EXPOSURE_STEP 1 #define IMX355_EXPOSURE_DEFAULT 0x0282 +#define IMX355_EXPOSURE_OFFSET 10 /* Analog gain control */ -#define IMX355_REG_ANALOG_GAIN 0x0204 +#define IMX355_REG_ANALOG_GAIN CCI_REG16(0x0204) #define IMX355_ANA_GAIN_MIN 0 #define IMX355_ANA_GAIN_MAX 960 #define IMX355_ANA_GAIN_STEP 1 #define IMX355_ANA_GAIN_DEFAULT 0 /* Digital gain control */ -#define IMX355_REG_DPGA_USE_GLOBAL_GAIN 0x3070 -#define IMX355_REG_DIG_GAIN_GLOBAL 0x020e +#define IMX355_REG_DPGA_USE_GLOBAL_GAIN CCI_REG8(0x3070) +#define IMX355_REG_DIG_GAIN_GLOBAL CCI_REG16(0x020e) #define IMX355_DGTL_GAIN_MIN 256 #define IMX355_DGTL_GAIN_MAX 4095 #define IMX355_DGTL_GAIN_STEP 1 #define IMX355_DGTL_GAIN_DEFAULT 256 /* Test Pattern Control */ -#define IMX355_REG_TEST_PATTERN 0x0600 +#define IMX355_REG_TEST_PATTERN CCI_REG16(0x0600) #define IMX355_TEST_PATTERN_DISABLED 0 #define IMX355_TEST_PATTERN_SOLID_COLOR 1 #define IMX355_TEST_PATTERN_COLOR_BARS 2 #define IMX355_TEST_PATTERN_GRAY_COLOR_BARS 3 #define IMX355_TEST_PATTERN_PN9 4 -/* Flip Control */ -#define IMX355_REG_ORIENTATION 0x0101 +#define IMX355_REG_REQ_LINK_BIT_RATE CCI_REG16(0x0820) -/* default link frequency and external clock */ -#define IMX355_LINK_FREQ_DEFAULT 360000000LL -#define IMX355_EXT_CLK 19200000 -#define IMX355_LINK_FREQ_INDEX 0 +#define IMX355_REG_BINNING_MODE CCI_REG8(0x0900) +#define IMX355_REG_BINNING_TYPE CCI_REG8(0x0901) +#define IMX355_REG_BINNING_WEIGHTING CCI_REG8(0x0902) -/* number of data lanes */ -#define IMX355_DATA_LANES 4 +/* Flip Control */ +#define IMX355_REG_ORIENTATION CCI_REG8(0x0101) -struct imx355_reg { - u16 address; - u8 val; -}; +#define IMX355_PIXEL_ARRAY_TOP 0 +#define IMX355_PIXEL_ARRAY_LEFT 0 +#define IMX355_PIXEL_ARRAY_WIDTH 3280 +#define IMX355_PIXEL_ARRAY_HEIGHT 2464 struct imx355_reg_list { u32 num_of_regs; - const struct imx355_reg *regs; + const struct cci_reg_sequence *regs; }; /* Mode : resolution and related config&values */ @@ -85,28 +108,58 @@ struct imx355_mode { u32 width; /* Frame height */ u32 height; + struct v4l2_rect crop; /* V-timing */ u32 fll_def; - u32 fll_min; /* H-timing */ u32 llp; - /* index of link frequency */ - u32 link_freq_index; - /* Default register values */ struct imx355_reg_list reg_list; }; +struct imx355_clk_params { + u32 ext_clk; + u16 extclk_freq; /* External clock (MHz) in 8.8 fixed point) */ + u16 pll_op_mpy[2]; /* OP system PLL multiplier */ + u8 pll_op_prediv[2]; /* OP system pre PLL d */ +}; + +/* + * The clock tree is in single PLL mode, so PREDIV_VT and MPY_IVT do nothing. + * In 4 lane mode the MIPI rate is 360Mhz (720Mbit/s) and pixel rate is + * 288MPix/s. + * In 2 lane mode the MIPI rate is 444MHz (888Mbit/s) and pixel rate + * 177.6MPix/s with a 24MHz clock, and 441.6MHz (883.2Mbit/s) and 176.6MPix/s + * with a 19.2MHz clock. + */ +static const struct imx355_clk_params imx355_clk_params[] = { + { + .ext_clk = 19200000, + .extclk_freq = 0x1333, + .pll_op_mpy = { 75, 92 }, + .pll_op_prediv = { 2, 2 } + }, + { + .ext_clk = 24000000, + .extclk_freq = 0x1800, + .pll_op_mpy = { 60, 111 }, + .pll_op_prediv = { 2, 3 } + }, +}; + struct imx355_hwcfg { + s64 link_freq_menu; unsigned long link_freq_bitmap; + unsigned int num_lanes; }; struct imx355 { struct device *dev; struct clk *clk; + struct regmap *regmap; struct v4l2_subdev sd; struct media_pad pad; @@ -114,24 +167,14 @@ struct imx355 { struct v4l2_ctrl_handler ctrl_handler; /* V4L2 Controls */ struct v4l2_ctrl *link_freq; - struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *vblank; struct v4l2_ctrl *hblank; struct v4l2_ctrl *exposure; struct v4l2_ctrl *vflip; struct v4l2_ctrl *hflip; - /* Current mode */ - const struct imx355_mode *cur_mode; - struct imx355_hwcfg *hwcfg; - - /* - * Mutex for serialized access: - * Protect sensor set pad format and start/stop streaming safely. - * Protect access to sensor v4l2 controls. - */ - struct mutex mutex; + const struct imx355_clk_params *clk_params; struct gpio_desc *reset_gpio; struct regulator_bulk_data *supplies; @@ -143,750 +186,147 @@ static const struct regulator_bulk_data imx355_supplies[] = { { .supply = "dovdd" }, }; -static const struct imx355_reg imx355_global_regs[] = { - { 0x0136, 0x13 }, - { 0x0137, 0x33 }, - { 0x304e, 0x03 }, - { 0x4348, 0x16 }, - { 0x4350, 0x19 }, - { 0x4408, 0x0a }, - { 0x440c, 0x0b }, - { 0x4411, 0x5f }, - { 0x4412, 0x2c }, - { 0x4623, 0x00 }, - { 0x462c, 0x0f }, - { 0x462d, 0x00 }, - { 0x462e, 0x00 }, - { 0x4684, 0x54 }, - { 0x480a, 0x07 }, - { 0x4908, 0x07 }, - { 0x4909, 0x07 }, - { 0x490d, 0x0a }, - { 0x491e, 0x0f }, - { 0x4921, 0x06 }, - { 0x4923, 0x28 }, - { 0x4924, 0x28 }, - { 0x4925, 0x29 }, - { 0x4926, 0x29 }, - { 0x4927, 0x1f }, - { 0x4928, 0x20 }, - { 0x4929, 0x20 }, - { 0x492a, 0x20 }, - { 0x492c, 0x05 }, - { 0x492d, 0x06 }, - { 0x492e, 0x06 }, - { 0x492f, 0x06 }, - { 0x4930, 0x03 }, - { 0x4931, 0x04 }, - { 0x4932, 0x04 }, - { 0x4933, 0x05 }, - { 0x595e, 0x01 }, - { 0x5963, 0x01 }, - { 0x3030, 0x01 }, - { 0x3031, 0x01 }, - { 0x3045, 0x01 }, - { 0x4010, 0x00 }, - { 0x4011, 0x00 }, - { 0x4012, 0x00 }, - { 0x4013, 0x01 }, - { 0x68a8, 0xfe }, - { 0x68a9, 0xff }, - { 0x6888, 0x00 }, - { 0x6889, 0x00 }, - { 0x68b0, 0x00 }, - { 0x3058, 0x00 }, - { 0x305a, 0x00 }, +static const struct cci_reg_sequence imx355_global_regs[] = { + { CCI_REG8(0x304e), 0x03 }, + { CCI_REG8(0x4348), 0x16 }, + { CCI_REG8(0x4350), 0x19 }, + { CCI_REG8(0x4408), 0x0a }, + { CCI_REG8(0x440c), 0x0b }, + { CCI_REG8(0x4411), 0x5f }, + { CCI_REG8(0x4412), 0x2c }, + { CCI_REG8(0x4623), 0x00 }, + { CCI_REG8(0x462c), 0x0f }, + { CCI_REG8(0x462d), 0x00 }, + { CCI_REG8(0x462e), 0x00 }, + { CCI_REG8(0x4684), 0x54 }, + { CCI_REG8(0x480a), 0x07 }, + { CCI_REG8(0x4908), 0x07 }, + { CCI_REG8(0x4909), 0x07 }, + { CCI_REG8(0x490d), 0x0a }, + { CCI_REG8(0x491e), 0x0f }, + { CCI_REG8(0x4921), 0x06 }, + { CCI_REG8(0x4923), 0x28 }, + { CCI_REG8(0x4924), 0x28 }, + { CCI_REG8(0x4925), 0x29 }, + { CCI_REG8(0x4926), 0x29 }, + { CCI_REG8(0x4927), 0x1f }, + { CCI_REG8(0x4928), 0x20 }, + { CCI_REG8(0x4929), 0x20 }, + { CCI_REG8(0x492a), 0x20 }, + { CCI_REG8(0x492c), 0x05 }, + { CCI_REG8(0x492d), 0x06 }, + { CCI_REG8(0x492e), 0x06 }, + { CCI_REG8(0x492f), 0x06 }, + { CCI_REG8(0x4930), 0x03 }, + { CCI_REG8(0x4931), 0x04 }, + { CCI_REG8(0x4932), 0x04 }, + { CCI_REG8(0x4933), 0x05 }, + { CCI_REG8(0x595e), 0x01 }, + { CCI_REG8(0x5963), 0x01 }, + { CCI_REG8(0x3030), 0x01 }, + { CCI_REG8(0x3031), 0x01 }, + { CCI_REG8(0x3045), 0x01 }, + { CCI_REG8(0x4010), 0x00 }, + { CCI_REG8(0x4011), 0x00 }, + { CCI_REG8(0x4012), 0x00 }, + { CCI_REG8(0x4013), 0x01 }, + { CCI_REG8(0x68a8), 0xfe }, + { CCI_REG8(0x68a9), 0xff }, + { CCI_REG8(0x6888), 0x00 }, + { CCI_REG8(0x6889), 0x00 }, + { CCI_REG8(0x68b0), 0x00 }, + { CCI_REG8(0x3058), 0x00 }, + { CCI_REG8(0x305a), 0x00 }, + { CCI_REG8(0x0112), 0x0a }, + { CCI_REG8(0x0113), 0x0a }, + { IMX355_REG_PLL_IVT_PCK_DIV, IMX355_PLL_IVT_PCK_DIV }, + { CCI_REG8(0x0303), 0x01 }, + { CCI_REG8(0x0305), 0x02 }, + { CCI_REG8(0x0306), 0x00 }, + { CCI_REG8(0x0307), 0x78 }, + { CCI_REG8(0x030b), 0x01 }, + { IMX355_REG_PLL_OP_PREDIV, IMX355_PLL_OP_PREDIV }, + { CCI_REG8(0x0310), 0x00 }, + { CCI_REG8(0x0220), 0x00 }, + { CCI_REG8(0x0222), 0x01 }, + { CCI_REG8(0x3088), 0x04 }, + { CCI_REG8(0x6813), 0x02 }, + { CCI_REG8(0x6835), 0x07 }, + { CCI_REG8(0x6836), 0x01 }, + { CCI_REG8(0x6837), 0x04 }, + { CCI_REG8(0x684d), 0x07 }, + { CCI_REG8(0x684e), 0x01 }, + { CCI_REG8(0x684f), 0x04 }, }; -static const struct imx355_reg_list imx355_global_setting = { - .num_of_regs = ARRAY_SIZE(imx355_global_regs), - .regs = imx355_global_regs, +static const struct cci_reg_sequence mode_3268x2448_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_3268x2448_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x0a }, - { 0x0341, 0x37 }, - { 0x0344, 0x00 }, - { 0x0345, 0x08 }, - { 0x0346, 0x00 }, - { 0x0347, 0x08 }, - { 0x0348, 0x0c }, - { 0x0349, 0xcb }, - { 0x034a, 0x09 }, - { 0x034b, 0x97 }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x0c }, - { 0x034d, 0xc4 }, - { 0x034e, 0x09 }, - { 0x034f, 0x90 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_3264x2448_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_3264x2448_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x0a }, - { 0x0341, 0x37 }, - { 0x0344, 0x00 }, - { 0x0345, 0x08 }, - { 0x0346, 0x00 }, - { 0x0347, 0x08 }, - { 0x0348, 0x0c }, - { 0x0349, 0xc7 }, - { 0x034a, 0x09 }, - { 0x034b, 0x97 }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x0c }, - { 0x034d, 0xc0 }, - { 0x034e, 0x09 }, - { 0x034f, 0x90 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_3280x2464_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_3280x2464_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x0a }, - { 0x0341, 0x37 }, - { 0x0344, 0x00 }, - { 0x0345, 0x00 }, - { 0x0346, 0x00 }, - { 0x0347, 0x00 }, - { 0x0348, 0x0c }, - { 0x0349, 0xcf }, - { 0x034a, 0x09 }, - { 0x034b, 0x9f }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x0c }, - { 0x034d, 0xd0 }, - { 0x034e, 0x09 }, - { 0x034f, 0xa0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1940x1096_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1940x1096_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x02 }, - { 0x0345, 0xa0 }, - { 0x0346, 0x02 }, - { 0x0347, 0xac }, - { 0x0348, 0x0a }, - { 0x0349, 0x33 }, - { 0x034a, 0x06 }, - { 0x034b, 0xf3 }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x07 }, - { 0x034d, 0x94 }, - { 0x034e, 0x04 }, - { 0x034f, 0x48 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1936x1096_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1936x1096_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x02 }, - { 0x0345, 0xa0 }, - { 0x0346, 0x02 }, - { 0x0347, 0xac }, - { 0x0348, 0x0a }, - { 0x0349, 0x2f }, - { 0x034a, 0x06 }, - { 0x034b, 0xf3 }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x07 }, - { 0x034d, 0x90 }, - { 0x034e, 0x04 }, - { 0x034f, 0x48 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1924x1080_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1924x1080_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x02 }, - { 0x0345, 0xa8 }, - { 0x0346, 0x02 }, - { 0x0347, 0xb4 }, - { 0x0348, 0x0a }, - { 0x0349, 0x2b }, - { 0x034a, 0x06 }, - { 0x034b, 0xeb }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x07 }, - { 0x034d, 0x84 }, - { 0x034e, 0x04 }, - { 0x034f, 0x38 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1920x1080_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1920x1080_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x02 }, - { 0x0345, 0xa8 }, - { 0x0346, 0x02 }, - { 0x0347, 0xb4 }, - { 0x0348, 0x0a }, - { 0x0349, 0x27 }, - { 0x034a, 0x06 }, - { 0x034b, 0xeb }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x00 }, - { 0x0901, 0x11 }, - { 0x0902, 0x00 }, - { 0x034c, 0x07 }, - { 0x034d, 0x80 }, - { 0x034e, 0x04 }, - { 0x034f, 0x38 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1640x1232_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1640x1232_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x00 }, - { 0x0345, 0x00 }, - { 0x0346, 0x00 }, - { 0x0347, 0x00 }, - { 0x0348, 0x0c }, - { 0x0349, 0xcf }, - { 0x034a, 0x09 }, - { 0x034b, 0x9f }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x06 }, - { 0x034d, 0x68 }, - { 0x034e, 0x04 }, - { 0x034f, 0xd0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1640x922_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1640x922_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x00 }, - { 0x0345, 0x00 }, - { 0x0346, 0x01 }, - { 0x0347, 0x30 }, - { 0x0348, 0x0c }, - { 0x0349, 0xcf }, - { 0x034a, 0x08 }, - { 0x034b, 0x63 }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x06 }, - { 0x034d, 0x68 }, - { 0x034e, 0x03 }, - { 0x034f, 0x9a }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1300x736_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1300x736_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x01 }, - { 0x0345, 0x58 }, - { 0x0346, 0x01 }, - { 0x0347, 0xf0 }, - { 0x0348, 0x0b }, - { 0x0349, 0x7f }, - { 0x034a, 0x07 }, - { 0x034b, 0xaf }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x05 }, - { 0x034d, 0x14 }, - { 0x034e, 0x02 }, - { 0x034f, 0xe0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1296x736_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1296x736_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x01 }, - { 0x0345, 0x58 }, - { 0x0346, 0x01 }, - { 0x0347, 0xf0 }, - { 0x0348, 0x0b }, - { 0x0349, 0x77 }, - { 0x034a, 0x07 }, - { 0x034b, 0xaf }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x05 }, - { 0x034d, 0x10 }, - { 0x034e, 0x02 }, - { 0x034f, 0xe0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1284x720_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1284x720_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x01 }, - { 0x0345, 0x68 }, - { 0x0346, 0x02 }, - { 0x0347, 0x00 }, - { 0x0348, 0x0b }, - { 0x0349, 0x6f }, - { 0x034a, 0x07 }, - { 0x034b, 0x9f }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x05 }, - { 0x034d, 0x04 }, - { 0x034e, 0x02 }, - { 0x034f, 0xd0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_1280x720_regs[] = { + { CCI_REG8(0x0700), 0x00 }, + { CCI_REG8(0x0701), 0x10 }, }; -static const struct imx355_reg mode_1280x720_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x07 }, - { 0x0343, 0x2c }, - { 0x0340, 0x05 }, - { 0x0341, 0x1a }, - { 0x0344, 0x01 }, - { 0x0345, 0x68 }, - { 0x0346, 0x02 }, - { 0x0347, 0x00 }, - { 0x0348, 0x0b }, - { 0x0349, 0x67 }, - { 0x034a, 0x07 }, - { 0x034b, 0x9f }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x22 }, - { 0x0902, 0x00 }, - { 0x034c, 0x05 }, - { 0x034d, 0x00 }, - { 0x034e, 0x02 }, - { 0x034f, 0xd0 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x00 }, - { 0x0701, 0x10 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, -}; - -static const struct imx355_reg mode_820x616_regs[] = { - { 0x0112, 0x0a }, - { 0x0113, 0x0a }, - { 0x0114, 0x03 }, - { 0x0342, 0x0e }, - { 0x0343, 0x58 }, - { 0x0340, 0x02 }, - { 0x0341, 0x8c }, - { 0x0344, 0x00 }, - { 0x0345, 0x00 }, - { 0x0346, 0x00 }, - { 0x0347, 0x00 }, - { 0x0348, 0x0c }, - { 0x0349, 0xcf }, - { 0x034a, 0x09 }, - { 0x034b, 0x9f }, - { 0x0220, 0x00 }, - { 0x0222, 0x01 }, - { 0x0900, 0x01 }, - { 0x0901, 0x44 }, - { 0x0902, 0x00 }, - { 0x034c, 0x03 }, - { 0x034d, 0x34 }, - { 0x034e, 0x02 }, - { 0x034f, 0x68 }, - { 0x0301, 0x05 }, - { 0x0303, 0x01 }, - { 0x0305, 0x02 }, - { 0x0306, 0x00 }, - { 0x0307, 0x78 }, - { 0x030b, 0x01 }, - { 0x030d, 0x02 }, - { 0x030e, 0x00 }, - { 0x030f, 0x4b }, - { 0x0310, 0x00 }, - { 0x0700, 0x02 }, - { 0x0701, 0x78 }, - { 0x0820, 0x0b }, - { 0x0821, 0x40 }, - { 0x3088, 0x04 }, - { 0x6813, 0x02 }, - { 0x6835, 0x07 }, - { 0x6836, 0x01 }, - { 0x6837, 0x04 }, - { 0x684d, 0x07 }, - { 0x684e, 0x01 }, - { 0x684f, 0x04 }, +static const struct cci_reg_sequence mode_820x616_regs[] = { + { CCI_REG8(0x0700), 0x02 }, + { CCI_REG8(0x0701), 0x78 }, }; static const char * const imx355_test_pattern_menu[] = { @@ -897,23 +337,19 @@ static const char * const imx355_test_pattern_menu[] = { "Pseudorandom Sequence (PN9)", }; -/* - * When adding more than the one below, make sure the disallowed ones will - * actually be disabled in the LINK_FREQ control. - */ -static const s64 link_freq_menu_items[] = { - IMX355_LINK_FREQ_DEFAULT, -}; - /* Mode configs */ static const struct imx355_mode supported_modes[] = { { .width = 3280, .height = 2464, + .crop = { + .width = 3280, + .height = 2464, + .left = 0, + .top = 0, + }, .fll_def = 2615, - .fll_min = 2615, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), .regs = mode_3280x2464_regs, @@ -922,10 +358,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 3268, .height = 2448, + .crop = { + .width = 3268, + .height = 2448, + .left = 8, + .top = 8, + }, .fll_def = 2615, - .fll_min = 2615, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_3268x2448_regs), .regs = mode_3268x2448_regs, @@ -934,10 +374,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 3264, .height = 2448, + .crop = { + .width = 3264, + .height = 2448, + .left = 8, + .top = 8, + }, .fll_def = 2615, - .fll_min = 2615, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs), .regs = mode_3264x2448_regs, @@ -946,10 +390,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1940, .height = 1096, + .crop = { + .width = 1940, + .height = 1096, + .left = 672, + .top = 684, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1940x1096_regs), .regs = mode_1940x1096_regs, @@ -958,10 +406,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1936, .height = 1096, + .crop = { + .width = 1936, + .height = 1096, + .left = 672, + .top = 684, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs), .regs = mode_1936x1096_regs, @@ -970,10 +422,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1924, .height = 1080, + .crop = { + .width = 1924, + .height = 1080, + .left = 680, + .top = 692, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1924x1080_regs), .regs = mode_1924x1080_regs, @@ -982,10 +438,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1920, .height = 1080, + .crop = { + .width = 1920, + .height = 1080, + .left = 680, + .top = 692, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs), .regs = mode_1920x1080_regs, @@ -994,10 +454,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1640, .height = 1232, + .crop = { + .width = 3280, + .height = 2464, + .left = 0, + .top = 0, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs), .regs = mode_1640x1232_regs, @@ -1006,10 +470,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1640, .height = 922, + .crop = { + .width = 3280, + .height = 1844, + .left = 0, + .top = 304, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1640x922_regs), .regs = mode_1640x922_regs, @@ -1018,10 +486,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1300, .height = 736, + .crop = { + .width = 2600, + .height = 1472, + .left = 344, + .top = 496, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1300x736_regs), .regs = mode_1300x736_regs, @@ -1030,10 +502,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1296, .height = 736, + .crop = { + .width = 2592, + .height = 1472, + .left = 344, + .top = 496, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1296x736_regs), .regs = mode_1296x736_regs, @@ -1042,10 +518,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1284, .height = 720, + .crop = { + .width = 2568, + .height = 1440, + .left = 360, + .top = 512, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1284x720_regs), .regs = mode_1284x720_regs, @@ -1054,10 +534,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 1280, .height = 720, + .crop = { + .width = 2560, + .height = 1440, + .left = 360, + .top = 512, + }, .fll_def = 1306, - .fll_min = 1306, .llp = 1836, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1280x720_regs), .regs = mode_1280x720_regs, @@ -1066,10 +550,14 @@ static const struct imx355_mode supported_modes[] = { { .width = 820, .height = 616, + .crop = { + .width = 3280, + .height = 2464, + .left = 0, + .top = 0, + }, .fll_def = 652, - .fll_min = 652, .llp = 3672, - .link_freq_index = IMX355_LINK_FREQ_INDEX, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_820x616_regs), .regs = mode_820x616_regs, @@ -1095,116 +583,28 @@ static u32 imx355_get_format_code(struct imx355 *imx355) { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, }, }; - lockdep_assert_held(&imx355->mutex); code = codes[imx355->vflip->val][imx355->hflip->val]; return code; } -/* Read registers up to 4 at a time */ -static int imx355_read_reg(struct imx355 *imx355, u16 reg, u32 len, u32 *val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); - struct i2c_msg msgs[2]; - u8 addr_buf[2]; - u8 data_buf[4] = { 0 }; - int ret; - - if (len > 4) - return -EINVAL; - - put_unaligned_be16(reg, addr_buf); - /* Write register address */ - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = ARRAY_SIZE(addr_buf); - msgs[0].buf = addr_buf; - - /* Read data from register */ - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = len; - msgs[1].buf = &data_buf[4 - len]; - - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (ret != ARRAY_SIZE(msgs)) - return -EIO; - - *val = get_unaligned_be32(data_buf); - - return 0; -} - -/* Write registers up to 4 at a time */ -static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); - u8 buf[6]; - - if (len > 4) - return -EINVAL; - - put_unaligned_be16(reg, buf); - put_unaligned_be32(val << (8 * (4 - len)), buf + 2); - if (i2c_master_send(client, buf, len + 2) != len + 2) - return -EIO; - - return 0; -} - -/* Write a list of registers */ -static int imx355_write_regs(struct imx355 *imx355, - const struct imx355_reg *regs, u32 len) -{ - int ret; - u32 i; - - for (i = 0; i < len; i++) { - ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val); - if (ret) { - dev_err_ratelimited(imx355->dev, - "write reg 0x%4.4x return err %d", - regs[i].address, ret); - - return ret; - } - } - - return 0; -} - -/* Open sub-device */ -static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct imx355 *imx355 = to_imx355(sd); - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_state_get_format(fh->state, 0); - - mutex_lock(&imx355->mutex); - - /* Initialize try_fmt */ - try_fmt->width = imx355->cur_mode->width; - try_fmt->height = imx355->cur_mode->height; - try_fmt->code = imx355_get_format_code(imx355); - try_fmt->field = V4L2_FIELD_NONE; - - mutex_unlock(&imx355->mutex); - - return 0; -} - static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) { struct imx355 *imx355 = container_of(ctrl->handler, struct imx355, ctrl_handler); + const struct v4l2_mbus_framefmt *format = NULL; + struct v4l2_subdev_state *state; s64 max; int ret; + state = v4l2_subdev_get_locked_active_state(&imx355->sd); + format = v4l2_subdev_state_get_format(state, 0); + /* Propagate change of current control to all related controls */ switch (ctrl->id) { case V4L2_CID_VBLANK: /* Update max exposure while meeting expected vblanking */ - max = imx355->cur_mode->height + ctrl->val - 10; + max = format->height + ctrl->val - IMX355_EXPOSURE_OFFSET; __v4l2_ctrl_modify_range(imx355->exposure, imx355->exposure->minimum, max, imx355->exposure->step, max); @@ -1221,31 +621,31 @@ static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_ANALOGUE_GAIN: /* Analog gain = 1024/(1024 - ctrl->val) times */ - ret = imx355_write_reg(imx355, IMX355_REG_ANALOG_GAIN, 2, - ctrl->val); + ret = cci_write(imx355->regmap, IMX355_REG_ANALOG_GAIN, + ctrl->val, NULL); break; case V4L2_CID_DIGITAL_GAIN: - ret = imx355_write_reg(imx355, IMX355_REG_DIG_GAIN_GLOBAL, 2, - ctrl->val); + ret = cci_write(imx355->regmap, IMX355_REG_DIG_GAIN_GLOBAL, + ctrl->val, NULL); break; case V4L2_CID_EXPOSURE: - ret = imx355_write_reg(imx355, IMX355_REG_EXPOSURE, 2, - ctrl->val); + ret = cci_write(imx355->regmap, IMX355_REG_EXPOSURE, + ctrl->val, NULL); break; case V4L2_CID_VBLANK: /* Update FLL that meets expected vertical blanking */ - ret = imx355_write_reg(imx355, IMX355_REG_FLL, 2, - imx355->cur_mode->height + ctrl->val); + ret = cci_write(imx355->regmap, IMX355_REG_FLL, + format->height + ctrl->val, NULL); break; case V4L2_CID_TEST_PATTERN: - ret = imx355_write_reg(imx355, IMX355_REG_TEST_PATTERN, - 2, ctrl->val); + ret = cci_write(imx355->regmap, IMX355_REG_TEST_PATTERN, + ctrl->val, NULL); break; case V4L2_CID_HFLIP: case V4L2_CID_VFLIP: - ret = imx355_write_reg(imx355, IMX355_REG_ORIENTATION, 1, - imx355->hflip->val | - imx355->vflip->val << 1); + ret = cci_write(imx355->regmap, IMX355_REG_ORIENTATION, + imx355->hflip->val | imx355->vflip->val << 1, + NULL); break; default: ret = -EINVAL; @@ -1272,9 +672,7 @@ static int imx355_enum_mbus_code(struct v4l2_subdev *sd, if (code->index > 0) return -EINVAL; - mutex_lock(&imx355->mutex); code->code = imx355_get_format_code(imx355); - mutex_unlock(&imx355->mutex); return 0; } @@ -1288,12 +686,9 @@ static int imx355_enum_frame_size(struct v4l2_subdev *sd, if (fse->index >= ARRAY_SIZE(supported_modes)) return -EINVAL; - mutex_lock(&imx355->mutex); if (fse->code != imx355_get_format_code(imx355)) { - mutex_unlock(&imx355->mutex); return -EINVAL; } - mutex_unlock(&imx355->mutex); fse->min_width = supported_modes[fse->index].width; fse->max_width = fse->min_width; @@ -1311,36 +706,10 @@ static void imx355_update_pad_format(struct imx355 *imx355, fmt->format.height = mode->height; fmt->format.code = imx355_get_format_code(imx355); fmt->format.field = V4L2_FIELD_NONE; -} - -static int imx355_do_get_pad_format(struct imx355 *imx355, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct v4l2_mbus_framefmt *framefmt; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); - fmt->format = *framefmt; - } else { - imx355_update_pad_format(imx355, imx355->cur_mode, fmt); - } - - return 0; -} - -static int imx355_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *fmt) -{ - struct imx355 *imx355 = to_imx355(sd); - int ret; - - mutex_lock(&imx355->mutex); - ret = imx355_do_get_pad_format(imx355, sd_state, fmt); - mutex_unlock(&imx355->mutex); - - return ret; + fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_601; + fmt->format.quantization = V4L2_QUANTIZATION_FULL_RANGE; + fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; } static int @@ -1351,13 +720,8 @@ imx355_set_pad_format(struct v4l2_subdev *sd, struct imx355 *imx355 = to_imx355(sd); const struct imx355_mode *mode; struct v4l2_mbus_framefmt *framefmt; - s32 vblank_def; - s32 vblank_min; + struct v4l2_rect *crop; s64 h_blank; - u64 pixel_rate; - u32 height; - - mutex_lock(&imx355->mutex); /* * Only one bayer order is supported. @@ -1370,23 +734,25 @@ imx355_set_pad_format(struct v4l2_subdev *sd, width, height, fmt->format.width, fmt->format.height); imx355_update_pad_format(imx355, mode, fmt); - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); - *framefmt = fmt->format; - } else { - imx355->cur_mode = mode; - pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4; - do_div(pixel_rate, 10); - __v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate); + framefmt = v4l2_subdev_state_get_format(sd_state, 0); + + *framefmt = fmt->format; + + crop = v4l2_subdev_state_get_crop(sd_state, 0); + crop->width = mode->crop.width; + crop->height = mode->crop.height; + crop->left = mode->crop.left; + crop->top = mode->crop.top; + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { /* Update limits and set FPS to default */ - height = imx355->cur_mode->height; - vblank_def = imx355->cur_mode->fll_def - height; - vblank_min = imx355->cur_mode->fll_min - height; - height = IMX355_FLL_MAX - height; - __v4l2_ctrl_modify_range(imx355->vblank, vblank_min, height, 1, - vblank_def); - __v4l2_ctrl_s_ctrl(imx355->vblank, vblank_def); - h_blank = mode->llp - imx355->cur_mode->width; + __v4l2_ctrl_modify_range(imx355->vblank, IMX355_VBLANK_MIN, + IMX355_FLL_MAX - mode->height, 1, + mode->fll_def - mode->height); + __v4l2_ctrl_s_ctrl(imx355->vblank, mode->fll_def - mode->height); + + h_blank = mode->llp - mode->width; + /* * Currently hblank is not changeable. * So FPS control is done only by vblank. @@ -1395,7 +761,42 @@ imx355_set_pad_format(struct v4l2_subdev *sd, h_blank, 1, h_blank); } - mutex_unlock(&imx355->mutex); + return 0; +} + +static int imx355_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_selection *sel) +{ + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *v4l2_subdev_state_get_crop(sd_state, 0); + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r.top = IMX355_PIXEL_ARRAY_TOP; + sel->r.left = IMX355_PIXEL_ARRAY_LEFT; + sel->r.width = IMX355_PIXEL_ARRAY_WIDTH; + sel->r.height = IMX355_PIXEL_ARRAY_HEIGHT; + + return 0; + } + + return -EINVAL; +} + +static int imx355_entity_init_state(struct v4l2_subdev *subdev, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_subdev_format fmt = { }; + + fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.format.code = MEDIA_BUS_FMT_SRGGB10_1X10; + fmt.format.width = supported_modes[0].width; + fmt.format.height = supported_modes[0].height; + + imx355_set_pad_format(subdev, sd_state, &fmt); return 0; } @@ -1403,52 +804,98 @@ imx355_set_pad_format(struct v4l2_subdev *sd, /* Start streaming */ static int imx355_start_streaming(struct imx355 *imx355) { - const struct imx355_reg_list *reg_list; - int ret; + const struct v4l2_mbus_framefmt *fmt; + struct v4l2_subdev_state *state; + const struct imx355_mode *mode; + int lane_idx = imx355->hwcfg->num_lanes == 4 ? 0 : 1; + struct v4l2_rect *crop; + u64 link_bitrate; + u8 binning_mode; + int ret = 0; /* Global Setting */ - reg_list = &imx355_global_setting; - ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); - if (ret) { - dev_err(imx355->dev, "failed to set global settings"); - return ret; - } + cci_multi_reg_write(imx355->regmap, imx355_global_regs, + ARRAY_SIZE(imx355_global_regs), &ret); - /* Apply default values of current mode */ - reg_list = &imx355->cur_mode->reg_list; - ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); - if (ret) { - dev_err(imx355->dev, "failed to set mode"); - return ret; - } + /* Apply values of current mode */ + state = v4l2_subdev_get_locked_active_state(&imx355->sd); + fmt = v4l2_subdev_state_get_format(state, 0); + crop = v4l2_subdev_state_get_crop(state, 0); + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, fmt->width, fmt->height); + cci_multi_reg_write(imx355->regmap, mode->reg_list.regs, + mode->reg_list.num_of_regs, &ret); + + /* Set readout crop and size registers */ + cci_write(imx355->regmap, IMX355_REG_X_ADD_START, crop->left, + &ret); + cci_write(imx355->regmap, IMX355_REG_Y_ADD_START, crop->top, &ret); + cci_write(imx355->regmap, IMX355_REG_X_ADD_END, + crop->width + crop->left - 1, &ret); + cci_write(imx355->regmap, IMX355_REG_Y_ADD_END, + crop->height + crop->top - 1, &ret); + cci_write(imx355->regmap, IMX355_REG_X_OUT_SIZE, fmt->width, &ret); + cci_write(imx355->regmap, IMX355_REG_Y_OUT_SIZE, fmt->height, &ret); + + binning_mode = ((crop->width / fmt->width) << 4) | + (crop->height / fmt->height); + cci_write(imx355->regmap, IMX355_REG_BINNING_MODE, + binning_mode == 0x11 ? 0x00 : 0x01, &ret); + cci_write(imx355->regmap, IMX355_REG_BINNING_TYPE, binning_mode, &ret); + cci_write(imx355->regmap, IMX355_REG_BINNING_WEIGHTING, 0x00, &ret); + + /* Set PLL registers for the external clock frequency */ + cci_write(imx355->regmap, IMX355_REG_EXTCLK_FREQ, + imx355->clk_params->extclk_freq, &ret); + cci_write(imx355->regmap, IMX355_REG_PLL_OP_MUL, + imx355->clk_params->pll_op_mpy[lane_idx], &ret); + cci_write(imx355->regmap, IMX355_REG_PLL_OP_PREDIV, + imx355->clk_params->pll_op_prediv[lane_idx], &ret); + cci_write(imx355->regmap, IMX355_REG_PLL_IVT_SYSCK_DIV, + lane_idx ? 2 : 1, &ret); + + /* Set MIPI configuration */ + cci_write(imx355->regmap, IMX355_REG_LANE_SEL, + imx355->hwcfg->num_lanes - 1, &ret); + + link_bitrate = imx355->link_freq->qmenu_int[imx355->link_freq->val] * + imx355->hwcfg->num_lanes * 2; + do_div(link_bitrate, 1000000); + cci_write(imx355->regmap, IMX355_REG_REQ_LINK_BIT_RATE, link_bitrate, + &ret); /* set digital gain control to all color mode */ - ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1); - if (ret) - return ret; + cci_write(imx355->regmap, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, &ret); + + /* set line length */ + cci_write(imx355->regmap, IMX355_REG_LLP, + imx355->hblank->val + fmt->width, &ret); /* Apply customized values from user */ - ret = __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler); - if (ret) - return ret; + if (!ret) + ret = __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler); + + cci_write(imx355->regmap, IMX355_REG_MODE_SELECT, IMX355_MODE_STREAMING, + &ret); - return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT, - 1, IMX355_MODE_STREAMING); + return ret; } /* Stop streaming */ static int imx355_stop_streaming(struct imx355 *imx355) { - return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT, - 1, IMX355_MODE_STANDBY); + return cci_write(imx355->regmap, IMX355_REG_MODE_SELECT, + IMX355_MODE_STANDBY, NULL); } static int imx355_set_stream(struct v4l2_subdev *sd, int enable) { struct imx355 *imx355 = to_imx355(sd); + struct v4l2_subdev_state *state; int ret = 0; - mutex_lock(&imx355->mutex); + state = v4l2_subdev_lock_and_get_active_state(sd); if (enable) { ret = pm_runtime_resume_and_get(imx355->dev); @@ -1464,21 +911,21 @@ static int imx355_set_stream(struct v4l2_subdev *sd, int enable) goto err_rpm_put; } else { imx355_stop_streaming(imx355); - pm_runtime_put(imx355->dev); + pm_runtime_put_autosuspend(imx355->dev); } /* vflip and hflip cannot change during streaming */ __v4l2_ctrl_grab(imx355->vflip, enable); __v4l2_ctrl_grab(imx355->hflip, enable); - mutex_unlock(&imx355->mutex); + v4l2_subdev_unlock_state(state); return ret; err_rpm_put: - pm_runtime_put(imx355->dev); + pm_runtime_put_autosuspend(imx355->dev); err_unlock: - mutex_unlock(&imx355->mutex); + v4l2_subdev_unlock_state(state); return ret; } @@ -1487,14 +934,14 @@ err_unlock: static int imx355_identify_module(struct imx355 *imx355) { int ret; - u32 val; + u64 val; - ret = imx355_read_reg(imx355, IMX355_REG_CHIP_ID, 2, &val); + ret = cci_read(imx355->regmap, IMX355_REG_CHIP_ID, &val, NULL); if (ret) return ret; if (val != IMX355_CHIP_ID) { - dev_err(imx355->dev, "chip id mismatch: %x!=%x", + dev_err(imx355->dev, "chip id mismatch: %x!=%llx", IMX355_CHIP_ID, val); return -EIO; } @@ -1512,9 +959,10 @@ static const struct v4l2_subdev_video_ops imx355_video_ops = { static const struct v4l2_subdev_pad_ops imx355_pad_ops = { .enum_mbus_code = imx355_enum_mbus_code, - .get_fmt = imx355_get_pad_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = imx355_set_pad_format, .enum_frame_size = imx355_enum_frame_size, + .get_selection = imx355_get_selection, }; static const struct v4l2_subdev_ops imx355_subdev_ops = { @@ -1528,7 +976,7 @@ static const struct media_entity_operations imx355_subdev_entity_ops = { }; static const struct v4l2_subdev_internal_ops imx355_internal_ops = { - .open = imx355_open, + .init_state = imx355_entity_init_state, }; static int imx355_power_off(struct device *dev) @@ -1582,13 +1030,11 @@ static int imx355_init_controls(struct imx355 *imx355) { struct v4l2_fwnode_device_properties props; struct v4l2_ctrl_handler *ctrl_hdlr; + const struct imx355_mode *mode = &supported_modes[0]; s64 exposure_max; s64 vblank_def; - s64 vblank_min; s64 hblank; u64 pixel_rate; - const struct imx355_mode *mode; - u32 max; int ret; ctrl_hdlr = &imx355->ctrl_handler; @@ -1596,40 +1042,34 @@ static int imx355_init_controls(struct imx355 *imx355) if (ret) return ret; - ctrl_hdlr->lock = &imx355->mutex; - max = ARRAY_SIZE(link_freq_menu_items) - 1; imx355->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx355_ctrl_ops, - V4L2_CID_LINK_FREQ, max, 0, - link_freq_menu_items); + V4L2_CID_LINK_FREQ, 0, 0, + &imx355->hwcfg->link_freq_menu); if (imx355->link_freq) imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ - pixel_rate = IMX355_LINK_FREQ_DEFAULT * 2 * 4; + pixel_rate = imx355->hwcfg->link_freq_menu * 2 * imx355->hwcfg->num_lanes; do_div(pixel_rate, 10); - /* By default, PIXEL_RATE is read only */ - imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, - V4L2_CID_PIXEL_RATE, pixel_rate, - pixel_rate, 1, pixel_rate); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_PIXEL_RATE, + pixel_rate, pixel_rate, 1, pixel_rate); /* Initialize vblank/hblank/exposure parameters based on current mode */ - mode = imx355->cur_mode; vblank_def = mode->fll_def - mode->height; - vblank_min = mode->fll_min - mode->height; imx355->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, - V4L2_CID_VBLANK, vblank_min, + V4L2_CID_VBLANK, IMX355_VBLANK_MIN, IMX355_FLL_MAX - mode->height, 1, vblank_def); hblank = mode->llp - mode->width; - imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, - V4L2_CID_HBLANK, hblank, hblank, - 1, hblank); + imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, NULL, V4L2_CID_HBLANK, + hblank, hblank, 1, hblank); if (imx355->hblank) imx355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; /* fll >= exposure time + adjust parameter (default value is 10) */ - exposure_max = mode->fll_def - 10; + exposure_max = mode->fll_def - IMX355_EXPOSURE_OFFSET; imx355->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_EXPOSURE, IMX355_EXPOSURE_MIN, exposure_max, @@ -1683,14 +1123,17 @@ error: return ret; } -static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) +static struct imx355_hwcfg *imx355_get_hwcfg(struct imx355 *imx355) { + struct device *dev = imx355->dev; struct imx355_hwcfg *cfg; struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + const struct imx355_clk_params *clk = imx355->clk_params; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); + int lane_idx; int ret; if (!fwnode) @@ -1708,13 +1151,18 @@ static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) if (!cfg) goto out_err; - if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX355_DATA_LANES) + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2 && + bus_cfg.bus.mipi_csi2.num_data_lanes != 4) goto out_err; + cfg->num_lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + + lane_idx = cfg->num_lanes == 4 ? 0 : 1; + cfg->link_freq_menu = (clk->ext_clk * clk->pll_op_mpy[lane_idx]) / + (clk->pll_op_prediv[lane_idx] * 2); ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, bus_cfg.nr_of_link_frequencies, - link_freq_menu_items, - ARRAY_SIZE(link_freq_menu_items), + &cfg->link_freq_menu, 1, &cfg->link_freq_bitmap); if (ret) goto out_err; @@ -1741,7 +1189,10 @@ static int imx355_probe(struct i2c_client *client) imx355->dev = &client->dev; - mutex_init(&imx355->mutex); + imx355->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(imx355->regmap)) + return dev_err_probe(imx355->dev, PTR_ERR(imx355->regmap), + "Unable to initialize I2C\n"); imx355->clk = devm_v4l2_sensor_clk_get(imx355->dev, NULL); if (IS_ERR(imx355->clk)) @@ -1749,7 +1200,13 @@ static int imx355_probe(struct i2c_client *client) "failed to get clock\n"); freq = clk_get_rate(imx355->clk); - if (freq != IMX355_EXT_CLK) + for (unsigned int i = 0; i < ARRAY_SIZE(imx355_clk_params); i++) { + if (freq == imx355_clk_params[i].ext_clk) { + imx355->clk_params = &imx355_clk_params[i]; + break; + } + } + if (!imx355->clk_params) return dev_err_probe(imx355->dev, -EINVAL, "external clock %lu is not supported\n", freq); @@ -1760,7 +1217,7 @@ static int imx355_probe(struct i2c_client *client) &imx355->supplies); if (ret) { dev_err_probe(imx355->dev, ret, "could not get regulators"); - goto error_probe; + return ret; } imx355->reset_gpio = devm_gpiod_get_optional(imx355->dev, "reset", @@ -1768,22 +1225,21 @@ static int imx355_probe(struct i2c_client *client) if (IS_ERR(imx355->reset_gpio)) { ret = dev_err_probe(imx355->dev, PTR_ERR(imx355->reset_gpio), "failed to get gpios"); - goto error_probe; + return ret; } /* Initialize subdev */ v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops); - imx355->hwcfg = imx355_get_hwcfg(imx355->dev); + imx355->hwcfg = imx355_get_hwcfg(imx355); if (!imx355->hwcfg) { dev_err(imx355->dev, "failed to get hwcfg"); - ret = -ENODEV; - goto error_probe; + return -ENODEV; } ret = imx355_power_on(imx355->dev); if (ret) - goto error_probe; + return ret; /* Check module identity */ ret = imx355_identify_module(imx355); @@ -1792,9 +1248,6 @@ static int imx355_probe(struct i2c_client *client) goto error_power_off; } - /* Set default mode to max resolution */ - imx355->cur_mode = &supported_modes[0]; - ret = imx355_init_controls(imx355); if (ret) { dev_err(imx355->dev, "failed to init controls: %d", ret); @@ -1816,23 +1269,36 @@ static int imx355_probe(struct i2c_client *client) goto error_handler_free; } + imx355->sd.state_lock = imx355->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(&imx355->sd); + if (ret < 0) { + dev_err_probe(imx355->dev, ret, "subdev init error\n"); + goto error_media_entity_free; + } + /* * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ pm_runtime_set_active(imx355->dev); pm_runtime_enable(imx355->dev); - pm_runtime_idle(imx355->dev); + pm_runtime_set_autosuspend_delay(imx355->dev, 1000); + pm_runtime_use_autosuspend(imx355->dev); ret = v4l2_async_register_subdev_sensor(&imx355->sd); if (ret < 0) - goto error_media_entity_runtime_pm; + goto error_subdev_cleanup_runtime_pm; + + pm_runtime_idle(imx355->dev); return 0; -error_media_entity_runtime_pm: +error_subdev_cleanup_runtime_pm: pm_runtime_disable(imx355->dev); pm_runtime_set_suspended(imx355->dev); + pm_runtime_dont_use_autosuspend(imx355->dev); + v4l2_subdev_cleanup(&imx355->sd); +error_media_entity_free: media_entity_cleanup(&imx355->sd.entity); error_handler_free: @@ -1841,9 +1307,6 @@ error_handler_free: error_power_off: imx355_power_off(imx355->dev); -error_probe: - mutex_destroy(&imx355->mutex); - return ret; } @@ -1853,6 +1316,7 @@ static void imx355_remove(struct i2c_client *client) struct imx355 *imx355 = to_imx355(sd); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); @@ -1863,7 +1327,7 @@ static void imx355_remove(struct i2c_client *client) pm_runtime_set_suspended(imx355->dev); } - mutex_destroy(&imx355->mutex); + pm_runtime_dont_use_autosuspend(imx355->dev); } static const struct acpi_device_id imx355_acpi_ids[] __maybe_unused = { diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c index 2705af2f16c0..d2760e9e6194 100644 --- a/drivers/media/i2c/imx412.c +++ b/drivers/media/i2c/imx412.c @@ -13,38 +13,39 @@ #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> +#include <media/v4l2-cci.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> /* Streaming Mode */ -#define IMX412_REG_MODE_SELECT 0x0100 +#define IMX412_REG_MODE_SELECT CCI_REG8(0x0100) #define IMX412_MODE_STANDBY 0x00 #define IMX412_MODE_STREAMING 0x01 /* Lines per frame */ -#define IMX412_REG_LPFR 0x0340 +#define IMX412_REG_LPFR CCI_REG16(0x0340) /* Chip ID */ -#define IMX412_REG_ID 0x0016 +#define IMX412_REG_ID CCI_REG16(0x0016) #define IMX412_ID 0x577 /* Exposure control */ -#define IMX412_REG_EXPOSURE_CIT 0x0202 +#define IMX412_REG_EXPOSURE_CIT CCI_REG16(0x0202) #define IMX412_EXPOSURE_MIN 8 #define IMX412_EXPOSURE_OFFSET 22 #define IMX412_EXPOSURE_STEP 1 #define IMX412_EXPOSURE_DEFAULT 0x0648 /* Analog gain control */ -#define IMX412_REG_AGAIN 0x0204 +#define IMX412_REG_AGAIN CCI_REG16(0x0204) #define IMX412_AGAIN_MIN 0 #define IMX412_AGAIN_MAX 978 #define IMX412_AGAIN_STEP 1 #define IMX412_AGAIN_DEFAULT 0 /* Group hold register */ -#define IMX412_REG_HOLD 0x0104 +#define IMX412_REG_HOLD CCI_REG8(0x0104) /* Input clock rate */ #define IMX412_INCLK_RATE 24000000 @@ -57,23 +58,13 @@ #define IMX412_REG_MAX 0xffff /** - * struct imx412_reg - imx412 sensor register - * @address: Register address - * @val: Register value - */ -struct imx412_reg { - u16 address; - u8 val; -}; - -/** * struct imx412_reg_list - imx412 sensor register list * @num_of_regs: Number of registers in the list * @regs: Pointer to register list */ struct imx412_reg_list { u32 num_of_regs; - const struct imx412_reg *regs; + const struct cci_reg_sequence *regs; }; /** @@ -111,6 +102,7 @@ static const char * const imx412_supply_names[] = { /** * struct imx412 - imx412 sensor device structure * @dev: Pointer to generic device + * @cci: CCI register map * @client: Pointer to i2c client * @sd: V4L2 sub-device * @pad: Media pad. Only one pad supported @@ -126,10 +118,10 @@ static const char * const imx412_supply_names[] = { * @again_ctrl: Pointer to analog gain control * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode - * @mutex: Mutex for serializing sensor controls */ struct imx412 { struct device *dev; + struct regmap *cci; struct i2c_client *client; struct v4l2_subdev sd; struct media_pad pad; @@ -147,7 +139,6 @@ struct imx412 { }; u32 vblank; const struct imx412_mode *cur_mode; - struct mutex mutex; }; static const s64 link_freq[] = { @@ -155,238 +146,238 @@ static const s64 link_freq[] = { }; /* Sensor mode registers */ -static const struct imx412_reg mode_4056x3040_regs[] = { - {0x0136, 0x18}, - {0x0137, 0x00}, - {0x3c7e, 0x08}, - {0x3c7f, 0x02}, - {0x38a8, 0x1f}, - {0x38a9, 0xff}, - {0x38aa, 0x1f}, - {0x38ab, 0xff}, - {0x55d4, 0x00}, - {0x55d5, 0x00}, - {0x55d6, 0x07}, - {0x55d7, 0xff}, - {0x55e8, 0x07}, - {0x55e9, 0xff}, - {0x55ea, 0x00}, - {0x55eb, 0x00}, - {0x575c, 0x07}, - {0x575d, 0xff}, - {0x575e, 0x00}, - {0x575f, 0x00}, - {0x5764, 0x00}, - {0x5765, 0x00}, - {0x5766, 0x07}, - {0x5767, 0xff}, - {0x5974, 0x04}, - {0x5975, 0x01}, - {0x5f10, 0x09}, - {0x5f11, 0x92}, - {0x5f12, 0x32}, - {0x5f13, 0x72}, - {0x5f14, 0x16}, - {0x5f15, 0xba}, - {0x5f17, 0x13}, - {0x5f18, 0x24}, - {0x5f19, 0x60}, - {0x5f1a, 0xe3}, - {0x5f1b, 0xad}, - {0x5f1c, 0x74}, - {0x5f2d, 0x25}, - {0x5f5c, 0xd0}, - {0x6a22, 0x00}, - {0x6a23, 0x1d}, - {0x7ba8, 0x00}, - {0x7ba9, 0x00}, - {0x886b, 0x00}, - {0x9002, 0x0a}, - {0x9004, 0x1a}, - {0x9214, 0x93}, - {0x9215, 0x69}, - {0x9216, 0x93}, - {0x9217, 0x6b}, - {0x9218, 0x93}, - {0x9219, 0x6d}, - {0x921a, 0x57}, - {0x921b, 0x58}, - {0x921c, 0x57}, - {0x921d, 0x59}, - {0x921e, 0x57}, - {0x921f, 0x5a}, - {0x9220, 0x57}, - {0x9221, 0x5b}, - {0x9222, 0x93}, - {0x9223, 0x02}, - {0x9224, 0x93}, - {0x9225, 0x03}, - {0x9226, 0x93}, - {0x9227, 0x04}, - {0x9228, 0x93}, - {0x9229, 0x05}, - {0x922a, 0x98}, - {0x922b, 0x21}, - {0x922c, 0xb2}, - {0x922d, 0xdb}, - {0x922e, 0xb2}, - {0x922f, 0xdc}, - {0x9230, 0xb2}, - {0x9231, 0xdd}, - {0x9232, 0xe2}, - {0x9233, 0xe1}, - {0x9234, 0xb2}, - {0x9235, 0xe2}, - {0x9236, 0xb2}, - {0x9237, 0xe3}, - {0x9238, 0xb7}, - {0x9239, 0xb9}, - {0x923a, 0xb7}, - {0x923b, 0xbb}, - {0x923c, 0xb7}, - {0x923d, 0xbc}, - {0x923e, 0xb7}, - {0x923f, 0xc5}, - {0x9240, 0xb7}, - {0x9241, 0xc7}, - {0x9242, 0xb7}, - {0x9243, 0xc9}, - {0x9244, 0x98}, - {0x9245, 0x56}, - {0x9246, 0x98}, - {0x9247, 0x55}, - {0x9380, 0x00}, - {0x9381, 0x62}, - {0x9382, 0x00}, - {0x9383, 0x56}, - {0x9384, 0x00}, - {0x9385, 0x52}, - {0x9388, 0x00}, - {0x9389, 0x55}, - {0x938a, 0x00}, - {0x938b, 0x55}, - {0x938c, 0x00}, - {0x938d, 0x41}, - {0x5078, 0x01}, - {0x0112, 0x0a}, - {0x0113, 0x0a}, - {0x0114, 0x03}, - {0x0342, 0x11}, - {0x0343, 0xa0}, - {0x0340, 0x0d}, - {0x0341, 0xda}, - {0x3210, 0x00}, - {0x0344, 0x00}, - {0x0345, 0x00}, - {0x0346, 0x00}, - {0x0347, 0x00}, - {0x0348, 0x0f}, - {0x0349, 0xd7}, - {0x034a, 0x0b}, - {0x034b, 0xdf}, - {0x00e3, 0x00}, - {0x00e4, 0x00}, - {0x00e5, 0x01}, - {0x00fc, 0x0a}, - {0x00fd, 0x0a}, - {0x00fe, 0x0a}, - {0x00ff, 0x0a}, - {0xe013, 0x00}, - {0x0220, 0x00}, - {0x0221, 0x11}, - {0x0381, 0x01}, - {0x0383, 0x01}, - {0x0385, 0x01}, - {0x0387, 0x01}, - {0x0900, 0x00}, - {0x0901, 0x11}, - {0x0902, 0x00}, - {0x3140, 0x02}, - {0x3241, 0x11}, - {0x3250, 0x03}, - {0x3e10, 0x00}, - {0x3e11, 0x00}, - {0x3f0d, 0x00}, - {0x3f42, 0x00}, - {0x3f43, 0x00}, - {0x0401, 0x00}, - {0x0404, 0x00}, - {0x0405, 0x10}, - {0x0408, 0x00}, - {0x0409, 0x00}, - {0x040a, 0x00}, - {0x040b, 0x00}, - {0x040c, 0x0f}, - {0x040d, 0xd8}, - {0x040e, 0x0b}, - {0x040f, 0xe0}, - {0x034c, 0x0f}, - {0x034d, 0xd8}, - {0x034e, 0x0b}, - {0x034f, 0xe0}, - {0x0301, 0x05}, - {0x0303, 0x02}, - {0x0305, 0x04}, - {0x0306, 0x00}, - {0x0307, 0xc8}, - {0x0309, 0x0a}, - {0x030b, 0x01}, - {0x030d, 0x02}, - {0x030e, 0x01}, - {0x030f, 0x5e}, - {0x0310, 0x00}, - {0x0820, 0x12}, - {0x0821, 0xc0}, - {0x0822, 0x00}, - {0x0823, 0x00}, - {0x3e20, 0x01}, - {0x3e37, 0x00}, - {0x3f50, 0x00}, - {0x3f56, 0x00}, - {0x3f57, 0xe2}, - {0x3c0a, 0x5a}, - {0x3c0b, 0x55}, - {0x3c0c, 0x28}, - {0x3c0d, 0x07}, - {0x3c0e, 0xff}, - {0x3c0f, 0x00}, - {0x3c10, 0x00}, - {0x3c11, 0x02}, - {0x3c12, 0x00}, - {0x3c13, 0x03}, - {0x3c14, 0x00}, - {0x3c15, 0x00}, - {0x3c16, 0x0c}, - {0x3c17, 0x0c}, - {0x3c18, 0x0c}, - {0x3c19, 0x0a}, - {0x3c1a, 0x0a}, - {0x3c1b, 0x0a}, - {0x3c1c, 0x00}, - {0x3c1d, 0x00}, - {0x3c1e, 0x00}, - {0x3c1f, 0x00}, - {0x3c20, 0x00}, - {0x3c21, 0x00}, - {0x3c22, 0x3f}, - {0x3c23, 0x0a}, - {0x3e35, 0x01}, - {0x3f4a, 0x03}, - {0x3f4b, 0xbf}, - {0x3f26, 0x00}, - {0x0202, 0x0d}, - {0x0203, 0xc4}, - {0x0204, 0x00}, - {0x0205, 0x00}, - {0x020e, 0x01}, - {0x020f, 0x00}, - {0x0210, 0x01}, - {0x0211, 0x00}, - {0x0212, 0x01}, - {0x0213, 0x00}, - {0x0214, 0x01}, - {0x0215, 0x00}, - {0xbcf1, 0x00}, +static const struct cci_reg_sequence mode_4056x3040_regs[] = { + { CCI_REG8(0x0136), 0x18 }, + { CCI_REG8(0x0137), 0x00 }, + { CCI_REG8(0x3c7e), 0x08 }, + { CCI_REG8(0x3c7f), 0x02 }, + { CCI_REG8(0x38a8), 0x1f }, + { CCI_REG8(0x38a9), 0xff }, + { CCI_REG8(0x38aa), 0x1f }, + { CCI_REG8(0x38ab), 0xff }, + { CCI_REG8(0x55d4), 0x00 }, + { CCI_REG8(0x55d5), 0x00 }, + { CCI_REG8(0x55d6), 0x07 }, + { CCI_REG8(0x55d7), 0xff }, + { CCI_REG8(0x55e8), 0x07 }, + { CCI_REG8(0x55e9), 0xff }, + { CCI_REG8(0x55ea), 0x00 }, + { CCI_REG8(0x55eb), 0x00 }, + { CCI_REG8(0x575c), 0x07 }, + { CCI_REG8(0x575d), 0xff }, + { CCI_REG8(0x575e), 0x00 }, + { CCI_REG8(0x575f), 0x00 }, + { CCI_REG8(0x5764), 0x00 }, + { CCI_REG8(0x5765), 0x00 }, + { CCI_REG8(0x5766), 0x07 }, + { CCI_REG8(0x5767), 0xff }, + { CCI_REG8(0x5974), 0x04 }, + { CCI_REG8(0x5975), 0x01 }, + { CCI_REG8(0x5f10), 0x09 }, + { CCI_REG8(0x5f11), 0x92 }, + { CCI_REG8(0x5f12), 0x32 }, + { CCI_REG8(0x5f13), 0x72 }, + { CCI_REG8(0x5f14), 0x16 }, + { CCI_REG8(0x5f15), 0xba }, + { CCI_REG8(0x5f17), 0x13 }, + { CCI_REG8(0x5f18), 0x24 }, + { CCI_REG8(0x5f19), 0x60 }, + { CCI_REG8(0x5f1a), 0xe3 }, + { CCI_REG8(0x5f1b), 0xad }, + { CCI_REG8(0x5f1c), 0x74 }, + { CCI_REG8(0x5f2d), 0x25 }, + { CCI_REG8(0x5f5c), 0xd0 }, + { CCI_REG8(0x6a22), 0x00 }, + { CCI_REG8(0x6a23), 0x1d }, + { CCI_REG8(0x7ba8), 0x00 }, + { CCI_REG8(0x7ba9), 0x00 }, + { CCI_REG8(0x886b), 0x00 }, + { CCI_REG8(0x9002), 0x0a }, + { CCI_REG8(0x9004), 0x1a }, + { CCI_REG8(0x9214), 0x93 }, + { CCI_REG8(0x9215), 0x69 }, + { CCI_REG8(0x9216), 0x93 }, + { CCI_REG8(0x9217), 0x6b }, + { CCI_REG8(0x9218), 0x93 }, + { CCI_REG8(0x9219), 0x6d }, + { CCI_REG8(0x921a), 0x57 }, + { CCI_REG8(0x921b), 0x58 }, + { CCI_REG8(0x921c), 0x57 }, + { CCI_REG8(0x921d), 0x59 }, + { CCI_REG8(0x921e), 0x57 }, + { CCI_REG8(0x921f), 0x5a }, + { CCI_REG8(0x9220), 0x57 }, + { CCI_REG8(0x9221), 0x5b }, + { CCI_REG8(0x9222), 0x93 }, + { CCI_REG8(0x9223), 0x02 }, + { CCI_REG8(0x9224), 0x93 }, + { CCI_REG8(0x9225), 0x03 }, + { CCI_REG8(0x9226), 0x93 }, + { CCI_REG8(0x9227), 0x04 }, + { CCI_REG8(0x9228), 0x93 }, + { CCI_REG8(0x9229), 0x05 }, + { CCI_REG8(0x922a), 0x98 }, + { CCI_REG8(0x922b), 0x21 }, + { CCI_REG8(0x922c), 0xb2 }, + { CCI_REG8(0x922d), 0xdb }, + { CCI_REG8(0x922e), 0xb2 }, + { CCI_REG8(0x922f), 0xdc }, + { CCI_REG8(0x9230), 0xb2 }, + { CCI_REG8(0x9231), 0xdd }, + { CCI_REG8(0x9232), 0xe2 }, + { CCI_REG8(0x9233), 0xe1 }, + { CCI_REG8(0x9234), 0xb2 }, + { CCI_REG8(0x9235), 0xe2 }, + { CCI_REG8(0x9236), 0xb2 }, + { CCI_REG8(0x9237), 0xe3 }, + { CCI_REG8(0x9238), 0xb7 }, + { CCI_REG8(0x9239), 0xb9 }, + { CCI_REG8(0x923a), 0xb7 }, + { CCI_REG8(0x923b), 0xbb }, + { CCI_REG8(0x923c), 0xb7 }, + { CCI_REG8(0x923d), 0xbc }, + { CCI_REG8(0x923e), 0xb7 }, + { CCI_REG8(0x923f), 0xc5 }, + { CCI_REG8(0x9240), 0xb7 }, + { CCI_REG8(0x9241), 0xc7 }, + { CCI_REG8(0x9242), 0xb7 }, + { CCI_REG8(0x9243), 0xc9 }, + { CCI_REG8(0x9244), 0x98 }, + { CCI_REG8(0x9245), 0x56 }, + { CCI_REG8(0x9246), 0x98 }, + { CCI_REG8(0x9247), 0x55 }, + { CCI_REG8(0x9380), 0x00 }, + { CCI_REG8(0x9381), 0x62 }, + { CCI_REG8(0x9382), 0x00 }, + { CCI_REG8(0x9383), 0x56 }, + { CCI_REG8(0x9384), 0x00 }, + { CCI_REG8(0x9385), 0x52 }, + { CCI_REG8(0x9388), 0x00 }, + { CCI_REG8(0x9389), 0x55 }, + { CCI_REG8(0x938a), 0x00 }, + { CCI_REG8(0x938b), 0x55 }, + { CCI_REG8(0x938c), 0x00 }, + { CCI_REG8(0x938d), 0x41 }, + { CCI_REG8(0x5078), 0x01 }, + { CCI_REG8(0x0112), 0x0a }, + { CCI_REG8(0x0113), 0x0a }, + { CCI_REG8(0x0114), 0x03 }, + { CCI_REG8(0x0342), 0x11 }, + { CCI_REG8(0x0343), 0xa0 }, + { CCI_REG8(0x0340), 0x0d }, + { CCI_REG8(0x0341), 0xda }, + { CCI_REG8(0x3210), 0x00 }, + { CCI_REG8(0x0344), 0x00 }, + { CCI_REG8(0x0345), 0x00 }, + { CCI_REG8(0x0346), 0x00 }, + { CCI_REG8(0x0347), 0x00 }, + { CCI_REG8(0x0348), 0x0f }, + { CCI_REG8(0x0349), 0xd7 }, + { CCI_REG8(0x034a), 0x0b }, + { CCI_REG8(0x034b), 0xdf }, + { CCI_REG8(0x00e3), 0x00 }, + { CCI_REG8(0x00e4), 0x00 }, + { CCI_REG8(0x00e5), 0x01 }, + { CCI_REG8(0x00fc), 0x0a }, + { CCI_REG8(0x00fd), 0x0a }, + { CCI_REG8(0x00fe), 0x0a }, + { CCI_REG8(0x00ff), 0x0a }, + { CCI_REG8(0xe013), 0x00 }, + { CCI_REG8(0x0220), 0x00 }, + { CCI_REG8(0x0221), 0x11 }, + { CCI_REG8(0x0381), 0x01 }, + { CCI_REG8(0x0383), 0x01 }, + { CCI_REG8(0x0385), 0x01 }, + { CCI_REG8(0x0387), 0x01 }, + { CCI_REG8(0x0900), 0x00 }, + { CCI_REG8(0x0901), 0x11 }, + { CCI_REG8(0x0902), 0x00 }, + { CCI_REG8(0x3140), 0x02 }, + { CCI_REG8(0x3241), 0x11 }, + { CCI_REG8(0x3250), 0x03 }, + { CCI_REG8(0x3e10), 0x00 }, + { CCI_REG8(0x3e11), 0x00 }, + { CCI_REG8(0x3f0d), 0x00 }, + { CCI_REG8(0x3f42), 0x00 }, + { CCI_REG8(0x3f43), 0x00 }, + { CCI_REG8(0x0401), 0x00 }, + { CCI_REG8(0x0404), 0x00 }, + { CCI_REG8(0x0405), 0x10 }, + { CCI_REG8(0x0408), 0x00 }, + { CCI_REG8(0x0409), 0x00 }, + { CCI_REG8(0x040a), 0x00 }, + { CCI_REG8(0x040b), 0x00 }, + { CCI_REG8(0x040c), 0x0f }, + { CCI_REG8(0x040d), 0xd8 }, + { CCI_REG8(0x040e), 0x0b }, + { CCI_REG8(0x040f), 0xe0 }, + { CCI_REG8(0x034c), 0x0f }, + { CCI_REG8(0x034d), 0xd8 }, + { CCI_REG8(0x034e), 0x0b }, + { CCI_REG8(0x034f), 0xe0 }, + { CCI_REG8(0x0301), 0x05 }, + { CCI_REG8(0x0303), 0x02 }, + { CCI_REG8(0x0305), 0x04 }, + { CCI_REG8(0x0306), 0x00 }, + { CCI_REG8(0x0307), 0xc8 }, + { CCI_REG8(0x0309), 0x0a }, + { CCI_REG8(0x030b), 0x01 }, + { CCI_REG8(0x030d), 0x02 }, + { CCI_REG8(0x030e), 0x01 }, + { CCI_REG8(0x030f), 0x5e }, + { CCI_REG8(0x0310), 0x00 }, + { CCI_REG8(0x0820), 0x12 }, + { CCI_REG8(0x0821), 0xc0 }, + { CCI_REG8(0x0822), 0x00 }, + { CCI_REG8(0x0823), 0x00 }, + { CCI_REG8(0x3e20), 0x01 }, + { CCI_REG8(0x3e37), 0x00 }, + { CCI_REG8(0x3f50), 0x00 }, + { CCI_REG8(0x3f56), 0x00 }, + { CCI_REG8(0x3f57), 0xe2 }, + { CCI_REG8(0x3c0a), 0x5a }, + { CCI_REG8(0x3c0b), 0x55 }, + { CCI_REG8(0x3c0c), 0x28 }, + { CCI_REG8(0x3c0d), 0x07 }, + { CCI_REG8(0x3c0e), 0xff }, + { CCI_REG8(0x3c0f), 0x00 }, + { CCI_REG8(0x3c10), 0x00 }, + { CCI_REG8(0x3c11), 0x02 }, + { CCI_REG8(0x3c12), 0x00 }, + { CCI_REG8(0x3c13), 0x03 }, + { CCI_REG8(0x3c14), 0x00 }, + { CCI_REG8(0x3c15), 0x00 }, + { CCI_REG8(0x3c16), 0x0c }, + { CCI_REG8(0x3c17), 0x0c }, + { CCI_REG8(0x3c18), 0x0c }, + { CCI_REG8(0x3c19), 0x0a }, + { CCI_REG8(0x3c1a), 0x0a }, + { CCI_REG8(0x3c1b), 0x0a }, + { CCI_REG8(0x3c1c), 0x00 }, + { CCI_REG8(0x3c1d), 0x00 }, + { CCI_REG8(0x3c1e), 0x00 }, + { CCI_REG8(0x3c1f), 0x00 }, + { CCI_REG8(0x3c20), 0x00 }, + { CCI_REG8(0x3c21), 0x00 }, + { CCI_REG8(0x3c22), 0x3f }, + { CCI_REG8(0x3c23), 0x0a }, + { CCI_REG8(0x3e35), 0x01 }, + { CCI_REG8(0x3f4a), 0x03 }, + { CCI_REG8(0x3f4b), 0xbf }, + { CCI_REG8(0x3f26), 0x00 }, + { CCI_REG8(0x0202), 0x0d }, + { CCI_REG8(0x0203), 0xc4 }, + { CCI_REG8(0x0204), 0x00 }, + { CCI_REG8(0x0205), 0x00 }, + { CCI_REG8(0x020e), 0x01 }, + { CCI_REG8(0x020f), 0x00 }, + { CCI_REG8(0x0210), 0x01 }, + { CCI_REG8(0x0211), 0x00 }, + { CCI_REG8(0x0212), 0x01 }, + { CCI_REG8(0x0213), 0x00 }, + { CCI_REG8(0x0214), 0x01 }, + { CCI_REG8(0x0215), 0x00 }, + { CCI_REG8(0xbcf1), 0x00 }, }; /* Supported sensor mode configurations */ @@ -418,97 +409,6 @@ static inline struct imx412 *to_imx412(struct v4l2_subdev *subdev) } /** - * imx412_read_reg() - Read registers. - * @imx412: pointer to imx412 device - * @reg: register address - * @len: length of bytes to read. Max supported bytes is 4 - * @val: pointer to register value to be filled. - * - * Return: 0 if successful, error code otherwise. - */ -static int imx412_read_reg(struct imx412 *imx412, u16 reg, u32 len, u32 *val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd); - struct i2c_msg msgs[2] = {0}; - u8 addr_buf[2] = {0}; - u8 data_buf[4] = {0}; - int ret; - - if (WARN_ON(len > 4)) - return -EINVAL; - - put_unaligned_be16(reg, addr_buf); - - /* Write register address */ - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = ARRAY_SIZE(addr_buf); - msgs[0].buf = addr_buf; - - /* Read data from register */ - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = len; - msgs[1].buf = &data_buf[4 - len]; - - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (ret != ARRAY_SIZE(msgs)) - return -EIO; - - *val = get_unaligned_be32(data_buf); - - return 0; -} - -/** - * imx412_write_reg() - Write register - * @imx412: pointer to imx412 device - * @reg: register address - * @len: length of bytes. Max supported bytes is 4 - * @val: register value - * - * Return: 0 if successful, error code otherwise. - */ -static int imx412_write_reg(struct imx412 *imx412, u16 reg, u32 len, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&imx412->sd); - u8 buf[6] = {0}; - - if (WARN_ON(len > 4)) - return -EINVAL; - - put_unaligned_be16(reg, buf); - put_unaligned_be32(val << (8 * (4 - len)), buf + 2); - if (i2c_master_send(client, buf, len + 2) != len + 2) - return -EIO; - - return 0; -} - -/** - * imx412_write_regs() - Write a list of registers - * @imx412: pointer to imx412 device - * @regs: list of registers to be written - * @len: length of registers array - * - * Return: 0 if successful, error code otherwise. - */ -static int imx412_write_regs(struct imx412 *imx412, - const struct imx412_reg *regs, u32 len) -{ - unsigned int i; - int ret; - - for (i = 0; i < len; i++) { - ret = imx412_write_reg(imx412, regs[i].address, 1, regs[i].val); - if (ret) - return ret; - } - - return 0; -} - -/** * imx412_update_controls() - Update control ranges based on streaming mode * @imx412: pointer to imx412 device * @mode: pointer to imx412_mode sensor mode @@ -543,29 +443,25 @@ static int imx412_update_controls(struct imx412 *imx412, static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain) { u32 lpfr; - int ret; + int ret = 0; + int ret_hold; lpfr = imx412->vblank + imx412->cur_mode->height; dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u\n", exposure, gain, lpfr); - ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1); - if (ret) - return ret; + cci_write(imx412->cci, IMX412_REG_HOLD, 1, &ret); - ret = imx412_write_reg(imx412, IMX412_REG_LPFR, 2, lpfr); - if (ret) - goto error_release_group_hold; + cci_write(imx412->cci, IMX412_REG_LPFR, lpfr, &ret); - ret = imx412_write_reg(imx412, IMX412_REG_EXPOSURE_CIT, 2, exposure); - if (ret) - goto error_release_group_hold; + cci_write(imx412->cci, IMX412_REG_EXPOSURE_CIT, exposure, &ret); - ret = imx412_write_reg(imx412, IMX412_REG_AGAIN, 2, gain); + cci_write(imx412->cci, IMX412_REG_AGAIN, gain, &ret); -error_release_group_hold: - imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 0); + ret_hold = cci_write(imx412->cci, IMX412_REG_HOLD, 0, NULL); + if (ret_hold) + return ret_hold; return ret; } @@ -679,8 +575,6 @@ static int imx412_get_pad_format(struct v4l2_subdev *sd, { struct imx412 *imx412 = to_imx412(sd); - mutex_lock(&imx412->mutex); - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { struct v4l2_mbus_framefmt *framefmt; @@ -690,8 +584,6 @@ static int imx412_get_pad_format(struct v4l2_subdev *sd, imx412_fill_pad_format(imx412, imx412->cur_mode, fmt); } - mutex_unlock(&imx412->mutex); - return 0; } @@ -703,8 +595,6 @@ static int imx412_set_pad_format(struct v4l2_subdev *sd, const struct imx412_mode *mode; int ret = 0; - mutex_lock(&imx412->mutex); - mode = &supported_mode; imx412_fill_pad_format(imx412, mode, fmt); @@ -719,8 +609,6 @@ static int imx412_set_pad_format(struct v4l2_subdev *sd, imx412->cur_mode = mode; } - mutex_unlock(&imx412->mutex); - return ret; } @@ -737,88 +625,86 @@ static int imx412_init_state(struct v4l2_subdev *sd, } /** - * imx412_start_streaming() - Start sensor stream - * @imx412: pointer to imx412 device + * imx412_enable_streams() - Enable specified streams for the sensor + * @sd: pointer to the V4L2 subdevice + * @state: pointer to the subdevice state + * @pad: pad number for which streams are enabled + * @streams_mask: bitmask specifying the streams to enable * * Return: 0 if successful, error code otherwise. */ -static int imx412_start_streaming(struct imx412 *imx412) +static int imx412_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) { const struct imx412_reg_list *reg_list; + struct imx412 *imx412 = to_imx412(sd); int ret; + ret = pm_runtime_resume_and_get(imx412->dev); + if (ret < 0) + return ret; + /* Write sensor mode registers */ reg_list = &imx412->cur_mode->reg_list; - ret = imx412_write_regs(imx412, reg_list->regs, - reg_list->num_of_regs); + ret = cci_multi_reg_write(imx412->cci, reg_list->regs, + reg_list->num_of_regs, NULL); if (ret) { dev_err(imx412->dev, "fail to write initial registers\n"); - return ret; + goto err_rpm_put; } /* Setup handler will write actual exposure and gain */ ret = __v4l2_ctrl_handler_setup(imx412->sd.ctrl_handler); if (ret) { dev_err(imx412->dev, "fail to setup handler\n"); - return ret; + goto err_rpm_put; } /* Delay is required before streaming*/ usleep_range(7400, 8000); /* Start streaming */ - ret = imx412_write_reg(imx412, IMX412_REG_MODE_SELECT, - 1, IMX412_MODE_STREAMING); + ret = cci_write(imx412->cci, IMX412_REG_MODE_SELECT, + IMX412_MODE_STREAMING, NULL); if (ret) { dev_err(imx412->dev, "fail to start streaming\n"); - return ret; + goto err_rpm_put; } return 0; + +err_rpm_put: + pm_runtime_put(imx412->dev); + + return ret; } /** - * imx412_stop_streaming() - Stop sensor stream - * @imx412: pointer to imx412 device + * imx412_disable_streams() - Enable specified streams for the sensor + * @sd: pointer to the V4L2 subdevice + * @state: pointer to the subdevice state + * @pad: pad number for which streams are disabled + * @streams_mask: bitmask specifying the streams to disable * * Return: 0 if successful, error code otherwise. */ -static int imx412_stop_streaming(struct imx412 *imx412) -{ - return imx412_write_reg(imx412, IMX412_REG_MODE_SELECT, - 1, IMX412_MODE_STANDBY); -} - -static int imx412_set_stream(struct v4l2_subdev *sd, int enable) +static int imx412_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) { struct imx412 *imx412 = to_imx412(sd); int ret; - mutex_lock(&imx412->mutex); + ret = cci_write(imx412->cci, IMX412_REG_MODE_SELECT, + IMX412_MODE_STANDBY, NULL); - if (enable) { - ret = pm_runtime_resume_and_get(imx412->dev); - if (ret) - goto error_unlock; - - ret = imx412_start_streaming(imx412); - if (ret) - goto error_power_off; - } else { - imx412_stop_streaming(imx412); - pm_runtime_put(imx412->dev); - } - - mutex_unlock(&imx412->mutex); - - return 0; + if (ret) + dev_err(imx412->dev, "failed to set stream off\n"); -error_power_off: pm_runtime_put(imx412->dev); -error_unlock: - mutex_unlock(&imx412->mutex); - return ret; + return 0; } /** @@ -830,16 +716,18 @@ error_unlock: static int imx412_detect(struct imx412 *imx412) { int ret; - u32 val; + u64 val; - ret = imx412_read_reg(imx412, IMX412_REG_ID, 2, &val); + ret = cci_read(imx412->cci, IMX412_REG_ID, &val, NULL); if (ret) - return ret; + return dev_err_probe(imx412->dev, ret, + "failed to read chip id %x\n", + IMX412_ID); if (val != IMX412_ID) { - dev_err(imx412->dev, "chip id mismatch: %x!=%x\n", - IMX412_ID, val); - return -ENXIO; + return dev_err_probe(imx412->dev, -ENODEV, + "chip id mismatch: %x!=%llx", + IMX412_ID, val); } return 0; @@ -933,7 +821,7 @@ done_endpoint_free: /* V4l2 subdevice ops */ static const struct v4l2_subdev_video_ops imx412_video_ops = { - .s_stream = imx412_set_stream, + .s_stream = v4l2_subdev_s_stream_helper, }; static const struct v4l2_subdev_pad_ops imx412_pad_ops = { @@ -941,6 +829,8 @@ static const struct v4l2_subdev_pad_ops imx412_pad_ops = { .enum_frame_size = imx412_enum_frame_size, .get_fmt = imx412_get_pad_format, .set_fmt = imx412_set_pad_format, + .enable_streams = imx412_enable_streams, + .disable_streams = imx412_disable_streams, }; static const struct v4l2_subdev_ops imx412_subdev_ops = { @@ -1021,9 +911,6 @@ static int imx412_init_controls(struct imx412 *imx412) if (ret) return ret; - /* Serialize controls with sensor device */ - ctrl_hdlr->lock = &imx412->mutex; - /* Initialize exposure and gain */ lpfr = mode->vblank + mode->height; imx412->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, @@ -1104,6 +991,11 @@ static int imx412_probe(struct i2c_client *client) if (!name) return -ENODEV; + imx412->cci = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(imx412->cci)) + return dev_err_probe(imx412->dev, PTR_ERR(imx412->cci), + "Failed to init CCI\n"); + /* Initialize subdev */ v4l2_i2c_subdev_init(&imx412->sd, client, &imx412_subdev_ops); imx412->sd.internal_ops = &imx412_internal_ops; @@ -1114,13 +1006,10 @@ static int imx412_probe(struct i2c_client *client) return ret; } - mutex_init(&imx412->mutex); - ret = imx412_power_on(imx412->dev); - if (ret) { - dev_err(imx412->dev, "failed to power-on the sensor\n"); - goto error_mutex_destroy; - } + if (ret) + return dev_err_probe(imx412->dev, ret, + "failed to power-on the sensor\n"); /* Check module identity */ ret = imx412_detect(imx412); @@ -1153,27 +1042,37 @@ static int imx412_probe(struct i2c_client *client) goto error_handler_free; } - ret = v4l2_async_register_subdev_sensor(&imx412->sd); + imx412->sd.state_lock = imx412->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(&imx412->sd); if (ret < 0) { - dev_err(imx412->dev, - "failed to register async subdev: %d\n", ret); + dev_err_probe(imx412->dev, ret, "subdev init error\n"); goto error_media_entity; } pm_runtime_set_active(imx412->dev); pm_runtime_enable(imx412->dev); + + ret = v4l2_async_register_subdev_sensor(&imx412->sd); + if (ret < 0) { + dev_err_probe(imx412->dev, ret, + "failed to register sub-device\n"); + goto error_subdev_cleanup; + } + pm_runtime_idle(imx412->dev); return 0; +error_subdev_cleanup: + v4l2_subdev_cleanup(&imx412->sd); + pm_runtime_disable(imx412->dev); + pm_runtime_set_suspended(imx412->dev); error_media_entity: media_entity_cleanup(&imx412->sd.entity); error_handler_free: v4l2_ctrl_handler_free(imx412->sd.ctrl_handler); error_power_off: imx412_power_off(imx412->dev); -error_mutex_destroy: - mutex_destroy(&imx412->mutex); return ret; } @@ -1181,9 +1080,9 @@ error_mutex_destroy: static void imx412_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct imx412 *imx412 = to_imx412(sd); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); @@ -1191,8 +1090,6 @@ static void imx412_remove(struct i2c_client *client) if (!pm_runtime_status_suspended(&client->dev)) imx412_power_off(&client->dev); pm_runtime_set_suspended(&client->dev); - - mutex_destroy(&imx412->mutex); } static const struct dev_pm_ops imx412_pm_ops = { diff --git a/drivers/media/i2c/imx471.c b/drivers/media/i2c/imx471.c new file mode 100644 index 000000000000..6d358b11e96d --- /dev/null +++ b/drivers/media/i2c/imx471.c @@ -0,0 +1,957 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * imx471.c - imx471 sensor driver + * + * Copyright (C) 2025 Intel Corporation + * Copyright (C) 2026 Kate Hsuan <hpa@redhat.com> + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <media/v4l2-cci.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-fwnode.h> + +#define IMX471_REG_MODE_SELECT CCI_REG8(0x0100) +#define IMX471_MODE_STANDBY 0x00 +#define IMX471_MODE_STREAMING 0x01 + +/* Chip ID */ +#define IMX471_REG_CHIP_ID CCI_REG16(0x0016) +#define IMX471_CHIP_ID 0x0471 + +/* V_TIMING internal */ +#define IMX471_REG_FLL CCI_REG16(0x0340) +#define IMX471_FLL_MAX 0xffff + +/* Exposure control */ +#define IMX471_REG_EXPOSURE CCI_REG16(0x0202) +#define IMX471_EXPOSURE_MIN 1 +#define IMX471_EXPOSURE_STEP 1 +#define IMX471_EXPOSURE_DEFAULT 1270 + +/* Default exposure margin */ +#define IMX471_EXPOSURE_MARGIN 18 + +/* Analog gain control */ +#define IMX471_REG_ANALOG_GAIN CCI_REG16(0x0204) +#define IMX471_ANA_GAIN_MIN 0 +#define IMX471_ANA_GAIN_MAX 800 +#define IMX471_ANA_GAIN_STEP 1 +#define IMX471_ANA_GAIN_DEFAULT 0 + +/* Digital gain control */ +#define IMX471_REG_DPGA_USE_GLOBAL_GAIN CCI_REG16(0x3ff9) +#define IMX471_REG_DIG_GAIN_GLOBAL CCI_REG16(0x020e) +#define IMX471_DGTL_GAIN_MIN 256 +#define IMX471_DGTL_GAIN_MAX 4095 +#define IMX471_DGTL_GAIN_STEP 1 +#define IMX471_DGTL_GAIN_DEFAULT 256 + +/* HFLIP and VFLIP control */ +#define IMX471_REG_ORIENTATION CCI_REG8(0x0101) + +/* Test Pattern Control */ +#define IMX471_REG_TEST_PATTERN CCI_REG8(0x0600) + +/* default link frequency and external clock */ +#define IMX471_LINK_FREQ_DEFAULT 200000000LL +#define IMX471_EXT_CLK 19200000 + +/* PLL */ +#define IMX471_REG_VTPXCK_DIV CCI_REG8(0x0301) +#define IMX471_REG_VTSYCK_DIV CCI_REG8(0x0303) +#define IMX471_REG_PREPLLCK_VT_DIV CCI_REG8(0x0305) +#define IMX471_REG_PLL_VT_MPY CCI_REG16(0x0306) +#define IMX471_REG_OPPXCK_DIV CCI_REG8(0x0309) +#define IMX471_REG_OPSYCK_DIV CCI_REG8(0x030b) +#define IMX471_REG_PLL_MULT_DRIV CCI_REG8(0x0310) +#define IMX471_PLL_SINGLE 0 +#define IMX471_PLL_DUAL 1 + +/* IMX471 native and active pixel array size */ +#define IMX471_NATIVE_WIDTH 4672 +#define IMX471_NATIVE_HEIGHT 3512 +#define IMX471_PIXEL_ARRAY_LEFT 8 +#define IMX471_PIXEL_ARRAY_TOP 8 +#define IMX471_PIXEL_ARRAY_WIDTH 4656 +#define IMX471_PIXEL_ARRAY_HEIGHT 3496 + +#define IMX471_REG_EXCK_FREQ CCI_REG16(0x0136) + +#define IMX471_REG_CSI_DATA_FORMAT CCI_REG16(0x0112) +#define IMX471_CSI_DATA_FORMAT_RAW10 0x0a0a + +#define IMX471_REG_CSI_LANE_MODE CCI_REG8(0x0114) +#define IMX471_CSI_2_LANE_MODE 1 +#define IMX471_CSI_4_LANE_MODE 3 + +#define IMX471_REG_X_ADD_STA CCI_REG16(0x0344) +#define IMX471_REG_Y_ADD_STA CCI_REG16(0x0346) +#define IMX471_REG_X_ADD_END CCI_REG16(0x0348) +#define IMX471_REG_Y_ADD_END CCI_REG16(0x034a) +#define IMX471_REG_X_OUTPUT_SIZE CCI_REG16(0x034c) +#define IMX471_REG_Y_OUTPUT_SIZE CCI_REG16(0x034e) +#define IMX471_REG_X_EVEN_INC CCI_REG8(0x0381) +#define IMX471_REG_X_ODD_INC CCI_REG8(0x0383) +#define IMX471_REG_Y_EVEN_INC CCI_REG8(0x0385) +#define IMX471_REG_Y_ODD_INC CCI_REG8(0x0387) + +#define IMX471_REG_DIG_CROP_X_OFFSET CCI_REG16(0x0408) +#define IMX471_REG_DIG_CROP_Y_OFFSET CCI_REG16(0x040a) +#define IMX471_REG_DIG_CROP_WIDTH CCI_REG16(0x040c) +#define IMX471_REG_DIG_CROP_HEIGHT CCI_REG16(0x040e) + +/* Binning mode */ +#define IMX471_REG_BINNING_MODE CCI_REG8(0x0900) +#define IMX471_BINNING_NONE 0 +#define IMX471_BINNING_ENABLE 1 +#define IMX471_REG_BINNING_TYPE CCI_REG8(0x0901) +#define IMX471_REG_BINNING_WEIGHTING CCI_REG8(0x0902) + +#define to_imx471(_sd) container_of_const(_sd, struct imx471, sd) + +static const char * const imx471_supply_name[] = { + "vana", +}; + +struct imx471_mode { + u32 width; + u32 height; + + /* V-timing */ + u32 fll_def; + u32 fll_min; + + /* H-timing */ + u32 llp; + + const struct cci_reg_sequence *default_mode_regs; + unsigned int default_mode_regs_length; +}; + +struct imx471 { + struct v4l2_subdev sd; + struct media_pad pad; + + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *exposure; + + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[ARRAY_SIZE(imx471_supply_name)]; + struct clk *img_clk; + + struct device *dev; + struct regmap *regmap; +}; + +static const struct cci_reg_sequence imx471_global_regs[] = { + { IMX471_REG_EXCK_FREQ, 0x1333 }, + { CCI_REG8(0x3c7e), 0x08 }, + { CCI_REG8(0x3c7f), 0x05 }, + { CCI_REG8(0x3e35), 0x00 }, + { CCI_REG8(0x3e36), 0x00 }, + { CCI_REG8(0x3e37), 0x00 }, + { CCI_REG8(0x3f7f), 0x01 }, + { CCI_REG8(0x4431), 0x04 }, + { CCI_REG8(0x531c), 0x01 }, + { CCI_REG8(0x531d), 0x02 }, + { CCI_REG8(0x531e), 0x04 }, + { CCI_REG8(0x5928), 0x00 }, + { CCI_REG8(0x5929), 0x2f }, + { CCI_REG8(0x592a), 0x00 }, + { CCI_REG8(0x592b), 0x85 }, + { CCI_REG8(0x592c), 0x00 }, + { CCI_REG8(0x592d), 0x32 }, + { CCI_REG8(0x592e), 0x00 }, + { CCI_REG8(0x592f), 0x88 }, + { CCI_REG8(0x5930), 0x00 }, + { CCI_REG8(0x5931), 0x3d }, + { CCI_REG8(0x5932), 0x00 }, + { CCI_REG8(0x5933), 0x93 }, + { CCI_REG8(0x5938), 0x00 }, + { CCI_REG8(0x5939), 0x24 }, + { CCI_REG8(0x593a), 0x00 }, + { CCI_REG8(0x593b), 0x7a }, + { CCI_REG8(0x593c), 0x00 }, + { CCI_REG8(0x593d), 0x24 }, + { CCI_REG8(0x593e), 0x00 }, + { CCI_REG8(0x593f), 0x7a }, + { CCI_REG8(0x5940), 0x00 }, + { CCI_REG8(0x5941), 0x2f }, + { CCI_REG8(0x5942), 0x00 }, + { CCI_REG8(0x5943), 0x85 }, + { CCI_REG8(0x5f0e), 0x6e }, + { CCI_REG8(0x5f11), 0xc6 }, + { CCI_REG8(0x5f17), 0x5e }, + { CCI_REG8(0x7990), 0x01 }, + { CCI_REG8(0x7993), 0x5d }, + { CCI_REG8(0x7994), 0x5d }, + { CCI_REG8(0x7995), 0xa1 }, + { CCI_REG8(0x799a), 0x01 }, + { CCI_REG8(0x799d), 0x00 }, + { CCI_REG8(0x8169), 0x01 }, + { CCI_REG8(0x8359), 0x01 }, + { CCI_REG8(0x9302), 0x1e }, + { CCI_REG8(0x9306), 0x1f }, + { CCI_REG8(0x930a), 0x26 }, + { CCI_REG8(0x930e), 0x23 }, + { CCI_REG8(0x9312), 0x23 }, + { CCI_REG8(0x9316), 0x2c }, + { CCI_REG8(0x9317), 0x19 }, + { CCI_REG8(0xb046), 0x01 }, + { CCI_REG8(0xb048), 0x01 }, +}; + +static const struct cci_reg_sequence mode_1928x1088_regs[] = { + { IMX471_REG_CSI_DATA_FORMAT, IMX471_CSI_DATA_FORMAT_RAW10 }, + { IMX471_REG_CSI_LANE_MODE, IMX471_CSI_4_LANE_MODE }, + { IMX471_REG_X_ADD_STA, 8 }, + { IMX471_REG_Y_ADD_STA, 408 }, + { IMX471_REG_X_ADD_END, 4647 }, + { IMX471_REG_Y_ADD_END, 3051 }, + { IMX471_REG_X_EVEN_INC, 1 }, + { IMX471_REG_X_ODD_INC, 1 }, + { IMX471_REG_Y_EVEN_INC, 1 }, + { IMX471_REG_Y_ODD_INC, 1 }, + { IMX471_REG_BINNING_MODE, IMX471_BINNING_ENABLE }, + { IMX471_REG_BINNING_TYPE, 0x22 }, + { IMX471_REG_BINNING_WEIGHTING, 0x08 }, + { IMX471_REG_DIG_CROP_X_OFFSET, 208 }, + { IMX471_REG_DIG_CROP_Y_OFFSET, 108 }, + { IMX471_REG_DIG_CROP_WIDTH, 1928 }, + { IMX471_REG_DIG_CROP_HEIGHT, 1088 }, + { IMX471_REG_X_OUTPUT_SIZE, 1928 }, + { IMX471_REG_Y_OUTPUT_SIZE, 1088 }, + { IMX471_REG_VTPXCK_DIV, 0x06 }, + { IMX471_REG_VTSYCK_DIV, 0x02 }, + { IMX471_REG_PREPLLCK_VT_DIV, 0x02 }, + { IMX471_REG_PLL_VT_MPY, 0x0079 }, + { IMX471_REG_OPSYCK_DIV, 0x01 }, + { CCI_REG8(0x030d), 0x02 }, + { CCI_REG8(0x030e), 0x00 }, + { CCI_REG8(0x030f), 0x53 }, + { IMX471_REG_PLL_MULT_DRIV, IMX471_PLL_DUAL }, + { CCI_REG8(0x3f4c), 0x81 }, + { CCI_REG8(0x3f4d), 0x81 }, + { CCI_REG8(0x3f78), 0x01 }, + { CCI_REG8(0x3f79), 0x31 }, + { CCI_REG8(0x3ffe), 0x00 }, + { CCI_REG8(0x3fff), 0x8a }, + { CCI_REG8(0x5f0a), 0xb6 }, +}; + +static const char * const imx471_test_pattern_menu[] = { + "Disabled", + "Solid Colour", + "Eight Vertical Colour Bars", + "Colour Bars With Fade to Grey", + "Pseudorandom Sequence (PN9)", +}; + +static const s64 link_freq_menu_items[] = { + IMX471_LINK_FREQ_DEFAULT, +}; + +/* + * The Bayer formats for the flipping. + * - no flip + * - h flip + * - v flip + * - h and v flips + */ +static const u32 imx471_hv_flips_bayer_order[] = { + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SBGGR10_1X10, +}; + +static const struct imx471_mode imx471_modes[] = { + { + .width = 1928, + .height = 1088, + .fll_def = 1308, + .fll_min = 1308, + .llp = 2328, + .default_mode_regs = mode_1928x1088_regs, + .default_mode_regs_length = ARRAY_SIZE(mode_1928x1088_regs), + }, +}; + +static int imx471_get_regulators(struct device *dev, struct imx471 *sensor) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(imx471_supply_name); i++) + sensor->supplies[i].supply = imx471_supply_name[i]; + + return devm_regulator_bulk_get(dev, ARRAY_SIZE(imx471_supply_name), + sensor->supplies); +} + +static int imx471_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx471 *sensor = container_of_const(ctrl->handler, + struct imx471, + ctrl_handler); + struct v4l2_subdev_state *state = + v4l2_subdev_get_locked_active_state(&sensor->sd); + const struct v4l2_mbus_framefmt *format = + v4l2_subdev_state_get_format(state, 0); + int ret; + + if (ctrl->id == V4L2_CID_VBLANK) { + s64 exposure_max = format->height + ctrl->val - + IMX471_EXPOSURE_MARGIN; + ret = __v4l2_ctrl_modify_range(sensor->exposure, + sensor->exposure->minimum, + exposure_max, + sensor->exposure->step, + exposure_max); + if (ret) + return ret; + } + + if (!pm_runtime_get_if_in_use(sensor->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = cci_write(sensor->regmap, IMX471_REG_ANALOG_GAIN, + ctrl->val, NULL); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = cci_write(sensor->regmap, IMX471_REG_DIG_GAIN_GLOBAL, + ctrl->val, NULL); + break; + case V4L2_CID_EXPOSURE: + ret = cci_write(sensor->regmap, IMX471_REG_EXPOSURE, + ctrl->val, &ret); + break; + case V4L2_CID_VBLANK: + /* Update FLL that meets expected vertical blanking */ + ret = cci_write(sensor->regmap, IMX471_REG_FLL, + format->height + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN: + ret = cci_write(sensor->regmap, IMX471_REG_TEST_PATTERN, + ctrl->val, NULL); + break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + ret = cci_write(sensor->regmap, IMX471_REG_ORIENTATION, + sensor->hflip->val | sensor->vflip->val << 1, + NULL); + break; + default: + ret = -EINVAL; + dev_err(sensor->dev, "ctrl(id:0x%x,val:0x%x) is not handled\n", + ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(sensor->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops imx471_ctrl_ops = { + .s_ctrl = imx471_set_ctrl, +}; + +static u32 imx471_get_format_code(struct imx471 *sensor) +{ + unsigned int i; + + i = (sensor->vflip->val ? 2 : 0) | (sensor->hflip->val ? 1 : 0); + + return imx471_hv_flips_bayer_order[i]; +} + +static int imx471_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct imx471 *sensor = to_imx471(sd); + + if (code->index >= (ARRAY_SIZE(imx471_hv_flips_bayer_order) / 4)) + return -EINVAL; + + code->code = imx471_get_format_code(sensor); + + return 0; +} + +static int imx471_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(imx471_modes)) + return -EINVAL; + + fse->min_width = imx471_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = imx471_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static void imx471_update_pad_format(struct imx471 *sensor, + const struct imx471_mode *mode, + struct v4l2_subdev_format *fmt) +{ + fmt->format.code = imx471_get_format_code(sensor); + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.field = V4L2_FIELD_NONE; +} + +static int imx471_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct imx471 *sensor = to_imx471(sd); + const struct imx471_mode *mode; + int h_blank, ret; + + mode = v4l2_find_nearest_size(imx471_modes, ARRAY_SIZE(imx471_modes), + width, height, fmt->format.width, + fmt->format.height); + + imx471_update_pad_format(sensor, mode, fmt); + + *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + return 0; + + if (media_entity_is_streaming(&sensor->sd.entity)) + return -EBUSY; + + ret = __v4l2_ctrl_modify_range(sensor->vblank, + mode->fll_min - mode->height, + IMX471_FLL_MAX - mode->height, + 1, + mode->fll_def - mode->height); + if (ret) + return ret; + + h_blank = mode->llp - mode->width; + /* + * Currently hblank is not changeable. + * So FPS control is done only by vblank. + */ + return __v4l2_ctrl_modify_range(sensor->hblank, h_blank, + h_blank, 1, h_blank); +} + +static int imx471_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_selection *sel) +{ + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad); + break; + + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = IMX471_NATIVE_WIDTH; + sel->r.height = IMX471_NATIVE_HEIGHT; + return 0; + + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = IMX471_PIXEL_ARRAY_TOP; + sel->r.left = IMX471_PIXEL_ARRAY_LEFT; + sel->r.width = IMX471_PIXEL_ARRAY_WIDTH; + sel->r.height = IMX471_PIXEL_ARRAY_HEIGHT; + return 0; + } + + return -EINVAL; +} + +static int imx471_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .format = { + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .width = imx471_modes[0].width, + .height = imx471_modes[0].height, + }, + }; + + return imx471_set_pad_format(sd, sd_state, &fmt); +} + +static int imx471_identify_module(struct imx471 *sensor) +{ + int ret; + u64 val; + + ret = cci_read(sensor->regmap, IMX471_REG_CHIP_ID, &val, NULL); + if (ret) + return dev_err_probe(sensor->dev, ret, + "failed to read chip id\n"); + + if (val != IMX471_CHIP_ID) + return dev_err_probe(sensor->dev, -EIO, + "chip id mismatch: %x!=%llx\n", + IMX471_CHIP_ID, val); + + return 0; +} + +static int imx471_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct imx471 *sensor = to_imx471(sd); + + clk_disable_unprepare(sensor->img_clk); + gpiod_set_value_cansleep(sensor->reset_gpio, 1); + + regulator_bulk_disable(ARRAY_SIZE(imx471_supply_name), + sensor->supplies); + + return 0; +} + +static int imx471_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct imx471 *sensor = to_imx471(sd); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(imx471_supply_name), + sensor->supplies); + if (ret < 0) { + dev_err(dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(sensor->img_clk); + if (ret < 0) { + regulator_bulk_disable(ARRAY_SIZE(imx471_supply_name), + sensor->supplies); + dev_err(dev, "failed to enable imaging clock: %d\n", ret); + return ret; + } + + gpiod_set_value_cansleep(sensor->reset_gpio, 0); + + usleep_range(10000, 15000); + + return 0; +} + +static int imx471_enable_stream(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct imx471 *sensor = to_imx471(sd); + const struct imx471_mode *mode; + struct v4l2_mbus_framefmt *fmt; + int ret; + + ret = pm_runtime_resume_and_get(sensor->dev); + if (ret) + return ret; + + ret = imx471_identify_module(sensor); + if (ret) + goto error_powerdown; + + ret = cci_multi_reg_write(sensor->regmap, imx471_global_regs, + ARRAY_SIZE(imx471_global_regs), NULL); + if (ret) { + dev_err(sensor->dev, "failed to set global settings: %d\n", + ret); + goto error_powerdown; + } + + fmt = v4l2_subdev_state_get_format(state, 0); + mode = v4l2_find_nearest_size(imx471_modes, ARRAY_SIZE(imx471_modes), + width, height, fmt->width, fmt->height); + + ret = cci_multi_reg_write(sensor->regmap, mode->default_mode_regs, + mode->default_mode_regs_length, NULL); + if (ret) { + dev_err(sensor->dev, "failed to set mode: %d\n", ret); + goto error_powerdown; + } + + ret = cci_write(sensor->regmap, IMX471_REG_DPGA_USE_GLOBAL_GAIN, 1, + NULL); + if (ret) + goto error_powerdown; + + ret = __v4l2_ctrl_handler_setup(&sensor->ctrl_handler); + if (ret) + goto error_powerdown; + + ret = cci_write(sensor->regmap, IMX471_REG_MODE_SELECT, + IMX471_MODE_STREAMING, NULL); + if (ret) + goto error_powerdown; + + __v4l2_ctrl_grab(sensor->vflip, true); + __v4l2_ctrl_grab(sensor->hflip, true); + + return ret; + +error_powerdown: + pm_runtime_put(sensor->dev); + + return ret; +} + +static int imx471_disable_stream(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct imx471 *sensor = to_imx471(sd); + int ret; + + ret = cci_write(sensor->regmap, IMX471_REG_MODE_SELECT, + IMX471_MODE_STANDBY, NULL); + pm_runtime_put(sensor->dev); + + if (ret) + dev_err(sensor->dev, + "failed to disable stream with return value: %d\n", + ret); + + __v4l2_ctrl_grab(sensor->vflip, false); + __v4l2_ctrl_grab(sensor->hflip, false); + + return 0; +} + +static const struct v4l2_subdev_video_ops imx471_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops imx471_pad_ops = { + .enum_mbus_code = imx471_enum_mbus_code, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = imx471_set_pad_format, + .get_selection = imx471_get_selection, + .enum_frame_size = imx471_enum_frame_size, + .enable_streams = imx471_enable_stream, + .disable_streams = imx471_disable_stream, +}; + +static const struct v4l2_subdev_ops imx471_subdev_ops = { + .video = &imx471_video_ops, + .pad = &imx471_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops imx471_internal_ops = { + .init_state = imx471_init_state, +}; + +static int imx471_init_controls(struct imx471 *sensor) +{ + const struct imx471_mode *mode = &imx471_modes[0]; + struct v4l2_fwnode_device_properties props; + struct v4l2_ctrl_handler *ctrl_hdlr; + struct v4l2_ctrl *link_freq; + s64 exposure_max, hblank; + u64 pixel_rate; + int ret; + + ret = v4l2_fwnode_device_parse(sensor->dev, &props); + if (ret) { + dev_err(sensor->dev, "failed to parse fwnode: %d\n", ret); + return ret; + } + + ctrl_hdlr = &sensor->ctrl_handler; + v4l2_ctrl_handler_init(ctrl_hdlr, 12); + + v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx471_ctrl_ops, &props); + + link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, + &imx471_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq_menu_items) - 1, + 0, + link_freq_menu_items); + + /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ + pixel_rate = div_u64(IMX471_LINK_FREQ_DEFAULT * 2 * 4, 10); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_PIXEL_RATE, pixel_rate, + pixel_rate, 1, pixel_rate); + + sensor->vblank = v4l2_ctrl_new_std(ctrl_hdlr, + &imx471_ctrl_ops, + V4L2_CID_VBLANK, + mode->fll_min - mode->height, + IMX471_FLL_MAX - mode->height, + 1, + mode->fll_def - mode->height); + + hblank = mode->llp - mode->width; + sensor->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_HBLANK, hblank, hblank, + 1, hblank); + + /* fll >= exposure time + adjust parameter (default value is 18) */ + exposure_max = mode->fll_def - IMX471_EXPOSURE_MARGIN; + sensor->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX471_EXPOSURE_MIN, exposure_max, + IMX471_EXPOSURE_STEP, + IMX471_EXPOSURE_DEFAULT); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + IMX471_ANA_GAIN_MIN, IMX471_ANA_GAIN_MAX, + IMX471_ANA_GAIN_STEP, IMX471_ANA_GAIN_DEFAULT); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + IMX471_DGTL_GAIN_MIN, IMX471_DGTL_GAIN_MAX, + IMX471_DGTL_GAIN_STEP, IMX471_DGTL_GAIN_DEFAULT); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx471_test_pattern_menu) - 1, + 0, 0, imx471_test_pattern_menu); + + sensor->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + + sensor->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx471_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + if (ctrl_hdlr->error) { + dev_err(sensor->dev, "%s control init failed: %d\n", + __func__, ctrl_hdlr->error); + goto error; + } + + link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + sensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + sensor->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + sensor->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + + sensor->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +error: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ctrl_hdlr->error; +} + +static int imx471_check_hwcfg(struct imx471 *sensor) +{ + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct fwnode_handle *ep, *fwnode = dev_fwnode(sensor->dev); + unsigned long link_freq_bitmap; + struct clk *clk; + int ret; + + clk = devm_v4l2_sensor_clk_get(sensor->dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(sensor->dev, PTR_ERR(clk), + "can't get clock frequency\n"); + + if (clk_get_rate(clk) != IMX471_EXT_CLK) + return dev_err_probe(sensor->dev, -EINVAL, + "external clock %lu is not supported\n", + clk_get_rate(clk)); + + ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0, 0); + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return dev_err_probe(sensor->dev, ret, + "parsing endpoint failed\n"); + + if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) { + ret = dev_err_probe(sensor->dev, -EINVAL, + "number of CSI2 data lanes %u is not supported\n", + bus_cfg.bus.mipi_csi2.num_data_lanes); + goto done_endpoint_free; + } + + ret = v4l2_link_freq_to_bitmap(sensor->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq_menu_items, + ARRAY_SIZE(link_freq_menu_items), + &link_freq_bitmap); + +done_endpoint_free: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int imx471_probe(struct i2c_client *client) +{ + struct imx471 *sensor; + int ret; + + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return dev_err_probe(&client->dev, -ENOMEM, + "failed to allocate memory\n"); + + sensor->dev = &client->dev; + + ret = imx471_check_hwcfg(sensor); + if (ret) + return dev_err_probe(sensor->dev, ret, + "failed to check hwcfg: %d\n", ret); + + ret = imx471_get_regulators(sensor->dev, sensor); + if (ret) + return dev_err_probe(sensor->dev, ret, + "failed to get regulators\n"); + + sensor->reset_gpio = devm_gpiod_get_optional(sensor->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(sensor->reset_gpio)) + return dev_err_probe(sensor->dev, PTR_ERR(sensor->reset_gpio), + "failed to get reset gpio\n"); + + sensor->img_clk = devm_v4l2_sensor_clk_get(sensor->dev, NULL); + if (IS_ERR(sensor->img_clk)) + return dev_err_probe(sensor->dev, PTR_ERR(sensor->img_clk), + "failed to get imaging clock\n"); + + v4l2_i2c_subdev_init(&sensor->sd, client, &imx471_subdev_ops); + + sensor->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(sensor->regmap)) + return dev_err_probe(sensor->dev, PTR_ERR(sensor->regmap), + "failed to initialize CCI\n"); + + ret = imx471_power_on(sensor->dev); + if (ret) + return dev_err_probe(sensor->dev, ret, + "failed to power on\n"); + + ret = imx471_identify_module(sensor); + if (ret) { + dev_err_probe(sensor->dev, ret, "failed to find sensor: %d\n", + ret); + goto error_power_off; + } + + ret = imx471_init_controls(sensor); + if (ret) { + dev_err_probe(sensor->dev, ret, "failed to init controls: %d\n", + ret); + goto error_power_off; + } + + sensor->sd.internal_ops = &imx471_internal_ops; + sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sensor->pad.flags = MEDIA_PAD_FL_SOURCE; + sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); + if (ret) { + dev_err_probe(sensor->dev, ret, + "failed to init entity pads: %d\n", ret); + goto error_v4l2_ctrl_handler_free; + } + + sensor->sd.state_lock = sensor->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(&sensor->sd); + if (ret < 0) { + dev_err_probe(sensor->dev, ret, "failed to init subdev: %d\n", + ret); + goto error_media_entity_pm; + } + + pm_runtime_set_active(sensor->dev); + pm_runtime_enable(sensor->dev); + + ret = v4l2_async_register_subdev_sensor(&sensor->sd); + if (ret < 0) + goto error_v4l2_subdev_cleanup; + + pm_runtime_idle(sensor->dev); + + return 0; + +error_v4l2_subdev_cleanup: + pm_runtime_disable(sensor->dev); + pm_runtime_set_suspended(sensor->dev); + v4l2_subdev_cleanup(&sensor->sd); + +error_media_entity_pm: + media_entity_cleanup(&sensor->sd.entity); + +error_v4l2_ctrl_handler_free: + v4l2_ctrl_handler_free(sensor->sd.ctrl_handler); + +error_power_off: + imx471_power_off(sensor->dev); + + return ret; +} + +static void imx471_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + + pm_runtime_disable(&client->dev); + + if (!pm_runtime_status_suspended(&client->dev)) { + imx471_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + } +} + +static DEFINE_RUNTIME_DEV_PM_OPS(imx471_pm_ops, imx471_power_off, + imx471_power_on, NULL); + +static const struct acpi_device_id imx471_acpi_ids[] __maybe_unused = { + { "SONY471A" }, + { "TBE20A0" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, imx471_acpi_ids); + +static struct i2c_driver imx471_i2c_driver = { + .driver = { + .name = "imx471", + .acpi_match_table = ACPI_PTR(imx471_acpi_ids), + .pm = pm_sleep_ptr(&imx471_pm_ops), + }, + .probe = imx471_probe, + .remove = imx471_remove, +}; +module_i2c_driver(imx471_i2c_driver); + +MODULE_AUTHOR("Jimmy Su <jimmy.su@intel.com>"); +MODULE_AUTHOR("Serin Yeh <serin.yeh@intel.com>"); +MODULE_AUTHOR("Kate Hsuan <hpa@redhat.com>"); +MODULE_DESCRIPTION("Sony imx471 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/imx678.c b/drivers/media/i2c/imx678.c new file mode 100644 index 000000000000..0efbf43d2fe6 --- /dev/null +++ b/drivers/media/i2c/imx678.c @@ -0,0 +1,1447 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * V4L2 driver for Sony IMX678 + * + * Diagonal 8.86 mm (Type 1/1.8) CMOS image sensor with 8.40 M effective pixels. + * + * Copyright (C) 2026 Ideas On Board Oy. + * + * Based on Sony IMX678 driver prepared by Will Whang & Soho Enterprise Ltd. + */ +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/media-bus-format.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> +#include <media/v4l2-cci.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> +#include <media/v4l2-mediabus.h> +#include <media/v4l2-rect.h> +#include <media/v4l2-subdev.h> + +/* Standby or streaming mode */ +#define IMX678_REG_MODE_SELECT CCI_REG8(0x3000) +#define IMX678_MODE_STANDBY 0x01 +#define IMX678_MODE_STREAMING 0x00 +#define IMX678_STREAM_DELAY_US 25000 +#define IMX678_STREAM_DELAY_RANGE_US 1000 + +/* XVS/XHS sync control */ +#define IMX678_REG_XMSTA CCI_REG8(0x3002) +#define IMX678_REG_XXS_DRV CCI_REG8(0x30a6) +#define IMX678_REG_XXS_OUTSEL CCI_REG8(0x30a4) + +/* Clk selection */ +#define IMX678_REG_INCK_SEL CCI_REG8(0x3014) + +/* Link Speed */ +#define IMX678_REG_DATARATE_SEL CCI_REG8(0x3015) + +/* Lane Count */ +#define IMX678_REG_LANEMODE CCI_REG8(0x3040) + +/* + * The internal readout clock runs at 74.25 MHz. In one cycle the AD reads 8 + * pixels, thus giving us a rate of 74.25 * 8 = 594 MPix/s + */ +#define IMX678_PIXEL_RATE 594000000 +#define IMX678_PIX_PER_CLK 8 + +/* VMAX - Frame Length in Lines */ +#define IMX678_REG_VMAX CCI_REG24_LE(0x3028) +#define IMX678_VMAX_MAX 0xfffff +#define IMX678_VMAX_DEFAULT 2250 + +/* HMAX - Line Length in Cycles (8 Pixels) */ +#define IMX678_REG_HMAX CCI_REG16_LE(0x302c) +#define IMX678_HMAX_MAX 0xffff + +/* SHR internal */ +#define IMX678_REG_SHR CCI_REG24_LE(0x3050) +#define IMX678_SHR_MIN 8 + +/* Exposure control */ +#define IMX678_EXPOSURE_MIN 2 +#define IMX678_EXPOSURE_STEP 1 +#define IMX678_EXPOSURE_DEFAULT 1000 + +/* + * Analogue gain control + * Range is from 0 to 100 (0dB - 30dB) with 0.3dB step size + * Values from 101 to 240 are valid but correspond to additional digital gain + * (0.3dB - 42dB) so don't expose it to userspace + */ +#define IMX678_REG_GAIN CCI_REG16_LE(0x3070) +#define IMX678_ANA_GAIN_MIN_NORMAL 0 +#define IMX678_ANA_GAIN_MAX_NORMAL 100 +#define IMX678_ANA_GAIN_STEP 1 +#define IMX678_ANA_GAIN_DEFAULT 0 + +/* Crop */ +#define IMX678_REG_WINMODE CCI_REG8(0x3018) +#define IMX678_REG_PIX_HST CCI_REG16_LE(0x303c) +#define IMX678_REG_PIX_HWIDTH CCI_REG16_LE(0x303e) +#define IMX678_REG_PIX_VST CCI_REG16_LE(0x3044) +#define IMX678_REG_PIX_VWIDTH CCI_REG16_LE(0x3046) + +/* Flip */ +#define IMX678_REG_WINMODEH CCI_REG8(0x3020) +#define IMX678_REG_WINMODEV CCI_REG8(0x3021) + +/* Sensor Identification */ +#define IMX678_REG_MONOCHROME CCI_REG8(0x4d18) +#define IMX678_TYPE BIT(0) +#define IMX678_REG_MODULE_ID CCI_REG16_LE(0x4d1c) +#define IMX678_ID 0x02a6 +#define IMX678_MODULE_ID_DELAY 80000 + +/* Common configuration registers */ +#define IMX678_REG_WDMODE CCI_REG8(0x301a) +#define IMX678_REG_ADDMODE CCI_REG8(0x301b) +#define IMX678_REG_THIN_V_EN CCI_REG8(0x301c) +#define IMX678_REG_VCMODE CCI_REG8(0x301e) +#define IMX678_REG_ADBIT CCI_REG8(0x3022) +#define IMX678_REG_MDBIT CCI_REG8(0x3023) +#define IMX678_REG_GAIN_PGC_FIDMD CCI_REG8(0x3400) + +/* Test pattern generator */ +#define IMX678_REG_TPG_EN_DUOUT CCI_REG8(0x30e0) +#define IMX678_REG_TPG_PATSEL_DUOUT CCI_REG8(0x30e2) +#define IMX678_TPG_ALL_000 0 +#define IMX678_TPG_ALL_FFF 1 +#define IMX678_TPG_ALL_555 2 +#define IMX678_TPG_ALL_AAA 3 +#define IMX678_TPG_TOG_555_AAA 4 +#define IMX678_TPG_TOG_AAA_555 5 +#define IMX678_TPG_TOG_000_555 6 +#define IMX678_TPG_TOG_555_000 7 +#define IMX678_TPG_TOG_000_FFF 8 +#define IMX678_TPG_TOG_FFF_000 9 +#define IMX678_TPG_H_COLOR_BARS 10 +#define IMX678_TPG_V_COLOR_BARS 11 +#define IMX678_REG_TPG_COLORWIDTH CCI_REG8(0x30e4) +#define IMX678_TPG_COLORWIDTH_80PIX 0 +#define IMX678_TPG_COLORWIDTH_160PIX 1 +#define IMX678_TPG_COLORWIDTH_320PIX 2 +#define IMX678_TPG_COLORWIDTH_640PIX 3 + +#define IMX678_REG_INTERFACE_SEL CCI_REG8(0x4e3c) +#define IMX678_INTERFACE_2L_4L 0x07 +#define IMX678_INTERFACE_8L_2x4L 0x7f + +/* Minimum output resolution */ +#define IMX678_PIXEL_ARRAY_MIN_WIDTH 1040 +#define IMX678_PIXEL_ARRAY_MIN_HEIGHT 956 + +/* Sensor windowing register alignment */ +#define IMX678_CROP_HWIDTH_ALIGN 16 +#define IMX678_CROP_VWIDTH_ALIGN 4 +#define IMX678_CROP_HST_ALIGN 4 +#define IMX678_CROP_VST_ALIGN 4 + +/* Subdev pads */ +#define IMX678_SOURCE_PAD 0 + +/* IMX678 native and active pixel array size. */ +static const struct v4l2_rect imx678_native_area = { + .top = 0, + .left = 0, + .width = 3857, + .height = 2201, +}; + +static const struct v4l2_rect imx678_active_area = { + .top = 20, + .left = 0, + .width = 3856, + .height = 2180, +}; + +enum imx678_type { + IMX678_COLOR = 0, + IMX678_MONOCHROME = 1, +}; + +struct imx678_model_info { + enum imx678_type type; + const u32 *codes; + unsigned int num_codes; +}; + +enum imx678_lanemode { + IMX678_LANEMODE_2L = 1, + IMX678_LANEMODE_4L = 3, +}; + +/* Link frequency setup (DDR: lane rate = 2 x link freq) */ +enum { + IMX678_LINK_FREQ_297MHZ, + IMX678_LINK_FREQ_360MHZ, + IMX678_LINK_FREQ_445MHZ, + IMX678_LINK_FREQ_594MHZ, + IMX678_LINK_FREQ_720MHZ, + IMX678_LINK_FREQ_891MHZ, + IMX678_LINK_FREQ_1039MHZ, + IMX678_LINK_FREQ_1188MHZ, +}; + +static const u8 link_freqs_reg_value[] = { + [IMX678_LINK_FREQ_297MHZ] = 0x07, + [IMX678_LINK_FREQ_360MHZ] = 0x06, + [IMX678_LINK_FREQ_445MHZ] = 0x05, + [IMX678_LINK_FREQ_594MHZ] = 0x04, + [IMX678_LINK_FREQ_720MHZ] = 0x03, + [IMX678_LINK_FREQ_891MHZ] = 0x02, + [IMX678_LINK_FREQ_1039MHZ] = 0x01, + [IMX678_LINK_FREQ_1188MHZ] = 0x00, +}; + +static const u64 link_freqs[] = { + [IMX678_LINK_FREQ_297MHZ] = 297000000, + [IMX678_LINK_FREQ_360MHZ] = 360000000, + [IMX678_LINK_FREQ_445MHZ] = 445500000, + [IMX678_LINK_FREQ_594MHZ] = 594000000, + [IMX678_LINK_FREQ_720MHZ] = 720000000, + [IMX678_LINK_FREQ_891MHZ] = 891000000, + [IMX678_LINK_FREQ_1039MHZ] = 1039500000, + [IMX678_LINK_FREQ_1188MHZ] = 1188000000, +}; + +static const u16 min_hmax_4lane[] = { + [IMX678_LINK_FREQ_297MHZ] = 1584, + [IMX678_LINK_FREQ_360MHZ] = 1320, + [IMX678_LINK_FREQ_445MHZ] = 1100, + [IMX678_LINK_FREQ_594MHZ] = 792, + [IMX678_LINK_FREQ_720MHZ] = 660, + [IMX678_LINK_FREQ_891MHZ] = 550, + [IMX678_LINK_FREQ_1039MHZ] = 550, + [IMX678_LINK_FREQ_1188MHZ] = 550, +}; + +struct imx678_inck_cfg { + u32 xclk_hz; /* platform clock rate */ + u8 inck_sel; /* value for reg */ +}; + +static const struct imx678_inck_cfg imx678_inck_table[] = { + { 74250000, 0x00 }, + { 37125000, 0x01 }, + { 72000000, 0x02 }, + { 27000000, 0x03 }, + { 24000000, 0x04 }, + { 36000000, 0x05 }, + { 18000000, 0x06 }, + { 13500000, 0x07 }, +}; + +static const char * const imx678_tpg_menu[] = { + "Disabled", + "All 000h", + "All FFFh", + "All 555h", + "All AAAh", + "Toggle 555/AAAh", + "Toggle AAA/555h", + "Toggle 000/555h", + "Toggle 555/000h", + "Toggle 000/FFFh", + "Toggle FFF/000h", + "Horizontal color bars", + "Vertical color bars", +}; + +static const int imx678_tpg_val[] = { + IMX678_TPG_ALL_000, + IMX678_TPG_ALL_000, + IMX678_TPG_ALL_FFF, + IMX678_TPG_ALL_555, + IMX678_TPG_ALL_AAA, + IMX678_TPG_TOG_555_AAA, + IMX678_TPG_TOG_AAA_555, + IMX678_TPG_TOG_000_555, + IMX678_TPG_TOG_555_000, + IMX678_TPG_TOG_000_FFF, + IMX678_TPG_TOG_FFF_000, + IMX678_TPG_H_COLOR_BARS, + IMX678_TPG_V_COLOR_BARS, +}; + +/* Common configuration */ +static const struct cci_reg_sequence common_regs[] = { + { IMX678_REG_THIN_V_EN, 0x00 }, + { IMX678_REG_VCMODE, 0x01 }, + { CCI_REG8(0x306b), 0x00 }, + { IMX678_REG_GAIN_PGC_FIDMD, 0x01 }, + { CCI_REG8(0x3460), 0x22 }, + { CCI_REG8(0x355a), 0x64 }, + { CCI_REG8(0x3a02), 0x7a }, + { CCI_REG8(0x3a10), 0xec }, + { CCI_REG8(0x3a12), 0x71 }, + { CCI_REG8(0x3a14), 0xde }, + { CCI_REG8(0x3a20), 0x2b }, + { CCI_REG8(0x3a24), 0x22 }, + { CCI_REG8(0x3a25), 0x25 }, + { CCI_REG8(0x3a26), 0x2a }, + { CCI_REG8(0x3a27), 0x2c }, + { CCI_REG8(0x3a28), 0x39 }, + { CCI_REG8(0x3a29), 0x38 }, + { CCI_REG8(0x3a30), 0x04 }, + { CCI_REG8(0x3a31), 0x04 }, + { CCI_REG8(0x3a32), 0x03 }, + { CCI_REG8(0x3a33), 0x03 }, + { CCI_REG8(0x3a34), 0x09 }, + { CCI_REG8(0x3a35), 0x06 }, + { CCI_REG8(0x3a38), 0xcd }, + { CCI_REG8(0x3a3a), 0x4c }, + { CCI_REG8(0x3a3c), 0xb9 }, + { CCI_REG8(0x3a3e), 0x30 }, + { CCI_REG8(0x3a40), 0x2c }, + { CCI_REG8(0x3a42), 0x39 }, + { CCI_REG8(0x3a4e), 0x00 }, + { CCI_REG8(0x3a52), 0x00 }, + { CCI_REG8(0x3a56), 0x00 }, + { CCI_REG8(0x3a5a), 0x00 }, + { CCI_REG8(0x3a5e), 0x00 }, + { CCI_REG8(0x3a62), 0x00 }, + { CCI_REG8(0x3a64), 0x00 }, + { CCI_REG8(0x3a6e), 0xa0 }, + { CCI_REG8(0x3a70), 0x50 }, + { CCI_REG8(0x3a8c), 0x04 }, + { CCI_REG8(0x3a8d), 0x03 }, + { CCI_REG8(0x3a8e), 0x09 }, + { CCI_REG8(0x3a90), 0x38 }, + { CCI_REG8(0x3a91), 0x42 }, + { CCI_REG8(0x3a92), 0x3c }, + { CCI_REG8(0x3b0e), 0xf3 }, + { CCI_REG8(0x3b12), 0xe5 }, + { CCI_REG8(0x3b27), 0xc0 }, + { CCI_REG8(0x3b2e), 0xef }, + { CCI_REG8(0x3b30), 0x6a }, + { CCI_REG8(0x3b32), 0xf6 }, + { CCI_REG8(0x3b36), 0xe1 }, + { CCI_REG8(0x3b3a), 0xe8 }, + { CCI_REG8(0x3b5a), 0x17 }, + { CCI_REG8(0x3b5e), 0xef }, + { CCI_REG8(0x3b60), 0x6a }, + { CCI_REG8(0x3b62), 0xf6 }, + { CCI_REG8(0x3b66), 0xe1 }, + { CCI_REG8(0x3b6a), 0xe8 }, + { CCI_REG8(0x3b88), 0xec }, + { CCI_REG8(0x3b8a), 0xed }, + { CCI_REG8(0x3b94), 0x71 }, + { CCI_REG8(0x3b96), 0x72 }, + { CCI_REG8(0x3b98), 0xde }, + { CCI_REG8(0x3b9a), 0xdf }, + { CCI_REG8(0x3c0f), 0x06 }, + { CCI_REG8(0x3c10), 0x06 }, + { CCI_REG8(0x3c11), 0x06 }, + { CCI_REG8(0x3c12), 0x06 }, + { CCI_REG8(0x3c13), 0x06 }, + { CCI_REG8(0x3c18), 0x20 }, + { CCI_REG8(0x3c37), 0x10 }, + { CCI_REG8(0x3c3a), 0x7a }, + { CCI_REG8(0x3c40), 0xf4 }, + { CCI_REG8(0x3c48), 0xe6 }, + { CCI_REG8(0x3c54), 0xce }, + { CCI_REG8(0x3c56), 0xd0 }, + { CCI_REG8(0x3c6c), 0x53 }, + { CCI_REG8(0x3c6e), 0x55 }, + { CCI_REG8(0x3c70), 0xc0 }, + { CCI_REG8(0x3c72), 0xc2 }, + { CCI_REG8(0x3c7e), 0xce }, + { CCI_REG8(0x3c8c), 0xcf }, + { CCI_REG8(0x3c8e), 0xeb }, + { CCI_REG8(0x3c98), 0x54 }, + { CCI_REG8(0x3c9a), 0x70 }, + { CCI_REG8(0x3c9c), 0xc1 }, + { CCI_REG8(0x3c9e), 0xdd }, + { CCI_REG8(0x3cb0), 0x7a }, + { CCI_REG8(0x3cb2), 0xba }, + { CCI_REG8(0x3cc8), 0xbc }, + { CCI_REG8(0x3cca), 0x7c }, + { CCI_REG8(0x3cd4), 0xea }, + { CCI_REG8(0x3cd5), 0x01 }, + { CCI_REG8(0x3cd6), 0x4a }, + { CCI_REG8(0x3cd8), 0x00 }, + { CCI_REG8(0x3cd9), 0x00 }, + { CCI_REG8(0x3cda), 0xff }, + { CCI_REG8(0x3cdb), 0x03 }, + { CCI_REG8(0x3cdc), 0x00 }, + { CCI_REG8(0x3cdd), 0x00 }, + { CCI_REG8(0x3cde), 0xff }, + { CCI_REG8(0x3cdf), 0x03 }, + { CCI_REG8(0x3ce4), 0x4c }, + { CCI_REG8(0x3ce6), 0xec }, + { CCI_REG8(0x3ce7), 0x01 }, + { CCI_REG8(0x3ce8), 0xff }, + { CCI_REG8(0x3ce9), 0x03 }, + { CCI_REG8(0x3cea), 0x00 }, + { CCI_REG8(0x3ceb), 0x00 }, + { CCI_REG8(0x3cec), 0xff }, + { CCI_REG8(0x3ced), 0x03 }, + { CCI_REG8(0x3cee), 0x00 }, + { CCI_REG8(0x3cef), 0x00 }, + { CCI_REG8(0x3cf2), 0xff }, + { CCI_REG8(0x3cf3), 0x03 }, + { CCI_REG8(0x3cf4), 0x00 }, + { CCI_REG8(0x3e28), 0x82 }, + { CCI_REG8(0x3e2a), 0x80 }, + { CCI_REG8(0x3e30), 0x85 }, + { CCI_REG8(0x3e32), 0x7d }, + { CCI_REG8(0x3e5c), 0xce }, + { CCI_REG8(0x3e5e), 0xd3 }, + { CCI_REG8(0x3e70), 0x53 }, + { CCI_REG8(0x3e72), 0x58 }, + { CCI_REG8(0x3e74), 0xc0 }, + { CCI_REG8(0x3e76), 0xc5 }, + { CCI_REG8(0x3e78), 0xc0 }, + { CCI_REG8(0x3e79), 0x01 }, + { CCI_REG8(0x3e7a), 0xd4 }, + { CCI_REG8(0x3e7b), 0x01 }, + { CCI_REG8(0x3eb4), 0x0b }, + { CCI_REG8(0x3eb5), 0x02 }, + { CCI_REG8(0x3eb6), 0x4d }, + { CCI_REG8(0x3eb7), 0x42 }, + { CCI_REG8(0x3eec), 0xf3 }, + { CCI_REG8(0x3eee), 0xe7 }, + { CCI_REG8(0x3f01), 0x01 }, + { CCI_REG8(0x3f24), 0x10 }, + { CCI_REG8(0x3f28), 0x2d }, + { CCI_REG8(0x3f2a), 0x2d }, + { CCI_REG8(0x3f2c), 0x2d }, + { CCI_REG8(0x3f2e), 0x2d }, + { CCI_REG8(0x3f30), 0x23 }, + { CCI_REG8(0x3f38), 0x2d }, + { CCI_REG8(0x3f3a), 0x2d }, + { CCI_REG8(0x3f3c), 0x2d }, + { CCI_REG8(0x3f3e), 0x28 }, + { CCI_REG8(0x3f40), 0x1e }, + { CCI_REG8(0x3f48), 0x2d }, + { CCI_REG8(0x3f4a), 0x2d }, + { CCI_REG8(0x3f4c), 0x00 }, + { CCI_REG8(0x4004), 0xe4 }, + { CCI_REG8(0x4006), 0xff }, + { CCI_REG8(0x4018), 0x69 }, + { CCI_REG8(0x401a), 0x84 }, + { CCI_REG8(0x401c), 0xd6 }, + { CCI_REG8(0x401e), 0xf1 }, + { CCI_REG8(0x4038), 0xde }, + { CCI_REG8(0x403a), 0x00 }, + { CCI_REG8(0x403b), 0x01 }, + { CCI_REG8(0x404c), 0x63 }, + { CCI_REG8(0x404e), 0x85 }, + { CCI_REG8(0x4050), 0xd0 }, + { CCI_REG8(0x4052), 0xf2 }, + { CCI_REG8(0x4108), 0xdd }, + { CCI_REG8(0x410a), 0xf7 }, + { CCI_REG8(0x411c), 0x62 }, + { CCI_REG8(0x411e), 0x7c }, + { CCI_REG8(0x4120), 0xcf }, + { CCI_REG8(0x4122), 0xe9 }, + { CCI_REG8(0x4138), 0xe6 }, + { CCI_REG8(0x413a), 0xf1 }, + { CCI_REG8(0x414c), 0x6b }, + { CCI_REG8(0x414e), 0x76 }, + { CCI_REG8(0x4150), 0xd8 }, + { CCI_REG8(0x4152), 0xe3 }, + { CCI_REG8(0x417e), 0x03 }, + { CCI_REG8(0x417f), 0x01 }, + { CCI_REG8(0x4186), 0xe0 }, + { CCI_REG8(0x4190), 0xf3 }, + { CCI_REG8(0x4192), 0xf7 }, + { CCI_REG8(0x419c), 0x78 }, + { CCI_REG8(0x419e), 0x7c }, + { CCI_REG8(0x41a0), 0xe5 }, + { CCI_REG8(0x41a2), 0xe9 }, + { CCI_REG8(0x41c8), 0xe2 }, + { CCI_REG8(0x41ca), 0xfd }, + { CCI_REG8(0x41dc), 0x67 }, + { CCI_REG8(0x41de), 0x82 }, + { CCI_REG8(0x41e0), 0xd4 }, + { CCI_REG8(0x41e2), 0xef }, + { CCI_REG8(0x4200), 0xde }, + { CCI_REG8(0x4202), 0xda }, + { CCI_REG8(0x4218), 0x63 }, + { CCI_REG8(0x421a), 0x5f }, + { CCI_REG8(0x421c), 0xd0 }, + { CCI_REG8(0x421e), 0xcc }, + { CCI_REG8(0x425a), 0x82 }, + { CCI_REG8(0x425c), 0xef }, + { CCI_REG8(0x4348), 0xfe }, + { CCI_REG8(0x4349), 0x06 }, + { CCI_REG8(0x4352), 0xce }, + { CCI_REG8(0x4420), 0x0b }, + { CCI_REG8(0x4421), 0x02 }, + { CCI_REG8(0x4422), 0x4d }, + { CCI_REG8(0x4423), 0x0a }, + { CCI_REG8(0x4426), 0xf5 }, + { CCI_REG8(0x442a), 0xe7 }, + { CCI_REG8(0x4432), 0xf5 }, + { CCI_REG8(0x4436), 0xe7 }, + { CCI_REG8(0x4466), 0xb4 }, + { CCI_REG8(0x446e), 0x32 }, + { CCI_REG8(0x449f), 0x1c }, + { CCI_REG8(0x44a4), 0x2c }, + { CCI_REG8(0x44a6), 0x2c }, + { CCI_REG8(0x44a8), 0x2c }, + { CCI_REG8(0x44aa), 0x2c }, + { CCI_REG8(0x44b4), 0x2c }, + { CCI_REG8(0x44b6), 0x2c }, + { CCI_REG8(0x44b8), 0x2c }, + { CCI_REG8(0x44ba), 0x2c }, + { CCI_REG8(0x44c4), 0x2c }, + { CCI_REG8(0x44c6), 0x2c }, + { CCI_REG8(0x44c8), 0x2c }, + { CCI_REG8(0x4506), 0xf3 }, + { CCI_REG8(0x450e), 0xe5 }, + { CCI_REG8(0x4516), 0xf3 }, + { CCI_REG8(0x4522), 0xe5 }, + { CCI_REG8(0x4524), 0xf3 }, + { CCI_REG8(0x452c), 0xe5 }, + { CCI_REG8(0x453c), 0x22 }, + { CCI_REG8(0x453d), 0x1b }, + { CCI_REG8(0x453e), 0x1b }, + { CCI_REG8(0x453f), 0x15 }, + { CCI_REG8(0x4540), 0x15 }, + { CCI_REG8(0x4541), 0x15 }, + { CCI_REG8(0x4542), 0x15 }, + { CCI_REG8(0x4543), 0x15 }, + { CCI_REG8(0x4544), 0x15 }, + { CCI_REG8(0x4548), 0x00 }, + { CCI_REG8(0x4549), 0x01 }, + { CCI_REG8(0x454a), 0x01 }, + { CCI_REG8(0x454b), 0x06 }, + { CCI_REG8(0x454c), 0x06 }, + { CCI_REG8(0x454d), 0x06 }, + { CCI_REG8(0x454e), 0x06 }, + { CCI_REG8(0x454f), 0x06 }, + { CCI_REG8(0x4550), 0x06 }, + { CCI_REG8(0x4554), 0x55 }, + { CCI_REG8(0x4555), 0x02 }, + { CCI_REG8(0x4556), 0x42 }, + { CCI_REG8(0x4557), 0x05 }, + { CCI_REG8(0x4558), 0xfd }, + { CCI_REG8(0x4559), 0x05 }, + { CCI_REG8(0x455a), 0x94 }, + { CCI_REG8(0x455b), 0x06 }, + { CCI_REG8(0x455d), 0x06 }, + { CCI_REG8(0x455e), 0x49 }, + { CCI_REG8(0x455f), 0x07 }, + { CCI_REG8(0x4560), 0x7f }, + { CCI_REG8(0x4561), 0x07 }, + { CCI_REG8(0x4562), 0xa5 }, + { CCI_REG8(0x4564), 0x55 }, + { CCI_REG8(0x4565), 0x02 }, + { CCI_REG8(0x4566), 0x42 }, + { CCI_REG8(0x4567), 0x05 }, + { CCI_REG8(0x4568), 0xfd }, + { CCI_REG8(0x4569), 0x05 }, + { CCI_REG8(0x456a), 0x94 }, + { CCI_REG8(0x456b), 0x06 }, + { CCI_REG8(0x456d), 0x06 }, + { CCI_REG8(0x456e), 0x49 }, + { CCI_REG8(0x456f), 0x07 }, + { CCI_REG8(0x4572), 0xa5 }, + { CCI_REG8(0x460c), 0x7d }, + { CCI_REG8(0x460e), 0xb1 }, + { CCI_REG8(0x4614), 0xa8 }, + { CCI_REG8(0x4616), 0xb2 }, + { CCI_REG8(0x461c), 0x7e }, + { CCI_REG8(0x461e), 0xa7 }, + { CCI_REG8(0x4624), 0xa8 }, + { CCI_REG8(0x4626), 0xb2 }, + { CCI_REG8(0x462c), 0x7e }, + { CCI_REG8(0x462e), 0x8a }, + { CCI_REG8(0x4630), 0x94 }, + { CCI_REG8(0x4632), 0xa7 }, + { CCI_REG8(0x4634), 0xfb }, + { CCI_REG8(0x4636), 0x2f }, + { CCI_REG8(0x4638), 0x81 }, + { CCI_REG8(0x4639), 0x01 }, + { CCI_REG8(0x463a), 0xb5 }, + { CCI_REG8(0x463b), 0x01 }, + { CCI_REG8(0x463c), 0x26 }, + { CCI_REG8(0x463e), 0x30 }, + { CCI_REG8(0x4640), 0xac }, + { CCI_REG8(0x4641), 0x01 }, + { CCI_REG8(0x4642), 0xb6 }, + { CCI_REG8(0x4643), 0x01 }, + { CCI_REG8(0x4644), 0xfc }, + { CCI_REG8(0x4646), 0x25 }, + { CCI_REG8(0x4648), 0x82 }, + { CCI_REG8(0x4649), 0x01 }, + { CCI_REG8(0x464a), 0xab }, + { CCI_REG8(0x464b), 0x01 }, + { CCI_REG8(0x464c), 0x26 }, + { CCI_REG8(0x464e), 0x30 }, + { CCI_REG8(0x4654), 0xfc }, + { CCI_REG8(0x4656), 0x08 }, + { CCI_REG8(0x4658), 0x12 }, + { CCI_REG8(0x465a), 0x25 }, + { CCI_REG8(0x4662), 0xfc }, + { CCI_REG8(0x46a2), 0xfb }, + { CCI_REG8(0x46d6), 0xf3 }, + { CCI_REG8(0x46e6), 0x00 }, + { CCI_REG8(0x46e8), 0xff }, + { CCI_REG8(0x46e9), 0x03 }, + { CCI_REG8(0x46ec), 0x7a }, + { CCI_REG8(0x46ee), 0xe5 }, + { CCI_REG8(0x46f4), 0xee }, + { CCI_REG8(0x46f6), 0xf2 }, + { CCI_REG8(0x470c), 0xff }, + { CCI_REG8(0x470d), 0x03 }, + { CCI_REG8(0x470e), 0x00 }, + { CCI_REG8(0x4714), 0xe0 }, + { CCI_REG8(0x4716), 0xe4 }, + { CCI_REG8(0x471e), 0xed }, + { CCI_REG8(0x472e), 0x00 }, + { CCI_REG8(0x4730), 0xff }, + { CCI_REG8(0x4731), 0x03 }, + { CCI_REG8(0x4734), 0x7b }, + { CCI_REG8(0x4736), 0xdf }, + { CCI_REG8(0x4754), 0x7d }, + { CCI_REG8(0x4756), 0x8b }, + { CCI_REG8(0x4758), 0x93 }, + { CCI_REG8(0x475a), 0xb1 }, + { CCI_REG8(0x475c), 0xfb }, + { CCI_REG8(0x475e), 0x09 }, + { CCI_REG8(0x4760), 0x11 }, + { CCI_REG8(0x4762), 0x2f }, + { CCI_REG8(0x4766), 0xcc }, + { CCI_REG8(0x4776), 0xcb }, + { CCI_REG8(0x477e), 0x4a }, + { CCI_REG8(0x478e), 0x49 }, + { CCI_REG8(0x4794), 0x7c }, + { CCI_REG8(0x4796), 0x8f }, + { CCI_REG8(0x4798), 0xb3 }, + { CCI_REG8(0x4799), 0x00 }, + { CCI_REG8(0x479a), 0xcc }, + { CCI_REG8(0x479c), 0xc1 }, + { CCI_REG8(0x479e), 0xcb }, + { CCI_REG8(0x47a4), 0x7d }, + { CCI_REG8(0x47a6), 0x8e }, + { CCI_REG8(0x47a8), 0xb4 }, + { CCI_REG8(0x47a9), 0x00 }, + { CCI_REG8(0x47aa), 0xc0 }, + { CCI_REG8(0x47ac), 0xfa }, + { CCI_REG8(0x47ae), 0x0d }, + { CCI_REG8(0x47b0), 0x31 }, + { CCI_REG8(0x47b1), 0x01 }, + { CCI_REG8(0x47b2), 0x4a }, + { CCI_REG8(0x47b3), 0x01 }, + { CCI_REG8(0x47b4), 0x3f }, + { CCI_REG8(0x47b6), 0x49 }, + { CCI_REG8(0x47bc), 0xfb }, + { CCI_REG8(0x47be), 0x0c }, + { CCI_REG8(0x47c0), 0x32 }, + { CCI_REG8(0x47c1), 0x01 }, + { CCI_REG8(0x47c2), 0x3e }, + { CCI_REG8(0x47c3), 0x01 }, + { IMX678_REG_WDMODE, 0x00 }, + { IMX678_REG_MDBIT, 0x01 }, + { IMX678_REG_XXS_DRV, 0x00 }, +}; + +static const u32 codes_bayer[] = { + MEDIA_BUS_FMT_SRGGB12_1X12, +}; + +static const u32 codes_monochrome[] = { + MEDIA_BUS_FMT_Y12_1X12, +}; + +static const struct imx678_model_info imx678_aaqr_info = { + .type = IMX678_COLOR, + .codes = codes_bayer, + .num_codes = ARRAY_SIZE(codes_bayer), +}; + +static const struct imx678_model_info imx678_aamr_info = { + .type = IMX678_MONOCHROME, + .codes = codes_monochrome, + .num_codes = ARRAY_SIZE(codes_monochrome), +}; + +static const char * const imx678_supply_name[] = { + "avdd", /* Analog (3.3V) supply */ + "dvdd", /* Digital Core (1.1V) supply */ + "ovdd", /* IF (1.8V) supply */ +}; + +struct imx678 { + struct v4l2_subdev sd; + struct media_pad pad; + struct regmap *cci; + + const struct imx678_model_info *info; + + struct clk *xclk; + u32 xclk_freq; + + /* chosen INCK_SEL register value */ + u8 inck_sel_val; + + /* Link configurations */ + enum imx678_lanemode lane_mode; + unsigned long link_freq_bitmap; + + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[ARRAY_SIZE(imx678_supply_name)]; + + struct v4l2_ctrl_handler ctrl_handler; + + /* V4L2 Controls */ + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + + /* Track VMAX for exposure updates */ + u32 vmax; +}; + +static inline struct imx678 *to_imx678(struct v4l2_subdev *_sd) +{ + return container_of_const(_sd, struct imx678, sd); +} + +static u32 imx678_default_mbus_code(struct imx678 *imx678) +{ + return imx678->info->codes[0]; +} + +static bool imx678_mbus_code_supported(struct imx678 *imx678, u32 code) +{ + for (unsigned int i = 0; i < imx678->info->num_codes; i++) { + if (imx678->info->codes[i] == code) + return true; + } + + return false; +} + +static int imx678_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx678 *imx678 = container_of_const(ctrl->handler, struct + imx678, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); + const struct v4l2_mbus_framefmt *format; + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_get_locked_active_state(&imx678->sd); + format = v4l2_subdev_state_get_format(state, IMX678_SOURCE_PAD); + + if (ctrl->id == V4L2_CID_VBLANK) { + u32 current_exposure = imx678->exposure->cur.val; + + imx678->vmax = format->height + ctrl->val; + + current_exposure = clamp_t(u32, current_exposure, + IMX678_EXPOSURE_MIN, + imx678->vmax - IMX678_SHR_MIN); + ret = __v4l2_ctrl_modify_range(imx678->exposure, + IMX678_EXPOSURE_MIN, + imx678->vmax - IMX678_SHR_MIN, + 1, current_exposure); + if (ret) + return ret; + } + + /* + * Only apply control values when device is powered on (RPM ACTIVE) + * and streaming (usage count != 0) + */ + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_VBLANK: + cci_write(imx678->cci, IMX678_REG_VMAX, imx678->vmax, &ret); + fallthrough; /* SHR = VMAX - exposure, so update it */ + case V4L2_CID_EXPOSURE: { + u32 shr = imx678->vmax - imx678->exposure->val; + + cci_write(imx678->cci, IMX678_REG_SHR, shr, &ret); + break; + } + case V4L2_CID_ANALOGUE_GAIN: + cci_write(imx678->cci, IMX678_REG_GAIN, ctrl->val, &ret); + break; + case V4L2_CID_HBLANK: { + u32 hmax = (format->width + ctrl->val) / IMX678_PIX_PER_CLK; + + cci_write(imx678->cci, IMX678_REG_HMAX, hmax, &ret); + break; + } + case V4L2_CID_TEST_PATTERN: { + cci_write(imx678->cci, IMX678_REG_TPG_COLORWIDTH, + IMX678_TPG_COLORWIDTH_160PIX, &ret); + cci_write(imx678->cci, IMX678_REG_TPG_PATSEL_DUOUT, + imx678_tpg_val[ctrl->val], &ret); + cci_write(imx678->cci, IMX678_REG_TPG_EN_DUOUT, + (ctrl->val) ? 1 : 0, + &ret); + break; + } + case V4L2_CID_HFLIP: + cci_write(imx678->cci, IMX678_REG_WINMODEH, ctrl->val, &ret); + break; + case V4L2_CID_VFLIP: + cci_write(imx678->cci, IMX678_REG_WINMODEV, ctrl->val, &ret); + break; + default: + dev_warn(&client->dev, + "ctrl(id:0x%x,val:0x%x) is not handled\n", + ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops imx678_ctrl_ops = { + .s_ctrl = imx678_set_ctrl, +}; + +static int imx678_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct imx678 *imx678 = to_imx678(sd); + + if (code->index >= imx678->info->num_codes) + return -EINVAL; + + code->code = imx678->info->codes[code->index]; + + return 0; +} + +static int imx678_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct imx678 *imx678 = to_imx678(sd); + const struct v4l2_rect *crop; + + if (fse->index) + return -EINVAL; + + if (!imx678_mbus_code_supported(imx678, fse->code)) + return -EINVAL; + + crop = v4l2_subdev_state_get_crop(sd_state, fse->pad); + + fse->min_width = crop->width; + fse->max_width = fse->min_width; + fse->min_height = crop->height; + fse->max_height = fse->min_height; + + return 0; +} + +static int imx678_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_selection *sel) +{ + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *v4l2_subdev_state_get_crop(sd_state, sel->pad); + return 0; + + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r = imx678_native_area; + return 0; + + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r = imx678_active_area; + return 0; + } + + return -EINVAL; +} + +static int imx678_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct imx678 *imx678 = to_imx678(sd); + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *crop; + + crop = v4l2_subdev_state_get_crop(state, IMX678_SOURCE_PAD); + *crop = imx678_active_area; + + format = v4l2_subdev_state_get_format(state, IMX678_SOURCE_PAD); + format->code = imx678_default_mbus_code(imx678); + format->width = imx678_active_area.width; + format->height = imx678_active_area.height; + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_RAW; + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + format->quantization = V4L2_QUANTIZATION_FULL_RANGE; + format->xfer_func = V4L2_XFER_FUNC_NONE; + + return 0; +} + +static int imx678_write_common(struct imx678 *imx678) +{ + int ret = 0; + + cci_multi_reg_write(imx678->cci, common_regs, ARRAY_SIZE(common_regs), + &ret); + + cci_write(imx678->cci, IMX678_REG_INCK_SEL, imx678->inck_sel_val, &ret); + cci_write(imx678->cci, IMX678_REG_DATARATE_SEL, + link_freqs_reg_value[__ffs(imx678->link_freq_bitmap)], &ret); + cci_write(imx678->cci, IMX678_REG_LANEMODE, imx678->lane_mode, &ret); + + cci_write(imx678->cci, IMX678_REG_INTERFACE_SEL, IMX678_INTERFACE_2L_4L, + &ret); + + return ret; +} + +static int imx678_program_window(struct imx678 *imx678, + const struct v4l2_rect *crop) +{ + int ret = 0; + + cci_write(imx678->cci, IMX678_REG_ADDMODE, 0x00, &ret); + cci_write(imx678->cci, IMX678_REG_WINMODE, + v4l2_rect_equal(crop, &imx678_active_area) ? 0x00 : 0x04, + &ret); + cci_write(imx678->cci, IMX678_REG_PIX_HST, + crop->left - imx678_active_area.left, &ret); + cci_write(imx678->cci, IMX678_REG_PIX_HWIDTH, crop->width, &ret); + cci_write(imx678->cci, IMX678_REG_PIX_VST, + crop->top - imx678_active_area.top, &ret); + cci_write(imx678->cci, IMX678_REG_PIX_VWIDTH, crop->height, &ret); + cci_write(imx678->cci, IMX678_REG_ADBIT, 0x01, &ret); + + return ret; +} + +static int imx678_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, u32 pad, + u64 mask) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct imx678 *imx678 = to_imx678(sd); + const struct v4l2_rect *crop; + int ret; + + ret = pm_runtime_resume_and_get(&client->dev); + if (ret < 0) + return ret; + + crop = v4l2_subdev_state_get_crop(state, pad); + ret = imx678_program_window(imx678, crop); + if (ret) { + dev_err(&client->dev, "%s failed to set mode\n", __func__); + goto err_rpm_put; + } + + ret = __v4l2_ctrl_handler_setup(imx678->sd.ctrl_handler); + if (ret) { + dev_err(&client->dev, "%s failed to apply user values\n", + __func__); + goto err_rpm_put; + } + + cci_write(imx678->cci, IMX678_REG_MODE_SELECT, IMX678_MODE_STREAMING, + &ret); + usleep_range(IMX678_STREAM_DELAY_US, IMX678_STREAM_DELAY_US + + IMX678_STREAM_DELAY_RANGE_US); + cci_write(imx678->cci, IMX678_REG_XMSTA, 0x00, &ret); + + if (ret) { + dev_err(&client->dev, "%s failed to start streaming\n", + __func__); + goto err_rpm_put; + } + + return 0; + +err_rpm_put: + pm_runtime_put(&client->dev); + + return ret; +} + +static int imx678_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 mask) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct imx678 *imx678 = to_imx678(sd); + int ret = 0; + + /* Master mode disable */ + cci_write(imx678->cci, IMX678_REG_XMSTA, 0x01, &ret); + /* Standby */ + cci_write(imx678->cci, IMX678_REG_MODE_SELECT, IMX678_MODE_STANDBY, + &ret); + if (ret) + dev_err(&client->dev, "%s failed to stop stream\n", __func__); + + pm_runtime_put(&client->dev); + + return ret; +} + +static int imx678_power_on(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx678 *imx678 = to_imx678(sd); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(imx678_supply_name), + imx678->supplies); + if (ret) { + dev_err(&client->dev, "%s: failed to enable regulators\n", + __func__); + return ret; + } + + fsleep(1); /* Tlow > 500ns */ + + gpiod_set_value_cansleep(imx678->reset_gpio, 0); + + fsleep(1); /* T3 > 1us */ + + ret = clk_prepare_enable(imx678->xclk); + if (ret) { + dev_err(&client->dev, "%s: failed to enable clock\n", + __func__); + goto reg_off; + } + + fsleep(20); /* T4 > 20us */ + + ret = imx678_write_common(imx678); + if (ret) { + dev_err(&client->dev, "%s failed to write registers\n", + __func__); + goto clk_off; + } + + return 0; + +clk_off: + clk_disable_unprepare(imx678->xclk); + +reg_off: + gpiod_set_value_cansleep(imx678->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(imx678_supply_name), + imx678->supplies); + + return ret; +} + +static int imx678_power_off(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx678 *imx678 = to_imx678(sd); + + clk_disable_unprepare(imx678->xclk); + gpiod_set_value_cansleep(imx678->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(imx678_supply_name), + imx678->supplies); + + return 0; +} + +static int imx678_identify_model(struct imx678 *imx678) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); + const struct imx678_model_info *info; + enum imx678_type detected; + int ret = 0; + u64 val = 0; + + info = device_get_match_data(&client->dev); + + /* + * This sensor's ID registers become accessible 80ms after coming out + * of STANDBY mode. + */ + cci_write(imx678->cci, IMX678_REG_MODE_SELECT, 0, &ret); + fsleep(IMX678_MODULE_ID_DELAY); + + cci_read(imx678->cci, IMX678_REG_MODULE_ID, &val, &ret); + + if (ret) { + dev_err(&client->dev, + "I2C transaction failed ret = %d\n", ret); + return ret; + } + + if (val != IMX678_ID) { + dev_err(&client->dev, + "Chip ID mismatch: %x!=%llx\n", IMX678_ID, val); + return -ENXIO; + } + + cci_read(imx678->cci, IMX678_REG_MONOCHROME, &val, &ret); + + if (ret) { + dev_err(&client->dev, + "I2C transaction failed ret = %d\n", ret); + return ret; + } + + detected = val & IMX678_TYPE; + + /* Prefer to use sensor type specified in device tree */ + if (info) { + imx678->info = info; + if (detected != info->type) + dev_err(&client->dev, + "detected %s sensor, DT specifies %s; using DT value\n", + detected == IMX678_COLOR ? "color" : "mono", + info->type == IMX678_COLOR ? "color" : "mono"); + } else { + imx678->info = detected == IMX678_MONOCHROME ? + &imx678_aamr_info : &imx678_aaqr_info; + dev_info(&client->dev, + "sensor type missing in DT; detected %s sensor\n", + detected == IMX678_MONOCHROME ? "mono" : "color"); + } + + return 0; +} + +static const struct v4l2_subdev_video_ops imx678_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops imx678_pad_ops = { + .enum_mbus_code = imx678_enum_mbus_code, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = v4l2_subdev_get_fmt, + .get_selection = imx678_get_selection, + .enum_frame_size = imx678_enum_frame_size, + .enable_streams = imx678_enable_streams, + .disable_streams = imx678_disable_streams, +}; + +static const struct v4l2_subdev_ops imx678_subdev_ops = { + .video = &imx678_video_ops, + .pad = &imx678_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops imx678_internal_ops = { + .init_state = imx678_init_state, +}; + +static int imx678_init_controls(struct imx678 *imx678) +{ + struct v4l2_ctrl_handler *ctrl_hdlr; + const u32 hmax_4lane = min_hmax_4lane[__ffs(imx678->link_freq_bitmap)]; + const u32 lane_scale = imx678->lane_mode == IMX678_LANEMODE_2L ? 2 : 1; + struct i2c_client *client = v4l2_get_subdevdata(&imx678->sd); + struct v4l2_fwnode_device_properties props; + struct v4l2_ctrl *link_freq; + s32 hblank, max_hblank, vblank, max_vblank; + u32 hmax; + int ret; + + ret = v4l2_fwnode_device_parse(&client->dev, &props); + if (ret < 0) + return ret; + + ctrl_hdlr = &imx678->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 11); + if (ret) + return ret; + + imx678->vmax = IMX678_VMAX_DEFAULT; + hmax = hmax_4lane * lane_scale; + + /* PIXEL_RATE is fixed and read-only */ + v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_PIXEL_RATE, + IMX678_PIXEL_RATE, IMX678_PIXEL_RATE, 1, + IMX678_PIXEL_RATE); + + /* LINK_FREQ is also read only */ + link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freqs) - 1, + __ffs(imx678->link_freq_bitmap), + link_freqs); + + if (link_freq) + link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + vblank = imx678->vmax - imx678_active_area.height; + max_vblank = IMX678_VMAX_MAX - imx678_active_area.height; + imx678->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_VBLANK, vblank, max_vblank, + 2, vblank); + + hblank = hmax * IMX678_PIX_PER_CLK - imx678_active_area.width; + max_hblank = IMX678_HMAX_MAX * IMX678_PIX_PER_CLK - + imx678_active_area.width; + imx678->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_HBLANK, hblank, max_hblank, + IMX678_PIX_PER_CLK, hblank); + + imx678->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX678_EXPOSURE_MIN, + IMX678_VMAX_DEFAULT - + IMX678_SHR_MIN, + IMX678_EXPOSURE_STEP, + IMX678_EXPOSURE_DEFAULT); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + IMX678_ANA_GAIN_MIN_NORMAL, + IMX678_ANA_GAIN_MAX_NORMAL, IMX678_ANA_GAIN_STEP, + IMX678_ANA_GAIN_DEFAULT); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_HFLIP, + 0, 1, 1, 0); + v4l2_ctrl_new_std(ctrl_hdlr, &imx678_ctrl_ops, V4L2_CID_VFLIP, + 0, 1, 1, 0); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx678_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx678_tpg_menu) - 1, 0, 0, + imx678_tpg_menu); + + v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx678_ctrl_ops, &props); + + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + dev_err(&client->dev, "%s control init failed (%d)\n", + __func__, ret); + v4l2_ctrl_handler_free(ctrl_hdlr); + return ret; + } + + imx678->sd.ctrl_handler = ctrl_hdlr; + + return 0; +} + +static int imx678_check_hwcfg(struct device *dev, struct imx678 *imx678) +{ + struct fwnode_handle *endpoint; + struct v4l2_fwnode_endpoint ep_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + int ret = -EINVAL; + + endpoint = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0); + if (!endpoint) { + dev_err(dev, "endpoint node not found\n"); + return -EINVAL; + } + + if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep_cfg)) { + dev_err(dev, "could not parse endpoint\n"); + goto error_out; + } + + switch (ep_cfg.bus.mipi_csi2.num_data_lanes) { + case 2: + imx678->lane_mode = IMX678_LANEMODE_2L; + break; + case 4: + imx678->lane_mode = IMX678_LANEMODE_4L; + break; + default: + dev_err(dev, + "only 2 or 4 CSI2 data lanes are currently supported\n"); + goto error_out; + } + + ret = v4l2_link_freq_to_bitmap(dev, ep_cfg.link_frequencies, + ep_cfg.nr_of_link_frequencies, + link_freqs, ARRAY_SIZE(link_freqs), + &imx678->link_freq_bitmap); + +error_out: + v4l2_fwnode_endpoint_free(&ep_cfg); + fwnode_handle_put(endpoint); + + return ret; +} + +static int imx678_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct imx678 *imx678; + int ret, i; + + imx678 = devm_kzalloc(&client->dev, sizeof(*imx678), GFP_KERNEL); + if (!imx678) + return -ENOMEM; + + v4l2_i2c_subdev_init(&imx678->sd, client, &imx678_subdev_ops); + + imx678->cci = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(imx678->cci)) + return dev_err_probe(dev, PTR_ERR(imx678->cci), + "failed to init CCI\n"); + + if (imx678_check_hwcfg(dev, imx678)) + return -EINVAL; + + imx678->xclk = devm_v4l2_sensor_clk_get(dev, NULL); + if (IS_ERR(imx678->xclk)) + return dev_err_probe(dev, PTR_ERR(imx678->xclk), + "failed to get xclk\n"); + + imx678->xclk_freq = clk_get_rate(imx678->xclk); + + for (i = 0; i < ARRAY_SIZE(imx678_inck_table); ++i) { + if (imx678_inck_table[i].xclk_hz == imx678->xclk_freq) { + imx678->inck_sel_val = imx678_inck_table[i].inck_sel; + break; + } + } + + if (i == ARRAY_SIZE(imx678_inck_table)) + return dev_err_probe(dev, -EINVAL, + "unsupported XCLK rate %u Hz\n", + imx678->xclk_freq); + + for (i = 0; i < ARRAY_SIZE(imx678_supply_name); i++) + imx678->supplies[i].supply = imx678_supply_name[i]; + + ret = devm_regulator_bulk_get(&client->dev, + ARRAY_SIZE(imx678_supply_name), + imx678->supplies); + if (ret) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + imx678->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(imx678->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(imx678->reset_gpio), + "failed to get reset GPIO\n"); + + ret = imx678_power_on(dev); + if (ret) + return ret; + + ret = imx678_identify_model(imx678); + if (ret) + goto error_power_off; + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + ret = imx678_init_controls(imx678); + if (ret) + goto error_pm_runtime; + + imx678->sd.internal_ops = &imx678_internal_ops; + imx678->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + imx678->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + imx678->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&imx678->sd.entity, 1, &imx678->pad); + if (ret) { + dev_err_probe(dev, ret, "failed to init entity pads\n"); + goto error_handler_free; + } + + imx678->sd.state_lock = imx678->ctrl_handler.lock; + ret = v4l2_subdev_init_finalize(&imx678->sd); + if (ret < 0) { + dev_err_probe(dev, ret, "subdev init error\n"); + goto error_media_entity; + } + + ret = v4l2_async_register_subdev_sensor(&imx678->sd); + if (ret < 0) { + dev_err_probe(dev, ret, + "failed to register sensor sub-device\n"); + goto error_subdev_cleanup; + } + + pm_runtime_idle(dev); + + return 0; + +error_subdev_cleanup: + v4l2_subdev_cleanup(&imx678->sd); + +error_media_entity: + media_entity_cleanup(&imx678->sd.entity); + +error_handler_free: + v4l2_ctrl_handler_free(imx678->sd.ctrl_handler); + +error_pm_runtime: + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + +error_power_off: + imx678_power_off(&client->dev); + + return ret; +} + +static void imx678_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx678 *imx678 = to_imx678(sd); + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(imx678->sd.ctrl_handler); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + imx678_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); +} + +static const struct dev_pm_ops imx678_pm_ops = { + SET_RUNTIME_PM_OPS(imx678_power_off, imx678_power_on, NULL) +}; + +static const struct of_device_id imx678_of_match[] = { + { .compatible = "sony,imx678-aamr", .data = &imx678_aamr_info }, + { .compatible = "sony,imx678-aaqr", .data = &imx678_aaqr_info }, + /* for non-conforming DTs that rely on runtime check */ + { .compatible = "sony,imx678" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, imx678_of_match); + +static struct i2c_driver imx678_i2c_driver = { + .driver = { + .name = "imx678", + .of_match_table = imx678_of_match, + .pm = pm_ptr(&imx678_pm_ops), + }, + .probe = imx678_probe, + .remove = imx678_remove, +}; + +module_i2c_driver(imx678_i2c_driver); + +MODULE_AUTHOR("Will Whang <will@willwhang.com>"); +MODULE_AUTHOR("Tetsuya NOMURA <tetsuya.nomura@soho-enterprise.com>"); +MODULE_AUTHOR("Jai Luthra <jai.luthra@ideasonboard.com>"); +MODULE_DESCRIPTION("Sony imx678 sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c index 143dcfe10445..0150e4d296af 100644 --- a/drivers/media/i2c/ov02a10.c +++ b/drivers/media/i2c/ov02a10.c @@ -820,18 +820,16 @@ static int ov02a10_check_hwcfg(struct device *dev, struct ov02a10 *ov02a10) if (!ep) return -ENXIO; + /* Optional indication of MIPI clock voltage unit */ + if (!fwnode_property_read_u32(ep, "ovti,mipi-clock-voltage", + &clk_volt)) + ov02a10->mipi_clock_voltage = clk_volt; + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); fwnode_handle_put(ep); if (ret) return ret; - /* Optional indication of MIPI clock voltage unit */ - ret = fwnode_property_read_u32(ep, "ovti,mipi-clock-voltage", - &clk_volt); - - if (!ret) - ov02a10->mipi_clock_voltage = clk_volt; - for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) { for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) { if (link_freq_menu_items[i] == diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index c2e02f191816..b4e14171556f 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -1116,18 +1116,14 @@ static void ov7740_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev); - mutex_destroy(&ov7740->mutex); - v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler); - media_entity_cleanup(&ov7740->subdev.entity); v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&ov7740->subdev.entity); ov7740_free_controls(ov7740); - pm_runtime_get_sync(&client->dev); pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + ov7740_set_power(ov7740, 0); pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); - - ov7740_set_power(ov7740, 0); } static int __maybe_unused ov7740_runtime_suspend(struct device *dev) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index 8c9cd769fa01..289a34a3eeb1 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -2608,7 +2608,7 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable) { struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); struct ov8865_state *state = &sensor->state; - int ret; + int ret = 0; if (enable) { ret = pm_runtime_resume_and_get(sensor->dev); @@ -2617,18 +2617,32 @@ static int ov8865_s_stream(struct v4l2_subdev *subdev, int enable) } mutex_lock(&sensor->mutex); - ret = ov8865_sw_standby(sensor, !enable); - mutex_unlock(&sensor->mutex); - if (ret) - return ret; + /* + * The sensor may have been kept powered by something else (e.g. the + * VCM's runtime PM device link on IPU3 platforms), in which case + * runtime resume did not run and the hardware may still be + * configured for a previous mode. Always program the negotiated + * configuration on stream start. + */ + if (enable) { + ret = ov8865_sensor_init(sensor); + if (!ret) + ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); + } - state->streaming = !!enable; + if (!ret) + ret = ov8865_sw_standby(sensor, !enable); + + mutex_unlock(&sensor->mutex); - if (!enable) + if (ret || !enable) pm_runtime_put(sensor->dev); - return 0; + if (!ret) + state->streaming = enable; + + return ret; } static const struct v4l2_subdev_video_ops ov8865_subdev_video_ops = { @@ -2915,15 +2929,15 @@ static int ov8865_resume(struct device *dev) if (ret) goto complete; - ret = ov8865_sensor_init(sensor); - if (ret) - goto error_power; + if (state->streaming) { + ret = ov8865_sensor_init(sensor); + if (ret) + goto error_power; - ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); - if (ret) - goto error_power; + ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); + if (ret) + goto error_power; - if (state->streaming) { ret = ov8865_sw_standby(sensor, false); if (ret) goto error_power; diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c index 5b6f897a74fc..3ba630ec4f2a 100644 --- a/drivers/media/i2c/ov9282.c +++ b/drivers/media/i2c/ov9282.c @@ -197,7 +197,6 @@ struct ov9282_mode { * @noncontinuous_clock: Selection of CSI2 noncontinuous clock mode * @cur_mode: Pointer to current selected sensor mode * @code: Mbus code currently selected - * @mutex: Mutex for serializing sensor controls */ struct ov9282 { struct device *dev; diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c index bcab462708c7..ece8a410e7ce 100644 --- a/drivers/media/i2c/rdacm21.c +++ b/drivers/media/i2c/rdacm21.c @@ -588,10 +588,12 @@ static int rdacm21_probe(struct i2c_client *client) ret = v4l2_async_register_subdev(&dev->sd); if (ret) - goto error_free_ctrls; + goto error_entity_cleanup; return 0; +error_entity_cleanup: + media_entity_cleanup(&dev->sd.entity); error_free_ctrls: v4l2_ctrl_handler_free(&dev->ctrls); error: @@ -606,6 +608,7 @@ static void rdacm21_remove(struct i2c_client *client) v4l2_async_unregister_subdev(&dev->sd); v4l2_ctrl_handler_free(&dev->ctrls); + media_entity_cleanup(&dev->sd.entity); i2c_unregister_device(dev->isp); } diff --git a/drivers/media/i2c/vd55g1.c b/drivers/media/i2c/vd55g1.c index 78d18c028154..c4142d771e7c 100644 --- a/drivers/media/i2c/vd55g1.c +++ b/drivers/media/i2c/vd55g1.c @@ -29,11 +29,7 @@ /* Register Map */ #define VD55G1_REG_MODEL_ID CCI_REG32_LE(0x0000) -#define VD55G1_MODEL_ID_VD55G1 0x53354731 /* Mono */ -#define VD55G1_MODEL_ID_VD65G4 0x53354733 /* RGB */ -#define VD55G1_REG_REVISION CCI_REG16_LE(0x0004) -#define VD55G1_REVISION_CCB 0x2020 -#define VD55G1_REVISION_BAYER 0x3030 +#define VD55G1_REG_COLOR_VERSION CCI_REG32_LE(0x0670) #define VD55G1_REG_FWPATCH_REVISION CCI_REG16_LE(0x0012) #define VD55G1_REG_FWPATCH_START_ADDR CCI_REG8(0x2000) #define VD55G1_REG_SYSTEM_FSM CCI_REG8(0x001c) @@ -60,7 +56,10 @@ #define VD55G1_PATGEN_ENABLE BIT(0) #define VD55G1_REG_MANUAL_ANALOG_GAIN CCI_REG8(0x0501) #define VD55G1_REG_MANUAL_COARSE_EXPOSURE CCI_REG16_LE(0x0502) -#define VD55G1_REG_MANUAL_DIGITAL_GAIN CCI_REG16_LE(0x0504) +#define VD55G1_REG_MANUAL_DIGITAL_GAIN_CH0 CCI_REG16_LE(0x0504) +#define VD55G1_REG_MANUAL_DIGITAL_GAIN_CH1 CCI_REG16_LE(0x0506) +#define VD55G1_REG_MANUAL_DIGITAL_GAIN_CH2 CCI_REG16_LE(0x0508) +#define VD55G1_REG_MANUAL_DIGITAL_GAIN_CH3 CCI_REG16_LE(0x050a) #define VD55G1_REG_APPLIED_COARSE_EXPOSURE CCI_REG16_LE(0x00e8) #define VD55G1_REG_APPLIED_ANALOG_GAIN CCI_REG16_LE(0x00ea) #define VD55G1_REG_APPLIED_DIGITAL_GAIN CCI_REG16_LE(0x00ec) @@ -114,9 +113,8 @@ #define VD55G1_WIDTH 804 #define VD55G1_HEIGHT 704 -#define VD55G1_MODE_DEF 0 +#define VD55G1_MODE_IDX_DEF 0 #define VD55G1_NB_GPIOS 4 -#define VD55G1_MBUS_CODE_DEF 0 #define VD55G1_DGAIN_DEF 256 #define VD55G1_AGAIN_DEF 19 #define VD55G1_EXPO_MAX_TERM 64 @@ -135,8 +133,39 @@ #define VD55G1_MIPI_RATE_MIN (250 * MEGA) #define VD55G1_MIPI_RATE_MAX (1200 * MEGA) -#define VD55G1_MODEL_ID_NAME(id) \ - ((id) == VD55G1_MODEL_ID_VD55G1 ? "vd55g1" : "vd65g4") +enum vd55g1_model_id { + VD55G1_MODEL_ID_2 = 0x53354731, + VD55G1_MODEL_ID_3 = 0x53354733, +}; + +enum vd55g1_color_version { + VD55G1_COLOR_VERSION_MONO, + VD55G1_COLOR_VERSION_BAYER, +}; + +struct vd55g1_version { + char *name; + enum vd55g1_model_id id; + enum vd55g1_color_version color; +}; + +static const struct vd55g1_version vd55g1_versions[] = { + { + .name = "vd55g1", + .id = VD55G1_MODEL_ID_2, + .color = VD55G1_COLOR_VERSION_MONO, + }, + { + .name = "vd55g4", + .id = VD55G1_MODEL_ID_3, + .color = VD55G1_COLOR_VERSION_MONO, + }, + { + .name = "vd65g4", + .id = VD55G1_MODEL_ID_3, + .color = VD55G1_COLOR_VERSION_BAYER, + }, +}; static const u8 vd55g1_patch_array[] = { 0x44, 0x03, 0x09, 0x02, 0xe6, 0x01, 0x42, 0x00, 0xea, 0x01, 0x42, 0x00, @@ -532,7 +561,7 @@ struct vd55g1_vblank_limits { struct vd55g1 { struct device *dev; - unsigned int id; + const struct vd55g1_version *version; struct v4l2_subdev sd; struct media_pad pad; struct regulator_bulk_data supplies[ARRAY_SIZE(vd55g1_supply_name)]; @@ -623,20 +652,28 @@ static unsigned int vd55g1_get_fmt_data_type(u32 code) static u32 vd55g1_get_fmt_code(struct vd55g1 *sensor, u32 code) { + u32 fallback_code; unsigned int i, j; - if (sensor->id == VD55G1_MODEL_ID_VD55G1) - return code; - - for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_formats_bayer); i++) { - for (j = 0; j < ARRAY_SIZE(vd55g1_mbus_formats_bayer[i]); j++) { - if (vd55g1_mbus_formats_bayer[i][j] == code) - goto adapt_bayer_pattern; + if (sensor->version->color == VD55G1_COLOR_VERSION_MONO) { + fallback_code = vd55g1_mbus_formats_mono[0]; + for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_formats_mono); i++) + if (vd55g1_mbus_formats_mono[i] == code) + return code; + } else { + fallback_code = vd55g1_mbus_formats_bayer[0][0]; + for (i = 0; i < ARRAY_SIZE(vd55g1_mbus_formats_bayer); i++) { + for (j = 0; + j < ARRAY_SIZE(vd55g1_mbus_formats_bayer[i]); + j++) { + if (vd55g1_mbus_formats_bayer[i][j] == code) + goto adapt_bayer_pattern; + } } } - dev_warn(sensor->dev, "Unsupported mbus format\n"); + dev_warn(sensor->dev, "Unsupported mbus format: 0x%x\n", code); - return code; + return fallback_code; adapt_bayer_pattern: j = 0; @@ -850,9 +887,16 @@ static int vd55g1_update_expo_cluster(struct vd55g1 *sensor, bool is_auto) vd55g1_write(sensor, VD55G1_REG_MANUAL_ANALOG_GAIN, sensor->again_ctrl->val, &ret); - if (!is_auto && sensor->dgain_ctrl->is_new) - vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN, + if (!is_auto && sensor->dgain_ctrl->is_new) { + vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN_CH0, sensor->dgain_ctrl->val, &ret); + vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN_CH1, + sensor->dgain_ctrl->val, &ret); + vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN_CH2, + sensor->dgain_ctrl->val, &ret); + vd55g1_write(sensor, VD55G1_REG_MANUAL_DIGITAL_GAIN_CH3, + sensor->dgain_ctrl->val, &ret); + } return ret; } @@ -1173,8 +1217,8 @@ static int vd55g1_patch(struct vd55g1 *sensor) u64 patch; int ret = 0; - /* vd55g1 needs a patch while vd65g4 does not */ - if (sensor->id == VD55G1_MODEL_ID_VD55G1) { + /* Version 2 needs a patch while version 3 does not */ + if (sensor->version->id == VD55G1_MODEL_ID_2) { vd55g1_write_array(sensor, VD55G1_REG_FWPATCH_START_ADDR, sizeof(vd55g1_patch_array), vd55g1_patch_array, &ret); @@ -1246,7 +1290,7 @@ static int vd55g1_enum_mbus_code(struct v4l2_subdev *sd, struct vd55g1 *sensor = to_vd55g1(sd); u32 base_code; - if (sensor->id == VD55G1_MODEL_ID_VD55G1) { + if (sensor->version->color != VD55G1_COLOR_VERSION_BAYER) { if (code->index >= ARRAY_SIZE(vd55g1_mbus_formats_mono)) return -EINVAL; base_code = vd55g1_mbus_formats_mono[code->index]; @@ -1347,6 +1391,7 @@ static int vd55g1_init_state(struct v4l2_subdev *sd, { struct vd55g1 *sensor = to_vd55g1(sd); struct v4l2_subdev_format fmt = { 0 }; + int code; struct v4l2_subdev_route routes[] = { { .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE } }; @@ -1361,9 +1406,13 @@ static int vd55g1_init_state(struct v4l2_subdev *sd, if (ret) return ret; - vd55g1_update_pad_fmt(sensor, &vd55g1_supported_modes[VD55G1_MODE_DEF], - vd55g1_get_fmt_code(sensor, VD55G1_MBUS_CODE_DEF), - &fmt.format); + if (sensor->version->color != VD55G1_COLOR_VERSION_BAYER) + code = vd55g1_mbus_formats_mono[0]; + else + code = vd55g1_mbus_formats_bayer[0][0]; + fmt.format.code = vd55g1_get_fmt_code(sensor, code); + fmt.format.width = vd55g1_supported_modes[VD55G1_MODE_IDX_DEF].width; + fmt.format.height = vd55g1_supported_modes[VD55G1_MODE_IDX_DEF].height; return vd55g1_set_pad_fmt(sd, sd_state, &fmt); } @@ -1644,38 +1693,46 @@ unlock_state: return ret; } +static const struct vd55g1_version * +vd55g1_get_version(enum vd55g1_model_id id, + enum vd55g1_color_version color) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(vd55g1_versions); i++) { + if (vd55g1_versions[i].id == id && + vd55g1_versions[i].color == color) + return &vd55g1_versions[i]; + } + + return NULL; +} + static int vd55g1_detect(struct vd55g1 *sensor) { - unsigned int dt_id = (uintptr_t)device_get_match_data(sensor->dev); - u64 rev, id; - int ret; + const struct vd55g1_version *dt_version = + device_get_match_data(sensor->dev); + const struct vd55g1_version *version; + u64 color, id; + int ret = 0; - ret = vd55g1_read(sensor, VD55G1_REG_MODEL_ID, &id, NULL); + vd55g1_read(sensor, VD55G1_REG_MODEL_ID, &id, &ret); + vd55g1_read(sensor, VD55G1_REG_COLOR_VERSION, &color, &ret); if (ret) return ret; - if (id != VD55G1_MODEL_ID_VD55G1 && id != VD55G1_MODEL_ID_VD65G4) { - dev_warn(sensor->dev, "Unsupported sensor id 0x%x\n", - (u32)id); + version = vd55g1_get_version(id, color); + if (!version) { + dev_warn(sensor->dev, "Unsupported sensor version, expected %s\n", + dt_version->name); return -ENODEV; } - if (id != dt_id) { - dev_err(sensor->dev, "Probed sensor %s and device tree definition (%s) mismatch", - VD55G1_MODEL_ID_NAME(id), VD55G1_MODEL_ID_NAME(dt_id)); + if (version->id != dt_version->id || + version->color != dt_version->color) { + dev_err(sensor->dev, "Probed sensor version %s and device tree definition %s mismatch", + version->name, dt_version->name); return -ENODEV; } - sensor->id = id; - - ret = vd55g1_read(sensor, VD55G1_REG_REVISION, &rev, NULL); - if (ret) - return ret; - if ((id == VD55G1_MODEL_ID_VD55G1 && rev != VD55G1_REVISION_CCB) && - (id == VD55G1_MODEL_ID_VD65G4 && rev != VD55G1_REVISION_BAYER)) { - dev_err(sensor->dev, "Unsupported sensor revision 0x%x for sensor %s\n", - (u16)rev, VD55G1_MODEL_ID_NAME(id)); - return -ENODEV; - } + sensor->version = version; return 0; } @@ -2033,8 +2090,9 @@ static void vd55g1_remove(struct i2c_client *client) } static const struct of_device_id vd55g1_dt_ids[] = { - { .compatible = "st,vd55g1", .data = (void *)VD55G1_MODEL_ID_VD55G1 }, - { .compatible = "st,vd65g4", .data = (void *)VD55G1_MODEL_ID_VD65G4 }, + { .compatible = "st,vd55g1", .data = (void *)&vd55g1_versions[0] }, + { .compatible = "st,vd55g4", .data = (void *)&vd55g1_versions[1] }, + { .compatible = "st,vd65g4", .data = (void *)&vd55g1_versions[2] }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, vd55g1_dt_ids); diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c index 6b50fb422a61..4811a0489524 100644 --- a/drivers/media/i2c/video-i2c.c +++ b/drivers/media/i2c/video-i2c.c @@ -522,8 +522,12 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data, "%s-vid-cap", data->v4l2_dev.name); ret = PTR_ERR_OR_ZERO(data->kthread_vid_cap); - if (!ret) - return 0; + if (ret) { + data->kthread_vid_cap = NULL; + goto error_rpm_put; + } + + return 0; error_rpm_put: pm_runtime_put_autosuspend(dev); diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 663469208271..c631b8bbd386 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3563,12 +3563,12 @@ static int __maybe_unused bttv_resume(struct device *dev) } static const struct pci_device_id bttv_pci_tbl[] = { - {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0}, - {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, - {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, - {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, - {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0}, - {0,} + { PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848) }, + { PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849) }, + { PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878) }, + { PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879) }, + { PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879) }, + { } }; MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); diff --git a/drivers/media/pci/cobalt/cobalt-alsa-main.c b/drivers/media/pci/cobalt/cobalt-alsa-main.c index 7bb7f13c70c0..9ed547cd40af 100644 --- a/drivers/media/pci/cobalt/cobalt-alsa-main.c +++ b/drivers/media/pci/cobalt/cobalt-alsa-main.c @@ -135,7 +135,6 @@ int cobalt_alsa_init(struct cobalt_stream *s) err_exit_free: if (sc != NULL) snd_card_free(sc); - kfree(cobsc); err_exit: return ret; } diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 9b9f69ff4016..7b1ca1238c8d 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -26,9 +26,8 @@ /* add your revision and whatnot here */ static const struct pci_device_id cobalt_pci_tbl[] = { - {PCI_VENDOR_ID_CISCO, PCI_DEVICE_ID_COBALT, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_COBALT) }, + { } }; MODULE_DEVICE_TABLE(pci, cobalt_pci_tbl); diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index f778f79b921d..214fac7af61e 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -40,9 +40,8 @@ EXPORT_SYMBOL(cx18_ext_init); /* add your revision and whatnot here */ static const struct pci_device_id cx18_pci_tbl[] = { - {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + { PCI_VDEVICE(CX, PCI_DEVICE_ID_CX23418) }, + { } }; MODULE_DEVICE_TABLE(pci, cx18_pci_tbl); diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c index 8dc4ce325935..3a8430f3259e 100644 --- a/drivers/media/pci/cx18/cx18-vbi.c +++ b/drivers/media/pci/cx18/cx18-vbi.c @@ -135,7 +135,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, : VBI_HBLANK_SAMPLES_50HZ; /* find the first valid line */ - for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) { + for (i = hdr_size, buf += hdr_size; i + 3 < size; i++, buf++) { if (buf[0] == 0xff && !buf[1] && !buf[2] && (buf[3] == sliced_vbi_eav_rp[0] || buf[3] == sliced_vbi_eav_rp[1])) diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 9b92e8db494c..5fb26285e4af 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -2279,16 +2279,10 @@ static int __maybe_unused cx23885_resume(struct device *dev_d) static const struct pci_device_id cx23885_pci_tbl[] = { { /* CX23885 */ - .vendor = 0x14f1, - .device = 0x8852, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_DEVICE(0x14f1, 0x8852), }, { /* CX23887 Rev 2 */ - .vendor = 0x14f1, - .device = 0x8880, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_DEVICE(0x14f1, 0x8880), }, { /* --- end of list --- */ } diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 4fdc59aaed8e..f963ae79f685 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -681,8 +681,8 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device, */ static const struct pci_device_id __maybe_unused cx25821_audio_pci_tbl[] = { - {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + { PCI_DEVICE(0x14f1, 0x0920) }, + { } }; MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 5acb1dc00ae8..f883a779b570 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -1347,16 +1347,10 @@ static void cx25821_finidev(struct pci_dev *pci_dev) static const struct pci_device_id cx25821_pci_tbl[] = { { /* CX25821 Athena */ - .vendor = 0x14f1, - .device = 0x8210, - .subvendor = 0x14f1, - .subdevice = 0x0920, + PCI_DEVICE_SUB(0x14f1, 0x8210, 0x14f1, 0x0920), }, { /* CX25821 No Brand */ - .vendor = 0x14f1, - .device = 0x8210, - .subvendor = 0x0000, - .subdevice = 0x0000, + PCI_DEVICE_SUB(0x14f1, 0x8210, 0x0000, 0x0000), }, { /* --- end of list --- */ } diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index dce041a5e47a..d2534f90cfba 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -809,9 +809,9 @@ static const struct snd_kcontrol_new snd_cx88_alc_switch = { */ static const struct pci_device_id cx88_audio_pci_tbl[] = { - {0x14f1, 0x8801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x14f1, 0x8811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0, } + { PCI_DEVICE(0x14f1, 0x8801) }, + { PCI_DEVICE(0x14f1, 0x8811) }, + { } }; MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index 676160e9554d..a399a9bf3b92 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c @@ -787,10 +787,7 @@ static void cx8802_remove(struct pci_dev *pci_dev) static const struct pci_device_id cx8802_pci_tbl[] = { { - .vendor = 0x14f1, - .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_DEVICE(0x14f1, 0x8802), }, { /* --- end of list --- */ } diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index c78b156c5cda..eaa46a2f92e7 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1610,10 +1610,7 @@ static int __maybe_unused cx8800_resume(struct device *dev_d) static const struct pci_device_id cx8800_pci_tbl[] = { { - .vendor = 0x14f1, - .device = 0x8800, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_DEVICE(0x14f1, 0x8800), }, { /* --- end of list --- */ } diff --git a/drivers/media/pci/ddbridge/ddbridge-main.c b/drivers/media/pci/ddbridge/ddbridge-main.c index 363badab7cf0..248ace29e5c8 100644 --- a/drivers/media/pci/ddbridge/ddbridge-main.c +++ b/drivers/media/pci/ddbridge/ddbridge-main.c @@ -269,7 +269,7 @@ static const struct pci_device_id ddb_id_table[] = { DDB_DEVICE_ANY(0x0323), DDB_DEVICE_ANY(0x0328), DDB_DEVICE_ANY(0x0329), - {0} + { } }; MODULE_DEVICE_TABLE(pci, ddb_id_table); diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index f01ecdb0b627..cf50898f9a92 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -14,7 +14,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/dvb/ca.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 80d2e143384b..ae4544042a74 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -1209,15 +1209,9 @@ static void dm1105_remove(struct pci_dev *pdev) static const struct pci_device_id dm1105_id_table[] = { { - .vendor = PCI_VENDOR_ID_TRIGEM, - .device = PCI_DEVICE_ID_DM1105, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_VDEVICE(TRIGEM, PCI_DEVICE_ID_DM1105), }, { - .vendor = PCI_VENDOR_ID_AXESS, - .device = PCI_DEVICE_ID_DM05, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_VDEVICE(AXESS, PCI_DEVICE_ID_DM05), }, { /* empty */ }, diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c index 7bddcbba4cf1..660aab6b62e0 100644 --- a/drivers/media/pci/dt3155/dt3155.c +++ b/drivers/media/pci/dt3155/dt3155.c @@ -577,8 +577,8 @@ static void dt3155_remove(struct pci_dev *pdev) } static const struct pci_device_id pci_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) }, - { 0, /* zero marks the end */ }, + { PCI_VDEVICE(INTEL, DT3155_DEVICE_ID) }, + { /* zero marks the end */ }, }; MODULE_DEVICE_TABLE(pci, pci_ids); diff --git a/drivers/media/pci/hws/hws_v4l2_ioctl.h b/drivers/media/pci/hws/hws_v4l2_ioctl.h index 53044f78d6fa..9a81e940e33e 100644 --- a/drivers/media/pci/hws/hws_v4l2_ioctl.h +++ b/drivers/media/pci/hws/hws_v4l2_ioctl.h @@ -17,14 +17,10 @@ int hws_vidioc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *setfp int hws_vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i); int hws_vidioc_g_input(struct file *file, void *priv, unsigned int *i); int hws_vidioc_s_input(struct file *file, void *priv, unsigned int i); -int hws_vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *a); -int hws_vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a); int hws_vidioc_dv_timings_cap(struct file *file, void *fh, struct v4l2_dv_timings_cap *cap); int hws_vidioc_s_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings); - -int hws_vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a); int hws_vidioc_g_dv_timings(struct file *file, void *fh, struct v4l2_dv_timings *timings); int hws_vidioc_enum_dv_timings(struct file *file, void *fh, diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c index 88581a4c081d..42a309e7218e 100644 --- a/drivers/media/pci/intel/ipu-bridge.c +++ b/drivers/media/pci/intel/ipu-bridge.c @@ -97,6 +97,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), /* Sony IMX471 */ IPU_SENSOR_CONFIG("SONY471A", 1, 200000000), + /* Sony IMX471 (found on Lenovo X1 Carbon G14) */ + IPU_SENSOR_CONFIG("TBE20A0", 1, 200000000), /* Toshiba T4KA3 */ IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000), }; @@ -134,6 +136,52 @@ static const struct dmi_system_id upside_down_sensor_dmi_ids[] = { }, .driver_data = "OVTI02C1", }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "XPS 16 (Dell 16 Premium) DA16250"), + }, + .driver_data = "OVTI02C1", + }, + /* + * The first four characters of DMI_BOARD_NAME identify the Lenovo + * machine type/model. For example, a DMI_BOARD_NAME starting with + * "21Q6" indicates a ThinkPad X9-15. + * + * Reference: https://psref.lenovo.com/ + */ + { + /* Lenovo X9-14 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_BOARD_NAME, "21QA"), + }, + .driver_data = "SONY471A", + }, + { + /* Lenovo X9-14 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_BOARD_NAME, "21QB"), + }, + .driver_data = "SONY471A", + }, + { + /* Lenovo X9-15 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_BOARD_NAME, "21Q6"), + }, + .driver_data = "SONY471A", + }, + { + /* Lenovo X9-15 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_BOARD_NAME, "21Q7"), + }, + .driver_data = "SONY471A", + }, {} /* Terminating entry */ }; @@ -171,6 +219,7 @@ static const struct acpi_device_id ivsc_acpi_ids[] = { { "INTC10DE" }, /* LNL */ { "INTC10E0" }, /* ARL */ { "INTC10E1" }, /* PTL */ + { "INTC10FA" }, /* NVL */ }; static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev) @@ -180,8 +229,8 @@ static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev for (i = 0; i < ARRAY_SIZE(ivsc_acpi_ids); i++) { const struct acpi_device_id *acpi_id = &ivsc_acpi_ids[i]; struct acpi_device *consumer, *ivsc_adev; - acpi_handle handle = acpi_device_handle(ACPI_PTR(adev)); + for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) /* camera sensor depends on IVSC in DSDT if exist */ for_each_acpi_consumer_dev(ivsc_adev, consumer) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 986b9afd7cb5..eb1824ee86fd 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1961,7 +1961,7 @@ static const struct dev_pm_ops cio2_pm_ops = { }; static const struct pci_device_id cio2_pci_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, CIO2_PCI_ID) }, + { PCI_VDEVICE(INTEL, CIO2_PCI_ID) }, { } }; diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index d033d4618169..5449a2006bcc 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -400,7 +400,6 @@ ipu6_isys_init(struct pci_dev *pdev, struct device *parent, &ipdata->hw_variant); if (IS_ERR(isys_adev->mmu)) { put_device(&isys_adev->auxdev.dev); - kfree(pdata); return dev_err_cast_probe(dev, isys_adev->mmu, "ipu6_mmu_init(isys_adev->mmu) failed\n"); } @@ -408,10 +407,8 @@ ipu6_isys_init(struct pci_dev *pdev, struct device *parent, isys_adev->mmu->dev = &isys_adev->auxdev.dev; ret = ipu6_bus_add_device(isys_adev); - if (ret) { - kfree(pdata); + if (ret) return ERR_PTR(ret); - } return isys_adev; } @@ -444,7 +441,6 @@ ipu6_psys_init(struct pci_dev *pdev, struct device *parent, &ipdata->hw_variant); if (IS_ERR(psys_adev->mmu)) { put_device(&psys_adev->auxdev.dev); - kfree(pdata); return dev_err_cast_probe(&pdev->dev, psys_adev->mmu, "ipu6_mmu_init(psys_adev->mmu) failed\n"); } @@ -452,10 +448,8 @@ ipu6_psys_init(struct pci_dev *pdev, struct device *parent, psys_adev->mmu->dev = &psys_adev->auxdev.dev; ret = ipu6_bus_add_device(psys_adev); - if (ret) { - kfree(pdata); + if (ret) return ERR_PTR(ret); - } return psys_adev; } diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index e0091a8e5c88..b9ea56ec9593 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -60,11 +60,9 @@ EXPORT_SYMBOL(ivtv_ext_init); /* add your revision and whatnot here */ static const struct pci_device_id ivtv_pci_tbl[] = { - {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + { PCI_VDEVICE(ICOMP, PCI_DEVICE_ID_IVTV15) }, + { PCI_VDEVICE(ICOMP, PCI_DEVICE_ID_IVTV16) }, + { } }; MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c index ae7a00f46257..af086c4cbe1a 100644 --- a/drivers/media/pci/ivtv/ivtv-vbi.c +++ b/drivers/media/pci/ivtv/ivtv-vbi.c @@ -330,7 +330,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 unsigned lines = 0; /* find the first valid line */ - for (i = 0; i < size; i++, buf++) { + for (i = 0; i + 3 < size; i++, buf++) { if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) break; } diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h index 6e563ecd94e8..f357ca268dd1 100644 --- a/drivers/media/pci/mantis/mantis_common.h +++ b/drivers/media/pci/mantis/mantis_common.h @@ -58,11 +58,9 @@ #define TERRATEC 0x153b #define MAKE_ENTRY(__subven, __subdev, __configptr, __rc) { \ - .vendor = TWINHAN_TECHNOLOGIES, \ - .device = MANTIS, \ - .subvendor = (__subven), \ - .subdevice = (__subdev), \ - .driver_data = (unsigned long) \ + PCI_DEVICE_SUB(TWINHAN_TECHNOLOGIES, MANTIS, \ + (__subven), (__subdev)), \ + .driver_data = (unsigned long) \ &(struct mantis_pci_drvdata){__configptr, __rc} \ } diff --git a/drivers/media/pci/mgb4/mgb4_core.c b/drivers/media/pci/mgb4/mgb4_core.c index d23d854581c5..cbd193e06536 100644 --- a/drivers/media/pci/mgb4/mgb4_core.c +++ b/drivers/media/pci/mgb4/mgb4_core.c @@ -694,9 +694,9 @@ static void mgb4_remove(struct pci_dev *pdev) } static const struct pci_device_id mgb4_pci_ids[] = { - { PCI_DEVICE(DIGITEQ_VID, T100_DID), }, - { PCI_DEVICE(DIGITEQ_VID, T200_DID), }, - { 0, } + { PCI_DEVICE(DIGITEQ_VID, T100_DID) }, + { PCI_DEVICE(DIGITEQ_VID, T200_DID) }, + { } }; MODULE_DEVICE_TABLE(pci, mgb4_pci_ids); diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index ec08023b5d5e..00f81e4c8e8d 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -1014,7 +1014,7 @@ static void netup_unidvb_finidev(struct pci_dev *pci_dev) static const struct pci_device_id netup_unidvb_pci_tbl[] = { { PCI_DEVICE(0x1b55, 0x18f6) }, /* hw rev. 1.3 */ { PCI_DEVICE(0x1b55, 0x18f7) }, /* hw rev. 1.4 */ - { 0, } + { } }; MODULE_DEVICE_TABLE(pci, netup_unidvb_pci_tbl); diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index 7dbc21e1a2ca..a1a83f3bb6b4 100644 --- a/drivers/media/pci/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -1155,8 +1155,7 @@ static const struct ngene_info ngene_info_terratec = { /****************************************************************************/ #define NGENE_ID(_subvend, _subdev, _driverdata) { \ - .vendor = NGENE_VID, .device = NGENE_PID, \ - .subvendor = _subvend, .subdevice = _subdev, \ + PCI_DEVICE_SUB(NGENE_VID, NGENE_PID, (_subvend), (_subdev)), \ .driver_data = (unsigned long) &_driverdata } /****************************************************************************/ @@ -1173,7 +1172,7 @@ static const struct pci_device_id ngene_id_tbl[] = { NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), NGENE_ID(0x1461, 0x062e, ngene_info_m780), NGENE_ID(0x153b, 0x1167, ngene_info_terratec), - {0} + { } }; MODULE_DEVICE_TABLE(pci, ngene_id_tbl); diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 22c2222d5c4d..77b3e4eec54d 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -762,10 +762,7 @@ static void pluto2_remove(struct pci_dev *pdev) static const struct pci_device_id pluto2_id_table[] = { { - .vendor = PCI_VENDOR_ID_SCM, - .device = PCI_DEVICE_ID_PLUTO2, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_VDEVICE(SCM, PCI_DEVICE_ID_PLUTO2), }, { /* empty */ }, diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index e80fb4ebfda6..a7d665407460 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -5800,1317 +5800,758 @@ const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); struct pci_device_id saa7134_pci_tbl[] = { { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2001, - .driver_data = SAA7134_BOARD_PROTEUS_PRO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2001, - .driver_data = SAA7134_BOARD_PROTEUS_PRO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x6752, - .driver_data = SAA7134_BOARD_EMPRESS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1131, - .subdevice = 0x4e85, - .driver_data = SAA7134_BOARD_MONSTERTV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153b, - .subdevice = 0x1142, - .driver_data = SAA7134_BOARD_CINERGY400, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153b, - .subdevice = 0x1143, - .driver_data = SAA7134_BOARD_CINERGY600, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x153b, - .subdevice = 0x1158, - .driver_data = SAA7134_BOARD_CINERGY600_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x153b, - .subdevice = 0x1162, - .driver_data = SAA7134_BOARD_CINERGY400_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5169, - .subdevice = 0x0138, - .driver_data = SAA7134_BOARD_FLYVIDEO3000_NTSC, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5168, - .subdevice = 0x0138, - .driver_data = SAA7134_BOARD_FLYVIDEO3000, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x4e42, /* "Typhoon PCI Capture TV Card" Art.No. 50673 */ - .subdevice = 0x0138, - .driver_data = SAA7134_BOARD_FLYVIDEO3000, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x5168, - .subdevice = 0x0138, - .driver_data = SAA7134_BOARD_FLYVIDEO2000, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x4e42, /* Typhoon */ - .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ - .driver_data = SAA7134_BOARD_FLYVIDEO2000, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x0212, /* minipci, LR212 */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x14c0, - .subdevice = 0x1212, /* minipci, LR1212 */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI2, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4e42, - .subdevice = 0x0212, /* OEM minipci, LR212 */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1489, /* KYE */ - .subdevice = 0x0214, /* Genius VideoWonder ProTV */ - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */ - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x16be, - .subdevice = 0x0003, - .driver_data = SAA7134_BOARD_MD7134, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x16be, /* CTX946 analog TV, HW mpeg, DVB-T */ - .subdevice = 0x5000, /* only analog TV and DVB-T for now */ - .driver_data = SAA7134_BOARD_MD7134, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1048, - .subdevice = 0x226b, - .driver_data = SAA7134_BOARD_ELSA, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1048, - .subdevice = 0x226a, - .driver_data = SAA7134_BOARD_ELSA_500TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1048, - .subdevice = 0x226c, - .driver_data = SAA7134_BOARD_ELSA_700TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_ASUSTEK, - .subdevice = 0x4842, - .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_VENDOR_ID_ASUSTEK, - .subdevice = 0x4845, - .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7135, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_ASUSTEK, - .subdevice = 0x4830, - .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_VENDOR_ID_ASUSTEK, - .subdevice = 0x4843, - .driver_data = SAA7134_BOARD_ASUSTEK_TVFM7133, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_ASUSTEK, - .subdevice = 0x4840, - .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0xfe01, - .driver_data = SAA7134_BOARD_TVSTATION_RDS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1894, - .subdevice = 0xfe01, - .driver_data = SAA7134_BOARD_TVSTATION_RDS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1894, - .subdevice = 0xa006, - .driver_data = SAA7134_BOARD_TVSTATION_DVR, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1131, - .subdevice = 0x7133, - .driver_data = SAA7134_BOARD_VA1000POWER, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2001, - .driver_data = SAA7134_BOARD_10MOONSTVMASTER, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x185b, - .subdevice = 0xc100, - .driver_data = SAA7134_BOARD_VIDEOMATE_TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x185b, - .subdevice = 0xc100, - .driver_data = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_MATROX, - .subdevice = 0x48d0, - .driver_data = SAA7134_BOARD_CRONOS_PLUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa70b, - .driver_data = SAA7134_BOARD_MD2819, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa7a1, - .driver_data = SAA7134_BOARD_AVERMEDIA_A700_PRO, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa7a2, - .driver_data = SAA7134_BOARD_AVERMEDIA_A700_HYBRID, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x2115, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa115, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_505, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x2108, - .driver_data = SAA7134_BOARD_AVERMEDIA_305, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x10ff, - .driver_data = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER, - },{ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_PHILIPS, 0x2001), + .driver_data = SAA7134_BOARD_PROTEUS_PRO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, + PCI_VENDOR_ID_PHILIPS, 0x2001), + .driver_data = SAA7134_BOARD_PROTEUS_PRO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_PHILIPS, 0x6752), + .driver_data = SAA7134_BOARD_EMPRESS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1131, 0x4e85), + .driver_data = SAA7134_BOARD_MONSTERTV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x153b, 0x1142), + .driver_data = SAA7134_BOARD_CINERGY400, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x153b, 0x1143), + .driver_data = SAA7134_BOARD_CINERGY600, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x153b, 0x1158), + .driver_data = SAA7134_BOARD_CINERGY600_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x153b, 0x1162), + .driver_data = SAA7134_BOARD_CINERGY400_CARDBUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5169, 0x0138), + .driver_data = SAA7134_BOARD_FLYVIDEO3000_NTSC, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5168, 0x0138), + .driver_data = SAA7134_BOARD_FLYVIDEO3000, + }, { + /* "Typhoon PCI Capture TV Card" Art.No. 50673 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x4e42, 0x0138), + .driver_data = SAA7134_BOARD_FLYVIDEO3000, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x5168, 0x0138), + .driver_data = SAA7134_BOARD_FLYVIDEO2000, + }, { + /* Typhoon LifeView FlyTV Prime30 OEM */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x4e42, 0x0138), + .driver_data = SAA7134_BOARD_FLYVIDEO2000, + }, { + /* minipci, LR212 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0212), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, + }, { + /* minipci, LR1212 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x14c0, 0x1212), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI2, + }, { + /* OEM minipci, LR212 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x4e42, 0x0212), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, + }, { + /* + * Animation Technologies (LifeView) + * Standard PCI, LR214 Rev E and earlier (SAA7135) + */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0214), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + }, { + /* + * Animation Technologies (LifeView) + * Standard PCI, LR214 Rev F onwards (SAA7131) + */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x5214), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + }, { + /* KYE Genius VideoWonder ProTV */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1489, 0x0214), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */ + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x16be, 0x0003), + .driver_data = SAA7134_BOARD_MD7134, + }, { + /* CTX946 analog TV, HW mpeg, DVB-T; only analog TV and DVB-T for now */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x16be, 0x5000), + .driver_data = SAA7134_BOARD_MD7134, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1048, 0x226b), + .driver_data = SAA7134_BOARD_ELSA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1048, 0x226a), + .driver_data = SAA7134_BOARD_ELSA_500TV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1048, 0x226c), + .driver_data = SAA7134_BOARD_ELSA_700TV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_ASUSTEK, 0x4842), + .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, + PCI_VENDOR_ID_ASUSTEK, 0x4845), + .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7135, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_ASUSTEK, 0x4830), + .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, + PCI_VENDOR_ID_ASUSTEK, 0x4843), + .driver_data = SAA7134_BOARD_ASUSTEK_TVFM7133, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_ASUSTEK, 0x4840), + .driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_PHILIPS, 0xfe01), + .driver_data = SAA7134_BOARD_TVSTATION_RDS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1894, 0xfe01), + .driver_data = SAA7134_BOARD_TVSTATION_RDS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1894, 0xa006), + .driver_data = SAA7134_BOARD_TVSTATION_DVR, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1131, 0x7133), + .driver_data = SAA7134_BOARD_VA1000POWER, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_PHILIPS, 0x2001), + .driver_data = SAA7134_BOARD_10MOONSTVMASTER, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x185b, 0xc100), + .driver_data = SAA7134_BOARD_VIDEOMATE_TV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x185b, 0xc100), + .driver_data = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_MATROX, 0x48d0), + .driver_data = SAA7134_BOARD_CRONOS_PLUS, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0xa70b), + .driver_data = SAA7134_BOARD_MD2819, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xa7a1), + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_PRO, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xa7a2), + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_HYBRID, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0x2115), + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0xa115), + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_505, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0x2108), + .driver_data = SAA7134_BOARD_AVERMEDIA_305, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0x10ff), + .driver_data = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER, + }, { /* AVerMedia CardBus */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xd6ee, - .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS, - },{ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0xd6ee), + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS, + }, { /* AVerMedia CardBus */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xb7e9, - .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_501, + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0xb7e9), + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_501, }, { - /* TransGear 3000TV */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x050c, - .driver_data = SAA7134_BOARD_TG3000TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x11bd, - .subdevice = 0x002b, - .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x11bd, - .subdevice = 0x002d, - .driver_data = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1019, - .subdevice = 0x4cb4, - .driver_data = SAA7134_BOARD_ECS_TVP3XP, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1019, - .subdevice = 0x4cb5, - .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1019, - .subdevice = 0x4cb6, - .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x12ab, - .subdevice = 0x0800, - .driver_data = SAA7134_BOARD_UPMOST_PURPLE_TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x153b, - .subdevice = 0x1152, - .driver_data = SAA7134_BOARD_CINERGY200, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x185b, - .subdevice = 0xc100, - .driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x9715, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_307, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa70a, - .driver_data = SAA7134_BOARD_AVERMEDIA_307, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x185b, - .subdevice = 0xc200, - .driver_data = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1540, - .subdevice = 0x9524, - .driver_data = SAA7134_BOARD_PROVIDEO_PV952, - - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x0502, /* Cardbus version */ - .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x0306, /* PCI version */ - .driver_data = SAA7134_BOARD_FLYDVBTDUO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf31f, - .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM, - - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf11d, - .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x4155, - .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x4255, - .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2004, - .driver_data = SAA7134_BOARD_PHILIPS_TOUGH, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1421, - .subdevice = 0x0350, /* PCI version */ - .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1421, - .subdevice = 0x0351, /* PCI version, new revision */ - .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1421, - .subdevice = 0x0370, /* cardbus version */ - .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1421, - .subdevice = 0x1370, /* cardbus version */ - .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, - - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4e42, /* Typhoon */ - .subdevice = 0x0502, /* LifeView LR502 OEM */ - .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x0210, /* mini pci NTSC version */ - .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1043, - .subdevice = 0x0210, /* mini pci PAL/SECAM version */ - .driver_data = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV, - - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ - .subdevice = 0x4091, - .driver_data = SAA7134_BOARD_BEHOLD_409FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5456, /* GoTView */ - .subdevice = 0x7135, - .driver_data = SAA7134_BOARD_GOTVIEW_7135, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2004, - .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x185b, - .subdevice = 0xc900, - .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x185b, - .subdevice = 0xc901, - .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7350, - .driver_data = SAA7134_BOARD_RTD_VFG7350, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7330, - .driver_data = SAA7134_BOARD_RTD_VFG7330, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, - .subdevice = 0x1044, - .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1131, - .subdevice = 0x4ee9, - .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x11bd, - .subdevice = 0x002e, - .driver_data = SAA7134_BOARD_PINNACLE_PCTV_110i, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4862, - .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2018, - .driver_data = SAA7134_BOARD_PHILIPS_TIGER, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1462, - .subdevice = 0x6231, /* tda8275a, ks003 IR */ - .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1462, - .subdevice = 0x8624, /* tda8275, ks003 IR */ - .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x153b, - .subdevice = 0x1160, - .driver_data = SAA7134_BOARD_CINERGY250PCI, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA 7131E */ - .subvendor = 0x5168, - .subdevice = 0x0319, - .driver_data = SAA7134_BOARD_FLYDVB_TRIO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, - .subdevice = 0x2c05, - .driver_data = SAA7134_BOARD_AVERMEDIA_777, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5168, - .subdevice = 0x0301, - .driver_data = SAA7134_BOARD_FLYDVBT_LR301, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0331, - .subdevice = 0x1421, - .driver_data = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x17de, - .subdevice = 0x7201, - .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x17de, - .subdevice = 0x7250, - .driver_data = SAA7134_BOARD_KWORLD_DVBT_210, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ - .subvendor = 0x17de, - .subdevice = 0x7350, - .driver_data = SAA7134_BOARD_KWORLD_ATSC110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ - .subvendor = 0x17de, - .subdevice = 0x7352, - .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ - .subvendor = 0x17de, - .subdevice = 0xa134, - .driver_data = SAA7134_BOARD_KWORLD_PC150U, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, - .subdevice = 0x7360, - .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, - .subdevice = 0x6360, - .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B1, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x16be, - .subdevice = 0x0005, - .driver_data = SAA7134_BOARD_MD7134_BRIDGE_2, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5168, - .subdevice = 0x0300, - .driver_data = SAA7134_BOARD_FLYDVBS_LR300, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x4e42, - .subdevice = 0x0300,/* LR300 */ - .driver_data = SAA7134_BOARD_FLYDVBS_LR300, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1489, - .subdevice = 0x0301, + /* AVerMedia TransGear 3000TV */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0x050c), + .driver_data = SAA7134_BOARD_TG3000TV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x11bd, 0x002b), + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x11bd, 0x002d), + .driver_data = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1019, 0x4cb4), + .driver_data = SAA7134_BOARD_ECS_TVP3XP, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1019, 0x4cb5), + .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1019, 0x4cb6), + .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x12ab, 0x0800), + .driver_data = SAA7134_BOARD_UPMOST_PURPLE_TV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x153b, 0x1152), + .driver_data = SAA7134_BOARD_CINERGY200, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x185b, 0xc100), + .driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0x9715), + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_307, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0xa70a), + .driver_data = SAA7134_BOARD_AVERMEDIA_307, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x185b, 0xc200), + .driver_data = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1540, 0x9524), + .driver_data = SAA7134_BOARD_PROVIDEO_PV952, + }, { + /* Cardbus version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0502), + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, + }, { + /* PCI version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0306), + .driver_data = SAA7134_BOARD_FLYDVBTDUO, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf31f), + .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf11d), + .driver_data = SAA7134_BOARD_AVERMEDIA_M135A, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x4155), + .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x4255), + .driver_data = SAA7134_BOARD_AVERMEDIA_M733A, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_PHILIPS, 0x2004), + .driver_data = SAA7134_BOARD_PHILIPS_TOUGH, + }, { + /* PCI version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1421, 0x0350), + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + }, { + /* PCI version, new revision */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1421, 0x0351), + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + }, { + /* cardbus version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1421, 0x0370), + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + }, { + /* cardbus version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1421, 0x1370), + .driver_data = SAA7134_BOARD_ADS_INSTANT_TV, + }, { + /* Typhoon LifeView LR502 OEM */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x4e42, 0x0502), + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, + }, { + /* mini pci NTSC version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x0210), + .driver_data = SAA7134_BOARD_FLYTV_DIGIMATRIX, + }, { + /* mini pci PAL/SECAM version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1043, 0x0210), + .driver_data = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV, + }, { + /* subvendor == 0 shouldn't break anything, since subdevice id seems unique */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0000, 0x4091), + .driver_data = SAA7134_BOARD_BEHOLD_409FM, + }, { + /* GoTView */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5456, 0x7135), + .driver_data = SAA7134_BOARD_GOTVIEW_7135, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_PHILIPS, 0x2004), + .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x185b, 0xc900), + .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x185b, 0xc901), + .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1435, 0x7350), + .driver_data = SAA7134_BOARD_RTD_VFG7350, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1435, 0x7330), + .driver_data = SAA7134_BOARD_RTD_VFG7330, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x1044), + .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1131, 0x4ee9), + .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x11bd, 0x002e), + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_110i, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x4862), + .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, + PCI_VENDOR_ID_PHILIPS, 0x2018), + .driver_data = SAA7134_BOARD_PHILIPS_TIGER, + }, { + /* tda8275a, ks003 IR */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1462, 0x6231), + .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, + }, { + /* tda8275, ks003 IR */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1462, 0x8624), + .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x153b, 0x1160), + .driver_data = SAA7134_BOARD_CINERGY250PCI, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0319), + .driver_data = SAA7134_BOARD_FLYDVB_TRIO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0x2c05), + .driver_data = SAA7134_BOARD_AVERMEDIA_777, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5168, 0x0301), .driver_data = SAA7134_BOARD_FLYDVBT_LR301, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x0304, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0331, 0x1421), + .driver_data = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0x7201), + .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0x7250), + .driver_data = SAA7134_BOARD_KWORLD_DVBT_210, + }, { + /* SAA7135HL */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0x7350), + .driver_data = SAA7134_BOARD_KWORLD_ATSC110, + }, { + /* SAA7135HL */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0x7352), + .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ + }, { + /* SAA7135HL */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0xa134), + .driver_data = SAA7134_BOARD_KWORLD_PC150U, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0x7360), + .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0x6360), + .driver_data = SAA7134_BOARD_AVERMEDIA_A169_B1, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x16be, 0x0005), + .driver_data = SAA7134_BOARD_MD7134_BRIDGE_2, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5168, 0x0300), + .driver_data = SAA7134_BOARD_FLYDVBS_LR300, + }, { + /* LR300 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x4e42, 0x0300), + .driver_data = SAA7134_BOARD_FLYDVBS_LR300, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1489, 0x0301), + .driver_data = SAA7134_BOARD_FLYDVBT_LR301, + }, { + /* Animation Technologies (LifeView) */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x0304), .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x3306, - .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x3502, /* what's the difference to 0x3306 ?*/ - .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5168, - .subdevice = 0x3307, /* FlyDVB-T Hybrid Mini PCI */ - .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x16be, - .subdevice = 0x0007, - .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x16be, - .subdevice = 0x0008, - .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x16be, - .subdevice = 0x000d, /* triple CTX948_V1.1.1 */ - .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, - .subdevice = 0x2c05, - .driver_data = SAA7134_BOARD_AVERMEDIA_777, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1489, - .subdevice = 0x0502, /* Cardbus version */ - .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0919, /* Philips Proteus PRO 2309 */ - .subdevice = 0x2003, - .driver_data = SAA7134_BOARD_PROTEUS_2309, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, - .subdevice = 0x2c00, - .driver_data = SAA7134_BOARD_AVERMEDIA_A16AR, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1043, - .subdevice = 0x4860, - .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x11bd, - .subdevice = 0x002f, - .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x9715, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa11b, - .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4876, - .driver_data = SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6700, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6701, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6702, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6703, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6704, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6705, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6706, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6707, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6708, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x6709, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0070, - .subdevice = 0x670a, - .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x153b, - .subdevice = 0x1172, - .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2342, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1131, - .subdevice = 0x2341, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x3016, - .subdevice = 0x2344, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1131, - .subdevice = 0x230f, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1a7f, - .subdevice = 0x2008, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1a7f, - .subdevice = 0x2108, - .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM3, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x153b, - .subdevice = 0x1175, - .driver_data = SAA7134_BOARD_CINERGY_HT_PCI, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf31e, - .driver_data = SAA7134_BOARD_AVERMEDIA_M102, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4E42, /* MSI */ - .subdevice = 0x0306, /* TV@nywhere DUO */ - .driver_data = SAA7134_BOARD_FLYDVBTDUO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4871, - .driver_data = SAA7134_BOARD_ASUS_P7131_4871, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4857, /* REV:1.00 */ - .driver_data = SAA7134_BOARD_ASUSTeK_TIGER, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */ - .subdevice = 0x2003, /* OEM cardbus */ - .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2304, - .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf01d, /* AVerTV DVB-T Super 007 */ - .driver_data = SAA7134_BOARD_AVERMEDIA_SUPER_007, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x4016, - .driver_data = SAA7134_BOARD_BEHOLD_401, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x0000, - .subdevice = 0x4036, - .driver_data = SAA7134_BOARD_BEHOLD_403, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x0000, - .subdevice = 0x4037, - .driver_data = SAA7134_BOARD_BEHOLD_403FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x4050, - .driver_data = SAA7134_BOARD_BEHOLD_405, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x4051, - .driver_data = SAA7134_BOARD_BEHOLD_405FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x0000, - .subdevice = 0x4070, - .driver_data = SAA7134_BOARD_BEHOLD_407, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x0000, - .subdevice = 0x4071, - .driver_data = SAA7134_BOARD_BEHOLD_407FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0000, - .subdevice = 0x4090, - .driver_data = SAA7134_BOARD_BEHOLD_409, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x505B, - .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK5, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x0000, - .subdevice = 0x5051, - .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x5ace, - .subdevice = 0x5050, - .driver_data = SAA7134_BOARD_BEHOLD_505FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0000, - .subdevice = 0x5071, - .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0000, - .subdevice = 0x507B, - .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5ace, - .subdevice = 0x5070, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x5090, - .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x0000, - .subdevice = 0x5201, - .driver_data = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5ace, - .subdevice = 0x6070, - .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5ace, - .subdevice = 0x6071, - .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5ace, - .subdevice = 0x6072, - .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x5ace, - .subdevice = 0x6073, - .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6090, - .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6091, - .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6092, - .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK3, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6093, - .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK5, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6190, - .driver_data = SAA7134_BOARD_BEHOLD_M6, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6193, - .driver_data = SAA7134_BOARD_BEHOLD_M6_EXTRA, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6191, - .driver_data = SAA7134_BOARD_BEHOLD_M63, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x4e42, - .subdevice = 0x3502, - .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ - .subdevice = 0x0022, - .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x16be, - .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ - .driver_data = SAA7134_BOARD_CREATIX_CTX953, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1462, /* MSI */ - .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ - .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf436, - .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf936, - .driver_data = SAA7134_BOARD_AVERMEDIA_A16D, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa836, - .driver_data = SAA7134_BOARD_AVERMEDIA_M115, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x185b, - .subdevice = 0xc900, - .driver_data = SAA7134_BOARD_VIDEOMATE_T750, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ - .subvendor = 0x1421, - .subdevice = 0x0380, - .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5169, - .subdevice = 0x1502, - .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x6290, - .driver_data = SAA7134_BOARD_BEHOLD_H6, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf636, - .driver_data = SAA7134_BOARD_AVERMEDIA_M103, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf736, - .driver_data = SAA7134_BOARD_AVERMEDIA_M103, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x4878, /* REV:1.02G */ - .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1043, - .subdevice = 0x48cd, - .driver_data = SAA7134_BOARD_ASUSTeK_PS3_100, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x17de, - .subdevice = 0x7128, - .driver_data = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x17de, - .subdevice = 0xb136, - .driver_data = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xf31d, - .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x185b, - .subdevice = 0xc900, - .driver_data = SAA7134_BOARD_VIDEOMATE_S350, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ - .subdevice = 0x7595, - .driver_data = SAA7134_BOARD_BEHOLD_X7, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x19d1, /* RoverMedia */ - .subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */ - .driver_data = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0x2004, - .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x1043, - .subdevice = 0x4847, - .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x107d, - .subdevice = 0x6655, - .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x13c2, - .subdevice = 0x2804, - .driver_data = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ - .subdevice = 0x7190, - .driver_data = SAA7134_BOARD_BEHOLD_H7, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, /* Beholder Intl. Ltd. */ - .subdevice = 0x7090, - .driver_data = SAA7134_BOARD_BEHOLD_A7, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7135, - .subvendor = 0x185b, - .subdevice = 0xc900, - .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5ace, - .subdevice = 0x5030, - .driver_data = SAA7134_BOARD_BEHOLD_503FM, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x5ace, - .subdevice = 0x5010, - .driver_data = SAA7134_BOARD_BEHOLD_501, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = 0x17de, - .subdevice = 0xd136, - .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x6000, - .subdevice = 0x0811, - .driver_data = SAA7134_BOARD_SENSORAY811_911, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x6000, - .subdevice = 0x0911, - .driver_data = SAA7134_BOARD_SENSORAY811_911, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0x2055, /* AverTV Satellite Hybrid+FM A706 */ - .driver_data = SAA7134_BOARD_AVERMEDIA_A706, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1905, /* WIS */ - .subdevice = 0x7007, - .driver_data = SAA7134_BOARD_WIS_VOYAGER, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x1461, /* Avermedia Technologies Inc */ - .subdevice = 0xa10a, - .driver_data = SAA7134_BOARD_AVERMEDIA_505, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = 0x107d, - .subdevice = 0x6f3a, - .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1779, /* V One Multimedia PTE Ltd */ - .subdevice = 0x13cf, - .driver_data = SAA7134_BOARD_SNAZIO_TVPVR_PRO, - }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x107d, - .subdevice = 0x6f2e, - .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_HDTV200_H, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x3306), + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { + /* what's the difference to .subdevice = 0x3306 above? */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x3502), + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { + /* FlyDVB-T Hybrid Mini PCI */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5168, 0x3307), + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x16be, 0x0007), + .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x16be, 0x0008), + .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, + }, { + /* triple CTX948_V1.1.1 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x16be, 0x000d), + .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x2c05), + .driver_data = SAA7134_BOARD_AVERMEDIA_777, + }, { + /* Cardbus version */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1489, 0x0502), + .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS, + }, { + /* Philips Proteus PRO 2309 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0919, 0x2003), + .driver_data = SAA7134_BOARD_PROTEUS_2309, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0x2c00), + .driver_data = SAA7134_BOARD_AVERMEDIA_A16AR, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1043, 0x4860), + .driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x11bd, 0x002f), + .driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x9715), + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1461, 0xa11b), + .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x4876), + .driver_data = SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6700), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6701), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6702), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6703), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6704), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6705), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6706), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6707), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6708), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1150, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x6709), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0070, 0x670a), + .driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1120, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x153b, 0x1172), + .driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_PHILIPS, 0x2342), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1131, 0x2341), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x3016, 0x2344), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1131, 0x230f), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1a7f, 0x2008), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM53, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1a7f, 0x2108), + .driver_data = SAA7134_BOARD_ENCORE_ENLTV_FM3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x153b, 0x1175), + .driver_data = SAA7134_BOARD_CINERGY_HT_PCI, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf31e), + .driver_data = SAA7134_BOARD_AVERMEDIA_M102, + }, { + /* MSI TV@nywhere DUO */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x4E42, 0x0306), + .driver_data = SAA7134_BOARD_FLYDVBTDUO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x4871), + .driver_data = SAA7134_BOARD_ASUS_P7131_4871, + }, { + /* REV:1.00 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x4857), + .driver_data = SAA7134_BOARD_ASUSTeK_TIGER, + }, { + /* SinoVideo PCI 2309 Proteus (7134) OEM cardbus */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x0919, 0x2003), + .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_PHILIPS, 0x2304), + .driver_data = SAA7134_BOARD_10MOONSTVMASTER3, + }, { + /* Avermedia Technologies Inc AVerTV DVB-T Super 007 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf01d), + .driver_data = SAA7134_BOARD_AVERMEDIA_SUPER_007, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0000, 0x4016), + .driver_data = SAA7134_BOARD_BEHOLD_401, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x0000, 0x4036), + .driver_data = SAA7134_BOARD_BEHOLD_403, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x0000, 0x4037), + .driver_data = SAA7134_BOARD_BEHOLD_403FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0000, 0x4050), + .driver_data = SAA7134_BOARD_BEHOLD_405, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0000, 0x4051), + .driver_data = SAA7134_BOARD_BEHOLD_405FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x0000, 0x4070), + .driver_data = SAA7134_BOARD_BEHOLD_407, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x0000, 0x4071), + .driver_data = SAA7134_BOARD_BEHOLD_407FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0000, 0x4090), + .driver_data = SAA7134_BOARD_BEHOLD_409, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0000, 0x505B), + .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x0000, 0x5051), + .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x5ace, 0x5050), + .driver_data = SAA7134_BOARD_BEHOLD_505FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0000, 0x5071), + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0000, 0x507B), + .driver_data = SAA7134_BOARD_BEHOLD_507RDS_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5ace, 0x5070), + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x5090), + .driver_data = SAA7134_BOARD_BEHOLD_507_9FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x0000, 0x5201), + .driver_data = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5ace, 0x6070), + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5ace, 0x6071), + .driver_data = SAA7134_BOARD_BEHOLD_607FM_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5ace, 0x6072), + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x5ace, 0x6073), + .driver_data = SAA7134_BOARD_BEHOLD_607RDS_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6090), + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6091), + .driver_data = SAA7134_BOARD_BEHOLD_609FM_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6092), + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK3, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6093), + .driver_data = SAA7134_BOARD_BEHOLD_609RDS_MK5, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6190), + .driver_data = SAA7134_BOARD_BEHOLD_M6, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6193), + .driver_data = SAA7134_BOARD_BEHOLD_M6_EXTRA, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6191), + .driver_data = SAA7134_BOARD_BEHOLD_M63, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x4e42, 0x3502), + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { + /*Twinhan Technology Co. Ltd*/ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1822, 0x0022), + .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, + }, { + /* Medion version CTX953_V.1.4.3 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x16be, 0x0010), + .driver_data = SAA7134_BOARD_CREATIX_CTX953, + }, { + /* MSI TV@nywhere A/D v1.1 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1462, 0x8625), + .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf436), + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf936), + .driver_data = SAA7134_BOARD_AVERMEDIA_A16D, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xa836), + .driver_data = SAA7134_BOARD_AVERMEDIA_M115, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x185b, 0xc900), + .driver_data = SAA7134_BOARD_VIDEOMATE_T750, + }, { + /* SAA7135HL */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1421, 0x0380), + .driver_data = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5169, 0x1502), + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x6290), + .driver_data = SAA7134_BOARD_BEHOLD_H6, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf636), + .driver_data = SAA7134_BOARD_AVERMEDIA_M103, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf736), + .driver_data = SAA7134_BOARD_AVERMEDIA_M103, + }, { + /* REV:1.02G */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x4878), + .driver_data = SAA7134_BOARD_ASUSTeK_TIGER_3IN1, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1043, 0x48cd), + .driver_data = SAA7134_BOARD_ASUSTeK_PS3_100, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x17de, 0x7128), + .driver_data = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x17de, 0xb136), + .driver_data = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0xf31d), + .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x185b, 0xc900), + .driver_data = SAA7134_BOARD_VIDEOMATE_S350, + }, { + /* Beholder Intl. Ltd. */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x7595), + .driver_data = SAA7134_BOARD_BEHOLD_X7, + }, { + /* RoverMedia LifeView FlyTV Prime30 OEM */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x19d1, 0x0138), + .driver_data = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, + PCI_VENDOR_ID_PHILIPS, 0x2004), + .driver_data = SAA7134_BOARD_ZOLID_HYBRID_PCI, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x1043, 0x4847), + .driver_data = SAA7134_BOARD_ASUS_EUROPA_HYBRID, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x107d, 0x6655), + .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x13c2, 0x2804), + .driver_data = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000, + }, { + /* Beholder Intl. Ltd. */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x7190), + .driver_data = SAA7134_BOARD_BEHOLD_H7, + }, { + /* Beholder Intl. Ltd. */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x7090), + .driver_data = SAA7134_BOARD_BEHOLD_A7, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7135, 0x185b, 0xc900), + .driver_data = SAA7134_BOARD_VIDEOMATE_M1F, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x5ace, 0x5030), + .driver_data = SAA7134_BOARD_BEHOLD_503FM, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x5ace, 0x5010), + .driver_data = SAA7134_BOARD_BEHOLD_501, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, 0x17de, 0xd136), + .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x6000, 0x0811), + .driver_data = SAA7134_BOARD_SENSORAY811_911, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x6000, 0x0911), + .driver_data = SAA7134_BOARD_SENSORAY811_911, + }, { + /* Avermedia Technologies Inc AverTV Satellite Hybrid+FM A706 */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1461, 0x2055), + .driver_data = SAA7134_BOARD_AVERMEDIA_A706, + }, { + /* WIS */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1905, 0x7007), + .driver_data = SAA7134_BOARD_WIS_VOYAGER, + }, { + /* Avermedia Technologies Inc */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x1461, 0xa10a), + .driver_data = SAA7134_BOARD_AVERMEDIA_505, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, 0x107d, 0x6f3a), + .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_TV2100_FM, + }, { + /* V One Multimedia PTE Ltd */ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x1779, 0x13cf), + .driver_data = SAA7134_BOARD_SNAZIO_TVPVR_PRO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133, 0x107d, 0x6f2e), + .driver_data = SAA7134_BOARD_LEADTEK_WINFAST_HDTV200_H, }, { /* --- boards without eeprom + subsystem ID --- */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0, - .driver_data = SAA7134_BOARD_NOAUTO, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_VENDOR_ID_PHILIPS, - .subdevice = 0, - .driver_data = SAA7134_BOARD_NOAUTO, - },{ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134, + PCI_VENDOR_ID_PHILIPS, 0), + .driver_data = SAA7134_BOARD_NOAUTO, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130, + PCI_VENDOR_ID_PHILIPS, 0), + .driver_data = SAA7134_BOARD_NOAUTO, + }, { /* --- default catch --- */ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7130, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SAA7134_BOARD_UNKNOWN, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SAA7134_BOARD_UNKNOWN, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7134, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SAA7134_BOARD_UNKNOWN, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7135, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = SAA7134_BOARD_UNKNOWN, - },{ + PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7130), + .driver_data = SAA7134_BOARD_UNKNOWN, + }, { + PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7133), + .driver_data = SAA7134_BOARD_UNKNOWN, + }, { + PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7134), + .driver_data = SAA7134_BOARD_UNKNOWN, + }, { + PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7135), + .driver_data = SAA7134_BOARD_UNKNOWN, + }, { /* --- end of list --- */ } }; diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index 1eef4e102972..f2298e8bb96d 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -361,22 +361,14 @@ static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = { static const struct pci_device_id pci_tbl[] = { { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x17c8, - .subdevice = 0x2401, - .driver_data = (unsigned long) &hexium_gemini_4bnc, - }, + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x17c8, 0x2401), + .driver_data = (unsigned long)&hexium_gemini_4bnc, + }, { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x17c8, - .subdevice = 0x2402, - .driver_data = (unsigned long) &hexium_gemini_dual_4bnc, - }, - { - .vendor = 0, - } + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x17c8, 0x2402), + .driver_data = (unsigned long)&hexium_gemini_dual_4bnc, + }, + { } }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 6f1b4bff7596..8ef2a4e8235d 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -425,29 +425,16 @@ static struct saa7146_pci_extension_data hexium_orion_4bnc = { static const struct pci_device_id pci_tbl[] = { { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x0000, - .subdevice = 0x0000, - .driver_data = (unsigned long) &hexium_hv_pci6, - }, - { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x17c8, - .subdevice = 0x0101, - .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc, - }, - { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x17c8, - .subdevice = 0x2101, - .driver_data = (unsigned long) &hexium_orion_4bnc, - }, - { - .vendor = 0, - } + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x0000, 0x0000), + .driver_data = (unsigned long)&hexium_hv_pci6, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x17c8, 0x0101), + .driver_data = (unsigned long)&hexium_orion_1svhs_3bnc, + }, { + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x17c8, 0x2101), + .driver_data = (unsigned long)&hexium_orion_4bnc, + }, + { } }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index d931b4e3052f..d759e8a87e24 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -821,14 +821,10 @@ static struct saa7146_pci_extension_data mxb = { static const struct pci_device_id pci_tbl[] = { { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - .subvendor = 0x0000, - .subdevice = 0x0000, + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0x0000, 0x0000), .driver_data = (unsigned long)&mxb, - }, { - .vendor = 0, - } + }, + { } }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 6bcde506adf5..683bd78288b3 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1535,10 +1535,7 @@ static void saa7164_finidev(struct pci_dev *pci_dev) static const struct pci_device_id saa7164_pci_tbl[] = { { /* SAA7164 */ - .vendor = 0x1131, - .device = 0x7164, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + PCI_DEVICE(0x1131, 0x7164), }, { /* --- end of list --- */ } diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c index 387c29958c98..5f18abb48b17 100644 --- a/drivers/media/pci/smipcie/smipcie-main.c +++ b/drivers/media/pci/smipcie/smipcie-main.c @@ -1097,8 +1097,7 @@ static const struct smi_cfg_info technotrend_s2_4200_cfg = { /* PCI IDs */ #define SMI_ID(_subvend, _subdev, _driverdata) { \ - .vendor = SMI_VID, .device = SMI_PID, \ - .subvendor = _subvend, .subdevice = _subdev, \ + PCI_DEVICE_SUB(SMI_VID, SMI_PID, (_subvend), (_subdev)), \ .driver_data = (unsigned long)&_driverdata } static const struct pci_device_id smi_id_table[] = { @@ -1106,7 +1105,7 @@ static const struct pci_device_id smi_id_table[] = { SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg), SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg), SMI_ID(0x13c2, 0x3016, technotrend_s2_4200_cfg), - {0} + { } }; MODULE_DEVICE_TABLE(pci, smi_id_table); diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c index 11cddf4b4312..282c2c87151f 100644 --- a/drivers/media/pci/solo6x10/solo6x10-core.c +++ b/drivers/media/pci/solo6x10/solo6x10-core.c @@ -656,7 +656,7 @@ static const struct pci_device_id solo_id_table[] = { .driver_data = SOLO_DEV_6110 }, { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16), .driver_data = SOLO_DEV_6110 }, - {0,} + { } }; MODULE_DEVICE_TABLE(pci, solo_id_table); diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 8b496b959d7e..eb82a670c5bf 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -1537,9 +1537,7 @@ static const struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a), MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019), MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b), - { - .vendor = 0, - } + { } }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index 95370156aff5..c9f419fc07ad 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -858,9 +858,7 @@ static const struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61), MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020), MAKE_EXTENSION_PCI(sylt, 0x1131, 0x4f52), - { - .vendor = 0, - } + { } }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/media/pci/tw5864/tw5864-core.c b/drivers/media/pci/tw5864/tw5864-core.c index 832788603f88..6ec8bce4ac4f 100644 --- a/drivers/media/pci/tw5864/tw5864-core.c +++ b/drivers/media/pci/tw5864/tw5864-core.c @@ -72,8 +72,8 @@ MODULE_PARM_DESC(video_nr, "video devices numbers array"); * added under vendor 0x1797 (Techwell Inc.) as subsystem IDs. */ static const struct pci_device_id tw5864_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_5864)}, - {0,} + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_5864) }, + { } }; void tw5864_irqmask_apply(struct tw5864_dev *dev) diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c index 08b7ce1043aa..509d7ddec150 100644 --- a/drivers/media/pci/tw68/tw68-core.c +++ b/drivers/media/pci/tw68/tw68-core.c @@ -62,14 +62,14 @@ static atomic_t tw68_instance = ATOMIC_INIT(0); * added under vendor 0x1797 (Techwell Inc.) as subsystem IDs. */ static const struct pci_device_id tw68_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6800)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6801)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6804)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_1)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_3)}, - {PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_4)}, - {0,} + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6800) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6801) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6804) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_1) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_2) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_3) }, + { PCI_VDEVICE(TECHWELL, PCI_DEVICE_ID_TECHWELL_6816_4) }, + { } }; /* ------------------------------------------------------------------ */ diff --git a/drivers/media/pci/tw686x/tw686x-core.c b/drivers/media/pci/tw686x/tw686x-core.c index a10e38221817..5a4ab329c06e 100644 --- a/drivers/media/pci/tw686x/tw686x-core.c +++ b/drivers/media/pci/tw686x/tw686x-core.c @@ -416,25 +416,24 @@ static void tw686x_remove(struct pci_dev *pci_dev) /* driver_data is number of A/V channels */ static const struct pci_device_id tw686x_pci_tbl[] = { { - PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6864), - .driver_data = 4 - }, - { - PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6865), /* not tested */ - .driver_data = 4 | TYPE_SECOND_GEN + PCI_VDEVICE(TECHWELL, 0x6864), + .driver_data = 4, + }, { + PCI_VDEVICE(TECHWELL, 0x6865), /* not tested */ + .driver_data = 4 | TYPE_SECOND_GEN, }, /* * TW6868 supports 8 A/V channels with an external TW2865 chip; * not supported by the driver. */ { - PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6868), /* not tested */ - .driver_data = 4 + PCI_VDEVICE(TECHWELL, 0x6868), /* not tested */ + .driver_data = 4, + }, { + PCI_VDEVICE(TECHWELL, 0x6869), + .driver_data = 8 | TYPE_SECOND_GEN }, - { - PCI_DEVICE(PCI_VENDOR_ID_TECHWELL, 0x6869), - .driver_data = 8 | TYPE_SECOND_GEN}, - {} + { } }; MODULE_DEVICE_TABLE(pci, tw686x_pci_tbl); diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index f707bdc1fb0f..8bcf355a5418 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -75,8 +75,9 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(ZORAN_VERSION); #define ZR_DEVICE(subven, subdev, data) { \ - .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \ - .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) } + PCI_DEVICE_SUB(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, \ + (subven), (subdev)), \ + .driver_data = (data) } static const struct pci_device_id zr36067_pci_tbl[] = { ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10_PLUS), @@ -84,7 +85,7 @@ static const struct pci_device_id zr36067_pci_tbl[] = { ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10), ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ), ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS), - {0} + { } }; MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); diff --git a/drivers/media/platform/amd/isp4/Kconfig b/drivers/media/platform/amd/isp4/Kconfig index 9d1927af1cb8..77b61fae82ba 100644 --- a/drivers/media/platform/amd/isp4/Kconfig +++ b/drivers/media/platform/amd/isp4/Kconfig @@ -5,6 +5,7 @@ config VIDEO_AMD_ISP4_CAPTURE depends on DRM_AMDGPU && DRM_AMD_ISP depends on HAS_DMA depends on VIDEO_DEV + select MEDIA_CONTROLLER select VIDEOBUF2_CORE select VIDEOBUF2_MEMOPS select VIDEOBUF2_V4L2 diff --git a/drivers/media/platform/amd/isp4/isp4_interface.c b/drivers/media/platform/amd/isp4/isp4_interface.c index 8d73f66bb42c..00a817909292 100644 --- a/drivers/media/platform/amd/isp4/isp4_interface.c +++ b/drivers/media/platform/amd/isp4/isp4_interface.c @@ -375,7 +375,7 @@ static int isp4if_send_fw_cmd(struct isp4_interface *ispif, u32 cmd_id, return -ENOMEM; /* Get two references: one for the resp thread, one for us */ - atomic_set(&ele->refcnt, 2); + refcount_set(&ele->refcnt, 2); init_completion(&ele->cmd_done); } @@ -455,7 +455,7 @@ err_dequeue_ele: put_ele_ref: /* Don't free the command if we didn't put the last reference */ - if (ele && atomic_dec_return(&ele->refcnt)) + if (ele && !refcount_dec_and_test(&ele->refcnt)) ele = NULL; free_ele: diff --git a/drivers/media/platform/amd/isp4/isp4_interface.h b/drivers/media/platform/amd/isp4/isp4_interface.h index ce3ac9b9e5cd..04db71cd54e6 100644 --- a/drivers/media/platform/amd/isp4/isp4_interface.h +++ b/drivers/media/platform/amd/isp4/isp4_interface.h @@ -68,7 +68,7 @@ struct isp4if_cmd_element { u32 seq_num; u32 cmd_id; struct completion cmd_done; - atomic_t refcnt; + refcount_t refcnt; }; struct isp4_interface { diff --git a/drivers/media/platform/amd/isp4/isp4_subdev.c b/drivers/media/platform/amd/isp4/isp4_subdev.c index 48deea79ce6c..2a8bc1207843 100644 --- a/drivers/media/platform/amd/isp4/isp4_subdev.c +++ b/drivers/media/platform/amd/isp4/isp4_subdev.c @@ -391,7 +391,7 @@ static void isp4sd_fw_resp_cmd_done(struct isp4_subdev *isp_subdev, if (ele) { complete(&ele->cmd_done); - if (atomic_dec_and_test(&ele->refcnt)) + if (refcount_dec_and_test(&ele->refcnt)) kfree(ele); } } diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c index 0b3d58b9f2f7..2ba4ae20f829 100644 --- a/drivers/media/platform/amphion/venc.c +++ b/drivers/media/platform/amphion/venc.c @@ -973,8 +973,6 @@ static int venc_start_session(struct vpu_inst *inst, u32 type) venc->ready_count = 0; venc->stopped = false; vpu_process_output_buffer(inst); - if (venc->frame_count == 0) - dev_err(inst->dev, "[%d] there is no input when starting\n", inst->id); return 0; error: diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c index 8d28ba0b59a3..1508843ae58c 100644 --- a/drivers/media/platform/broadcom/bcm2835-unicam.c +++ b/drivers/media/platform/broadcom/bcm2835-unicam.c @@ -2613,6 +2613,7 @@ static int unicam_async_nf_init(struct unicam_device *unicam) return 0; error: + v4l2_async_nf_cleanup(&unicam->notifier); fwnode_handle_put(ep_handle); return ret; } @@ -2745,6 +2746,7 @@ static void unicam_remove(struct platform_device *pdev) v4l2_device_unregister(&unicam->v4l2_dev); media_device_unregister(&unicam->mdev); v4l2_async_nf_unregister(&unicam->notifier); + v4l2_async_nf_cleanup(&unicam->notifier); unicam_subdev_cleanup(unicam); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index bb2ba9204a83..6564cf3ec739 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -5,6 +5,7 @@ * Copyright (C) 2021-2023 CHIPS&MEDIA INC */ +#include <linux/delay.h> #include <linux/pm_runtime.h> #include "wave5-helper.h" @@ -474,7 +475,10 @@ static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); } - inst->queuing_fail = false; + if (inst->queuing_fail) { + inst->queuing_fail = false; + v4l2_m2m_try_schedule(m2m_ctx); + } } static int wave5_vpu_dec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) @@ -819,7 +823,15 @@ static int wave5_vpu_dec_stop(struct vpu_instance *inst) * calls do not block on a mutex while inside this spinlock. */ spin_unlock_irqrestore(&inst->state_spinlock, flags); + /* + * V4L2_DEC_CMD_STOP can arrive while the device is runtime + * suspended (e.g. on pipeline teardown). Setting the EOS flag + * accesses VPU registers via send_firmware_command(), so the + * device must be resumed first to avoid an asynchronous SError. + */ + pm_runtime_resume_and_get(inst->dev->dev); ret = wave5_vpu_dec_set_eos_on_firmware(inst); + pm_runtime_put_autosuspend(inst->dev->dev); if (ret) return ret; @@ -1403,6 +1415,7 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { struct dec_initial_info *initial_info = &inst->codec_info->dec_info.initial_info; + struct dec_info *p_dec_info = &inst->codec_info->dec_info; if (inst->state == VPU_INST_STATE_STOP) ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ); @@ -1410,6 +1423,7 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count goto return_buffers; if (inst->state == VPU_INST_STATE_INIT_SEQ && + p_dec_info->initial_info_obtained && inst->dev->product_code == WAVE521C_CODE) { if (initial_info->luma_bitdepth != 8) { dev_info(inst->dev->dev, "%s: no support for %d bit depth", @@ -1418,7 +1432,6 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count goto return_buffers; } } - } pm_runtime_put_autosuspend(inst->dev->dev); return ret; @@ -1536,15 +1549,15 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) { struct vpu_instance *inst = vb2_get_drv_priv(q); struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; - - bool check_cmd = TRUE; + unsigned long timeout; dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type); pm_runtime_resume_and_get(inst->dev->dev); inst->empty_queue = true; - while (check_cmd) { + + timeout = jiffies + msecs_to_jiffies(VPU_DEC_STOP_TIMEOUT); + while (true) { struct queue_status_info q_status; - struct dec_output_info dec_output_info; wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); if ((inst->state == VPU_INST_STATE_STOP || @@ -1553,8 +1566,10 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) q_status.report_queue_count == 0) break; - if (wave5_vpu_dec_get_output_info(inst, &dec_output_info)) - dev_dbg(inst->dev->dev, "there is no output info\n"); + if (time_after(jiffies, timeout)) + break; + + usleep_range(1000, 2000); } v4l2_m2m_update_stop_streaming_state(m2m_ctx, q); @@ -1651,6 +1666,7 @@ static void wave5_vpu_dec_device_run(void *priv) struct queue_status_info q_status; u32 fail_res = 0; int ret = 0; + bool cmd_issued = false; dev_dbg(inst->dev->dev, "%s: Fill the ring buffer with new bitstream data", __func__); pm_runtime_resume_and_get(inst->dev->dev); @@ -1662,9 +1678,13 @@ static void wave5_vpu_dec_device_run(void *priv) } else if (!inst->eos && inst->queuing_num == 0 && inst->state == VPU_INST_STATE_PIC_RUN) { - dev_dbg(inst->dev->dev, "%s: no bitstream for feeding, so skip ", __func__); - inst->empty_queue = true; - goto finish_job_and_return; + wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); + if (q_status.instance_queue_count == v4l2_m2m_num_src_bufs_ready(m2m_ctx)) { + dev_dbg(inst->dev->dev, "%s: no bitstream, skip\n", + __func__); + inst->empty_queue = true; + goto finish_job_and_return; + } } } @@ -1744,6 +1764,7 @@ static void wave5_vpu_dec_device_run(void *priv) inst->retry = false; if (!inst->eos) inst->queuing_num--; + cmd_issued = true; } break; default: @@ -1761,8 +1782,16 @@ finish_job_and_return: * in power and CPU time. * If EOS is passed, device_run will not call job_finish no more, it is called * only if HW is idle status in order to reduce overhead. + * + * Deferring job_finish() is only safe when this run actually queued a + * DEC_PIC command (cmd_issued): that guarantees a completion IRQ, and + * thus a later finish_decode(), will release the shared job slot. When + * device_run() is entered with no command to issue (e.g. a job that was + * queued while draining but reached the STOP state by the time it ran), + * no IRQ follows, so finish the job here to avoid leaking the slot and + * stalling every instance sharing the VPU. */ - if (!inst->sent_eos) + if (!inst->sent_eos || !cmd_issued) v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); } @@ -1776,11 +1805,22 @@ static void wave5_vpu_dec_job_abort(void *priv) if (ret) return; + /* + * job_abort() runs from the STREAMOFF path and may be called while the + * device is runtime suspended. Setting the EOS flag talks to the + * firmware (send_firmware_command() accesses VPU registers), so the + * device must be resumed first; otherwise the register access faults + * with an asynchronous SError. + */ + pm_runtime_resume_and_get(inst->dev->dev); + ret = wave5_vpu_dec_set_eos_on_firmware(inst); if (ret) dev_warn(inst->dev->dev, "Setting EOS for the bitstream, fail: %d\n", ret); + pm_runtime_put_autosuspend(inst->dev->dev); + v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c index e6c94b6f2671..f9fcdf4c224b 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c @@ -1494,7 +1494,8 @@ static const struct vb2_ops wave5_vpu_enc_vb2_ops = { .stop_streaming = wave5_vpu_enc_stop_streaming, }; -static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt, +static void wave5_set_default_format(struct vpu_instance *inst, + struct v4l2_pix_format_mplane *src_fmt, struct v4l2_pix_format_mplane *dst_fmt) { src_fmt->pixelformat = enc_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt; @@ -1506,6 +1507,7 @@ static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt, wave5_update_pix_fmt(dst_fmt, VPU_FMT_TYPE_CODEC, W5_DEF_ENC_PIC_WIDTH, W5_DEF_ENC_PIC_HEIGHT, &enc_frmsize[VPU_FMT_TYPE_CODEC]); + inst->std = wave5_to_vpu_std(dst_fmt->pixelformat, inst->type); } static int wave5_vpu_enc_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) @@ -1770,7 +1772,7 @@ static int wave5_vpu_open_enc(struct file *filp) inst->v4l2_fh.ctrl_handler = v4l2_ctrl_hdl; v4l2_ctrl_handler_setup(v4l2_ctrl_hdl); - wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt); + wave5_set_default_format(inst, &inst->src_fmt, &inst->dst_fmt); inst->conf_win.width = inst->dst_fmt.width; inst->conf_win.height = inst->dst_fmt.height; inst->colorspace = V4L2_COLORSPACE_REC709; diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h index 4ebd48d5550e..e04f2dbf3b65 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h @@ -59,7 +59,7 @@ // application specific configuration #define VPU_ENC_TIMEOUT 60000 #define VPU_DEC_TIMEOUT 60000 -#define VPU_DEC_STOP_TIMEOUT 10 +#define VPU_DEC_STOP_TIMEOUT 300 // for WAVE encoder #define USE_SRC_PRP_AXI 0 diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c index d30a05782ab9..96a66aadf0cd 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c @@ -321,7 +321,7 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd, /* Enable mux settings */ for (index = 0; index < ctrl->num_sets; index++) { set = &ctrl->sets[index]; - cmdq_pkt_write(&cmd->pkt, set->subsys_id, set->reg, set->value); + cmdq_pkt_write_subsys(&cmd->pkt, set->subsys_id, set->reg, set->reg, set->value); } /* Config sub-frame information */ for (index = (num_comp - 1); index >= 0; index--) { @@ -376,7 +376,7 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd, /* Disable mux settings */ for (index = 0; index < ctrl->num_sets; index++) { set = &ctrl->sets[index]; - cmdq_pkt_write(&cmd->pkt, set->subsys_id, set->reg, 0); + cmdq_pkt_write_subsys(&cmd->pkt, set->subsys_id, set->reg, set->reg, 0); } return 0; @@ -628,7 +628,7 @@ static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp, goto err_free_path; } cmdq_pkt_eoc(&cmd->pkt); - cmdq_pkt_jump_rel(&cmd->pkt, CMDQ_INST_SIZE, mdp->cmdq_shift_pa[pp_idx]); + cmdq_pkt_jump_rel_temp(&cmd->pkt, CMDQ_INST_SIZE, mdp->cmdq_shift_pa[pp_idx]); for (i = 0; i < num_comp; i++) { s32 inner_id = MDP_COMP_NONE; diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h index 681906c16419..c6fc180950f2 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.h @@ -12,14 +12,14 @@ #define MM_REG_WRITE_MASK(cmd, id, base, ofst, val, mask) \ do { \ typeof(mask) (m) = (mask); \ - cmdq_pkt_write_mask(&((cmd)->pkt), id, (base) + (ofst), \ - (val), \ + cmdq_pkt_write_mask_subsys(&((cmd)->pkt), (id), (base), \ + (base) + (ofst), (val), \ (((m) & (ofst##_MASK)) == (ofst##_MASK)) ? \ (0xffffffff) : (m)); \ } while (0) #define MM_REG_WRITE(cmd, id, base, ofst, val) \ - cmdq_pkt_write(&((cmd)->pkt), id, (base) + (ofst), (val)) + cmdq_pkt_write_subsys(&((cmd)->pkt), (id), (base), (base) + (ofst), (val)) #define MM_REG_WAIT(cmd, evt) \ do { \ diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c index 8f4da4cf55d2..f412aadb5996 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c @@ -294,7 +294,11 @@ static int mdp_probe(struct platform_device *pdev) goto err_destroy_clock_wq; } mdp->scp = platform_get_drvdata(mm_pdev); - put_device(&mm_pdev->dev); + } + + if (!mdp->scp) { + ret = -EPROBE_DEFER; + goto err_destroy_clock_wq; } mdp->rproc_handle = scp_get_rproc(mdp->scp); diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c index adbacabdbebc..ba7a1cd998b9 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c @@ -974,10 +974,10 @@ static int vdec_vp9_slice_setup_pfc(struct vdec_vp9_slice_instance *instance, return 0; } -static int vdec_vp9_slice_setup_lat_buffer(struct vdec_vp9_slice_instance *instance, - struct vdec_vp9_slice_vsi *vsi, - struct mtk_vcodec_mem *bs, - struct vdec_lat_buf *lat_buf) +static void vdec_vp9_slice_setup_lat_buffer(struct vdec_vp9_slice_instance *instance, + struct vdec_vp9_slice_vsi *vsi, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf) { int i; @@ -1011,12 +1011,10 @@ static int vdec_vp9_slice_setup_lat_buffer(struct vdec_vp9_slice_instance *insta vsi->row_info.buf = 0; vsi->row_info.size = 0; - - return 0; } -static int vdec_vp9_slice_setup_prob_buffer(struct vdec_vp9_slice_instance *instance, - struct vdec_vp9_slice_vsi *vsi) +static void vdec_vp9_slice_setup_prob_buffer(struct vdec_vp9_slice_instance *instance, + struct vdec_vp9_slice_vsi *vsi) { struct vdec_vp9_slice_frame_ctx *frame_ctx; struct vdec_vp9_slice_uncompressed_header *uh; @@ -1032,8 +1030,6 @@ static int vdec_vp9_slice_setup_prob_buffer(struct vdec_vp9_slice_instance *inst else frame_ctx = vdec_vp9_slice_default_frame_ctx; memcpy(instance->prob.va, frame_ctx, sizeof(*frame_ctx)); - - return 0; } static void vdec_vp9_slice_setup_seg_buffer(struct vdec_vp9_slice_instance *instance, @@ -1166,17 +1162,13 @@ static int vdec_vp9_slice_setup_lat(struct vdec_vp9_slice_instance *instance, if (ret) goto err; - ret = vdec_vp9_slice_setup_lat_buffer(instance, vsi, bs, lat_buf); - if (ret) - goto err; + vdec_vp9_slice_setup_lat_buffer(instance, vsi, bs, lat_buf); vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[0]); /* setup prob/tile buffers for LAT */ - ret = vdec_vp9_slice_setup_prob_buffer(instance, vsi); - if (ret) - goto err; + vdec_vp9_slice_setup_prob_buffer(instance, vsi); ret = vdec_vp9_slice_setup_tile_buffer(instance, vsi, bs); if (ret) @@ -1808,10 +1800,7 @@ static int vdec_vp9_slice_setup_single(struct vdec_vp9_slice_instance *instance, vdec_vp9_slice_setup_single_buffer(instance, pfc, vsi, bs, fb); vdec_vp9_slice_setup_seg_buffer(instance, vsi, &instance->seg[0]); - - ret = vdec_vp9_slice_setup_prob_buffer(instance, vsi); - if (ret) - goto err; + vdec_vp9_slice_setup_prob_buffer(instance, vsi); ret = vdec_vp9_slice_setup_tile_buffer(instance, vsi, bs); if (ret) diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c index fb6f1016415e..faebb5472866 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c @@ -580,7 +580,7 @@ static u32 hfi_buffer_line_av1d(u32 frame_width, u32 frame_height, ALIGN(size_av1d_qp(frame_width, frame_height), DMA_ALIGNMENT); opbwr8 = size_av1d_lb_opb_wr1_nv12_ubwc(frame_width, frame_height); opbwr10 = size_av1d_lb_opb_wr1_tp10_ubwc(frame_width, frame_height); - opbwrbufsize = opbwr8 >= opbwr10 ? opbwr8 : opbwr10; + opbwrbufsize = max(opbwr8, opbwr10); size = ALIGN((size + opbwrbufsize), DMA_ALIGNMENT); if (is_opb) { vpss_lb_size = size_vpss_lb(frame_width, frame_height); @@ -700,7 +700,7 @@ static u32 hfi_buffer_ibc_av1d(u32 frame_width, u32 frame_height) ibc8 = size_av1d_ibc_nv12_ubwc(frame_width, frame_height); ibc10 = size_av1d_ibc_tp10_ubwc(frame_width, frame_height); - size = ibc8 >= ibc10 ? ibc8 : ibc10; + size = max(ibc8, ibc10); return ALIGN(size, DMA_ALIGNMENT); } diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h index 5bf334e173d2..b426bc7898bf 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h @@ -116,11 +116,9 @@ struct rzg2l_cru_info { * @scratch_phys: physical address of the scratch buffer * * @qlock: protects @queue_buf, @buf_list, @sequence - * @state * @queue_buf: Keeps track of buffers given to HW slot * @buf_list: list of queued buffers * @sequence: V4L2 buffers sequence number - * @state: keeps track of operation state * * @format: active V4L2 pixel format */ diff --git a/drivers/media/platform/rockchip/rga/rga3-hw.c b/drivers/media/platform/rockchip/rga/rga3-hw.c index ca1c268303dd..c4a71306278b 100644 --- a/drivers/media/platform/rockchip/rga/rga3-hw.c +++ b/drivers/media/platform/rockchip/rga/rga3-hw.c @@ -450,10 +450,14 @@ static void *rga3_adjust_and_map_format(struct rga_ctx *ctx, other_format = is_output ? &ctx->out.pix : &ctx->in.pix; other_format_info = v4l2_format_info(other_format->pixelformat); - if ((v4l2_is_format_rgb(format_info) && - v4l2_is_format_yuv(other_format_info)) || - (v4l2_is_format_yuv(format_info) && - v4l2_is_format_rgb(other_format_info))) { + /* + * Only apply the quantization restrictions when we need to + * convert between RGB and YUV. Otherwise there is no point + * to limit the quantization for operations like scaling or + * rotations. + */ + if (v4l2_is_format_yuv(format_info) && + v4l2_is_format_rgb(other_format_info)) { /* * The RGA3 only supports BT601, BT709 and BT2020 RGB<->YUV conversions * Additionally BT709 and BT2020 only support limited range YUV. diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c index f89602075121..9c4a6093af32 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc-common.c @@ -209,6 +209,9 @@ static void st_ref_pic_set_prediction(struct rkvdec_hevc_run *run, int idx, int i, j; int dPoc; + if ((unsigned int)rps_data->delta_idx_minus1 + 1 > idx) + return; + ref_rps_idx = st_rps_idx - (rps_data->delta_idx_minus1 + 1); /* 7-59 */ delta_rps = (1 - 2 * rps_data->delta_rps_sign) * (rps_data->abs_delta_rps_minus1 + 1); /* 7-60 */ diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c index 87abf93dfd5e..ff3942f91c5d 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c @@ -258,9 +258,9 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, for (i = 0; i <= pps->num_tile_rows_minus1; i++) WRITE_PPS(pps->row_height_minus1[i], ROW_HEIGHT(i)); } else { - WRITE_PPS(((sps->pic_width_in_luma_samples + ctb_size_y - 1) / ctb_size_y) - 1, + WRITE_PPS(DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_y) - 1, COLUMN_WIDTH(0)); - WRITE_PPS(((sps->pic_height_in_luma_samples + ctb_size_y - 1) / ctb_size_y) - 1, + WRITE_PPS(DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_y) - 1, ROW_HEIGHT(0)); } diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c index fe6414a17551..d07c74679552 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu381-hevc.c @@ -261,8 +261,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, memset(row_height, 0, sizeof(row_height)); max_cu_width = 1 << (sps->log2_diff_max_min_luma_coding_block_size + log2_min_cb_size); - pic_in_cts_width = (width + max_cu_width - 1) / max_cu_width; - pic_in_cts_height = (height + max_cu_width - 1) / max_cu_width; + pic_in_cts_width = DIV_ROUND_UP(width, max_cu_width); + pic_in_cts_height = DIV_ROUND_UP(height, max_cu_width); if (pps->flags & V4L2_HEVC_PPS_FLAG_TILES_ENABLED) { if (pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING) { @@ -275,8 +275,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, column_width, row_height); } } else { - column_width[0] = (width + max_cu_width - 1) / max_cu_width; - row_height[0] = (height + max_cu_width - 1) / max_cu_width; + column_width[0] = DIV_ROUND_UP(width, max_cu_width); + row_height[0] = DIV_ROUND_UP(height, max_cu_width); } for (i = 0; i < 20; i++) { diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c index 3575338a531a..3462d995d4cf 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vdpu383-hevc.c @@ -287,8 +287,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, memset(row_height, 0, sizeof(row_height)); max_cu_width = 1 << (sps->log2_diff_max_min_luma_coding_block_size + log2_min_cb_size); - pic_in_cts_width = (width + max_cu_width - 1) / max_cu_width; - pic_in_cts_height = (height + max_cu_width - 1) / max_cu_width; + pic_in_cts_width = DIV_ROUND_UP(width, max_cu_width); + pic_in_cts_height = DIV_ROUND_UP(height, max_cu_width); if (tiles_enabled) { if (pps->flags & V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING) { @@ -301,8 +301,8 @@ static void assemble_hw_pps(struct rkvdec_ctx *ctx, column_width, row_height); } } else { - column_width[0] = (width + max_cu_width - 1) / max_cu_width; - row_height[0] = (height + max_cu_width - 1) / max_cu_width; + column_width[0] = DIV_ROUND_UP(width, max_cu_width); + row_height[0] = DIV_ROUND_UP(height, max_cu_width); } for (i = 0; i < 20; i++) diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index 1d1e9bfef8e9..061281f903f3 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -278,12 +278,12 @@ static const struct rkvdec_ctrl_desc vdpu38x_hevc_ctrl_descs[] = { { .cfg.id = V4L2_CID_STATELESS_HEVC_EXT_SPS_ST_RPS, .cfg.ops = &rkvdec_ctrl_ops, - .cfg.dims = { 65 }, + .cfg.dims = { 64 }, }, { .cfg.id = V4L2_CID_STATELESS_HEVC_EXT_SPS_LT_RPS, .cfg.ops = &rkvdec_ctrl_ops, - .cfg.dims = { 65 }, + .cfg.dims = { 32 }, }, }; @@ -1818,8 +1818,8 @@ static int rkvdec_probe(struct platform_device *pdev) vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -ENXIO; + if (irq < 0) + return irq; ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, rkvdec_irq_handler, IRQF_ONESHOT, diff --git a/drivers/media/platform/samsung/s3c-camif/camif-core.c b/drivers/media/platform/samsung/s3c-camif/camif-core.c index 221e3c447f36..14eedd1ceb27 100644 --- a/drivers/media/platform/samsung/s3c-camif/camif-core.c +++ b/drivers/media/platform/samsung/s3c-camif/camif-core.c @@ -12,7 +12,6 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/errno.h> -#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -412,7 +411,7 @@ static int s3c_camif_probe(struct platform_device *pdev) camif->dev = dev; - if (!pdata || !pdata->gpio_get || !pdata->gpio_put) { + if (!pdata) { dev_err(dev, "wrong platform data\n"); return -EINVAL; } @@ -429,9 +428,7 @@ static int s3c_camif_probe(struct platform_device *pdev) if (ret < 0) return ret; - ret = pdata->gpio_get(); - if (ret < 0) - return ret; + /* FIXME: get GPIOs here */ ret = s3c_camif_create_subdev(camif); if (ret < 0) @@ -504,14 +501,12 @@ err_disable: err_clk: s3c_camif_unregister_subdev(camif); err_sd: - pdata->gpio_put(); return ret; } static void s3c_camif_remove(struct platform_device *pdev) { struct camif_dev *camif = platform_get_drvdata(pdev); - struct s3c_camif_plat_data *pdata = &camif->pdata; media_device_unregister(&camif->media_dev); media_device_cleanup(&camif->media_dev); @@ -521,7 +516,6 @@ static void s3c_camif_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); camif_clk_put(camif); s3c_camif_unregister_subdev(camif); - pdata->gpio_put(); } static int s3c_camif_runtime_resume(struct device *dev) diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index eeb0199864dd..b1f9af8edf6e 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -2273,9 +2273,7 @@ static int dcmi_resume(struct device *dev) pinctrl_pm_select_default_state(dev); /* clock enable */ - pm_runtime_force_resume(dev); - - return 0; + return pm_runtime_force_resume(dev); } static const struct dev_pm_ops dcmi_pm_ops = { diff --git a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c index 49398d077764..516334541b2c 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c +++ b/drivers/media/platform/st/stm32/stm32-dcmipp/dcmipp-core.c @@ -649,9 +649,7 @@ static int dcmipp_resume(struct device *dev) pinctrl_pm_select_default_state(dev); /* clock enable */ - pm_runtime_force_resume(dev); - - return 0; + return pm_runtime_force_resume(dev); } static const struct dev_pm_ops dcmipp_pm_ops = { diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig index d0cb05481bd8..1a020b2bbb4f 100644 --- a/drivers/media/platform/ti/Kconfig +++ b/drivers/media/platform/ti/Kconfig @@ -50,6 +50,7 @@ config VIDEO_TI_VIP select VIDEO_TI_VPDMA select VIDEO_TI_SC select VIDEO_TI_CSC + select V4L2_FWNODE help Driver support for VIP module on certain TI SoC's VIP = Video Input Port. diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index 2e81877f640f..ad71c0402ef3 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -771,8 +771,10 @@ static int hantro_register_entity(struct media_device *mdev, return ret; ret = media_device_register_entity(mdev, entity); - if (ret) + if (ret) { + media_entity_cleanup(entity); return ret; + } return 0; } @@ -860,12 +862,13 @@ err_rm_links0: err_rel_entity2: media_device_unregister_entity(&func->sink); - + media_entity_cleanup(&func->sink); err_rel_entity1: media_device_unregister_entity(&func->proc); - + media_entity_cleanup(&func->proc); err_rel_entity0: media_device_unregister_entity(&func->vdev.entity); + media_entity_cleanup(&func->vdev.entity); return ret; } @@ -878,6 +881,9 @@ static void hantro_detach_func(struct hantro_func *func) media_device_unregister_entity(&func->sink); media_device_unregister_entity(&func->proc); media_device_unregister_entity(&func->vdev.entity); + media_entity_cleanup(&func->sink); + media_entity_cleanup(&func->proc); + media_entity_cleanup(&func->vdev.entity); } static int hantro_add_func(struct hantro_dev *vpu, unsigned int funcid) diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 5110754e1a31..53c1d1061cf4 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -527,8 +527,8 @@ static const struct v4l2_ctrl_ops cadet_ctrl_ops = { static const struct pnp_device_id cadet_pnp_devices[] = { /* ADS Cadet AM/FM Radio Card */ - {.id = "MSM0c24", .driver_data = 0}, - {.id = ""} + { .id = "MSM0c24" }, + { } }; MODULE_DEVICE_TABLE(pnp, cadet_pnp_devices); diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 3d1d0b46195b..7e4257e4b71d 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -284,8 +284,8 @@ static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c } #ifdef CONFIG_PNP static const struct pnp_device_id gemtek_pnp_devices[] = { /* AOpen FX-3D/Pro Radio */ - {.id = "ADS7183", .driver_data = 0}, - {.id = ""} + { .id = "ADS7183" }, + { } }; MODULE_DEVICE_TABLE(pnp, gemtek_pnp_devices); diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index 5055dfc3f465..c196ee923ecd 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -642,8 +642,8 @@ static void fintek_shutdown(struct pnp_dev *pdev) } static const struct pnp_device_id fintek_ids[] = { - { "FIT0002", 0 }, /* CIR */ - { "", 0 }, + { .id = "FIT0002" }, /* CIR */ + { } }; static struct pnp_driver fintek_driver = { diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index bde2a7051231..1fbafcd8219e 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1203,9 +1203,16 @@ static void ite_close(struct rc_dev *rcdev) spin_unlock_irqrestore(&dev->lock, flags); } +enum ite_model_type { + ITE8704, + ITE8713, + ITE8708, + ITE8709, +}; + /* supported models and their parameters */ static const struct ite_dev_params ite_dev_descs[] = { - { /* 0: ITE8704 */ + [ITE8704] = { .model = "ITE8704 CIR transceiver", .io_region_size = IT87_IOREG_LENGTH, .io_rsrc_no = 0, @@ -1224,7 +1231,7 @@ static const struct ite_dev_params ite_dev_descs[] = { .init_hardware = it87_init_hardware, .set_carrier_params = it87_set_carrier_params, }, - { /* 1: ITE8713 */ + [ITE8713] = { .model = "ITE8713 CIR transceiver", .io_region_size = IT87_IOREG_LENGTH, .io_rsrc_no = 0, @@ -1243,7 +1250,7 @@ static const struct ite_dev_params ite_dev_descs[] = { .init_hardware = it87_init_hardware, .set_carrier_params = it87_set_carrier_params, }, - { /* 2: ITE8708 */ + [ITE8708] = { .model = "ITE8708 CIR transceiver", .io_region_size = IT8708_IOREG_LENGTH, .io_rsrc_no = 0, @@ -1263,7 +1270,7 @@ static const struct ite_dev_params ite_dev_descs[] = { .init_hardware = it8708_init_hardware, .set_carrier_params = it8708_set_carrier_params, }, - { /* 3: ITE8709 */ + [ITE8709] = { .model = "ITE8709 CIR transceiver", .io_region_size = IT8709_IOREG_LENGTH, .io_rsrc_no = 2, @@ -1286,11 +1293,11 @@ static const struct ite_dev_params ite_dev_descs[] = { }; static const struct pnp_device_id ite_ids[] = { - {"ITE8704", 0}, /* Default model */ - {"ITE8713", 1}, /* CIR found in EEEBox 1501U */ - {"ITE8708", 2}, /* Bridged IT8512 */ - {"ITE8709", 3}, /* SRAM-Bridged IT8512 */ - {"", 0}, + { .id = "ITE8704", .driver_data = ITE8704 }, /* Default model */ + { .id = "ITE8713", .driver_data = ITE8713 }, /* CIR found in EEEBox 1501U */ + { .id = "ITE8708", .driver_data = ITE8708 }, /* Bridged IT8512 */ + { .id = "ITE8709", .driver_data = ITE8709 }, /* SRAM-Bridged IT8512 */ + { } }; /* allocate memory, probe hardware, and initialize everything */ @@ -1301,7 +1308,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id struct ite_dev *itdev = NULL; struct rc_dev *rdev = NULL; int ret = -ENOMEM; - int model_no; + enum ite_model_type model_no; int io_rsrc_no; itdev = kzalloc_obj(struct ite_dev); @@ -1317,7 +1324,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id ret = -ENODEV; /* get the model number */ - model_no = (int)dev_id->driver_data; + model_no = dev_id->driver_data; dev_dbg(&pdev->dev, "Auto-detected model: %s\n", ite_dev_descs[model_no].model); diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index d04572627cdd..38b84e34b225 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -129,7 +129,7 @@ obj-$(CONFIG_RC_MAP) += \ rc-twinhan1027.o \ rc-twinhan-dtv-cab-ci.o \ rc-vega-s9x.o \ - rc-videomate-m1f.o \ + rc-videomate-k100.o \ rc-videomate-s350.o \ rc-videomate-tv-pvr.o \ rc-videostrong-kii-pro.o \ diff --git a/drivers/media/rc/keymaps/rc-videomate-m1f.c b/drivers/media/rc/keymaps/rc-videomate-k100.c index 1f9be84ff27b..6664cfd0b7f3 100644 --- a/drivers/media/rc/keymaps/rc-videomate-m1f.c +++ b/drivers/media/rc/keymaps/rc-videomate-k100.c @@ -87,4 +87,4 @@ module_exit(exit_rc_map_videomate_k100) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pavel Osnova <pvosnova@gmail.com>"); -MODULE_DESCRIPTION("videomate-m1f remote controller keytable"); +MODULE_DESCRIPTION("videomate-k100 remote controller keytable"); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 4e5a0c8dc9a0..918258dadd69 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1092,9 +1092,9 @@ static void nvt_shutdown(struct pnp_dev *pdev) } static const struct pnp_device_id nvt_ids[] = { - { "WEC0530", 0 }, /* CIR */ - { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ - { "", 0 }, + { .id = "WEC0530" }, /* CIR */ + { .id = "NTN0530" }, /* CIR for new chip's pnp id*/ + { } }; static struct pnp_driver nvt_driver = { diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index cb4c56bf0752..28e840a7e5b8 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -344,22 +344,25 @@ static int sunxi_ir_probe(struct platform_device *pdev) ir->irq = platform_get_irq(pdev, 0); if (ir->irq < 0) { ret = ir->irq; - goto exit_free_dev; + goto exit_unregister_dev; } ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir); if (ret) { dev_err(dev, "failed request irq\n"); - goto exit_free_dev; + goto exit_unregister_dev; } ret = sunxi_ir_hw_init(dev); if (ret) - goto exit_free_dev; + goto exit_unregister_dev; dev_info(dev, "initialized sunXi IR driver\n"); return 0; +exit_unregister_dev: + rc_unregister_device(ir->rc); + exit_free_dev: rc_free_device(ir->rc); diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 8e804661a621..1ae036f8a296 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -1179,8 +1179,8 @@ wbcir_remove(struct pnp_dev *device) } static const struct pnp_device_id wbcir_ids[] = { - { "WEC1022", 0 }, - { "", 0 } + { .id = "WEC1022" }, + { } }; MODULE_DEVICE_TABLE(pnp, wbcir_ids); diff --git a/drivers/media/test-drivers/vicodec/vicodec-core.c b/drivers/media/test-drivers/vicodec/vicodec-core.c index 318e8330f16a..ff9d50fb05fd 100644 --- a/drivers/media/test-drivers/vicodec/vicodec-core.c +++ b/drivers/media/test-drivers/vicodec/vicodec-core.c @@ -63,11 +63,11 @@ struct pixfmt_info { }; static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = { - V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1 + V4L2_PIX_FMT_FWHT, 0, 4, 1, 1, 1, 1, 1, 0, 1 }; static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = { - V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1 + V4L2_PIX_FMT_FWHT_STATELESS, 0, 4, 1, 1, 1, 1, 1, 0, 1 }; static void vicodec_dev_release(struct device *dev) diff --git a/drivers/media/test-drivers/vimc/vimc-sensor.c b/drivers/media/test-drivers/vimc/vimc-sensor.c index 5deebcc78a33..83dcc9d61ee0 100644 --- a/drivers/media/test-drivers/vimc/vimc-sensor.c +++ b/drivers/media/test-drivers/vimc/vimc-sensor.c @@ -92,8 +92,8 @@ static void vimc_sensor_tpg_s_format(struct vimc_sensor_device *vsensor, tpg_s_xfer_func(&vsensor->tpg, format->xfer_func); } -static int vimc_sensor_update_frame_timing(struct v4l2_subdev *sd, - u32 width, u32 height) +static void vimc_sensor_update_frame_timing(struct v4l2_subdev *sd, + u32 width, u32 height) { struct vimc_sensor_device *vsensor = container_of(sd, struct vimc_sensor_device, sd); @@ -103,13 +103,15 @@ static int vimc_sensor_update_frame_timing(struct v4l2_subdev *sd, u64 total_pixels = (u64)hts * vts; u64 frame_interval_ns; + /* Sanity check, pixel rate is fixed and fits in 32 bits. */ + if (WARN_ON(pixel_rate >= 0x100000000)) + return; + frame_interval_ns = total_pixels * NSEC_PER_SEC; - do_div(frame_interval_ns, pixel_rate); + do_div(frame_interval_ns, (u32)pixel_rate); vsensor->hw.fps_jiffies = nsecs_to_jiffies(frame_interval_ns); if (vsensor->hw.fps_jiffies == 0) vsensor->hw.fps_jiffies = 1; - - return 0; } static void vimc_sensor_adjust_fmt(struct v4l2_mbus_framefmt *fmt) diff --git a/drivers/media/test-drivers/vivid/vivid-meta-out.c b/drivers/media/test-drivers/vivid/vivid-meta-out.c index 55e5e5dec2f2..ca913b808225 100644 --- a/drivers/media/test-drivers/vivid/vivid-meta-out.c +++ b/drivers/media/test-drivers/vivid/vivid-meta-out.c @@ -17,12 +17,8 @@ static int meta_out_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { - struct vivid_dev *dev = vb2_get_drv_priv(vq); unsigned int size = sizeof(struct vivid_meta_out_buf); - if (!vivid_is_webcam(dev)) - return -EINVAL; - if (*nplanes) { if (sizes[0] < size) return -EINVAL; @@ -127,11 +123,6 @@ const struct vb2_ops vivid_meta_out_qops = { int vidioc_enum_fmt_meta_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct vivid_dev *dev = video_drvdata(file); - - if (!vivid_is_webcam(dev)) - return -EINVAL; - if (f->index > 0) return -EINVAL; @@ -143,12 +134,8 @@ int vidioc_enum_fmt_meta_out(struct file *file, void *priv, int vidioc_g_fmt_meta_out(struct file *file, void *priv, struct v4l2_format *f) { - struct vivid_dev *dev = video_drvdata(file); struct v4l2_meta_format *meta = &f->fmt.meta; - if (!vivid_is_webcam(dev) || !dev->has_meta_out) - return -EINVAL; - meta->dataformat = V4L2_META_FMT_VIVID; meta->buffersize = sizeof(struct vivid_meta_out_buf); return 0; @@ -159,10 +146,12 @@ void vivid_meta_out_process(struct vivid_dev *dev, { struct vivid_meta_out_buf *meta = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); - v4l2_ctrl_s_ctrl(dev->brightness, meta->brightness); - v4l2_ctrl_s_ctrl(dev->contrast, meta->contrast); - v4l2_ctrl_s_ctrl(dev->saturation, meta->saturation); - v4l2_ctrl_s_ctrl(dev->hue, meta->hue); + if (dev->brightness) { + v4l2_ctrl_s_ctrl(dev->brightness, meta->brightness); + v4l2_ctrl_s_ctrl(dev->contrast, meta->contrast); + v4l2_ctrl_s_ctrl(dev->saturation, meta->saturation); + v4l2_ctrl_s_ctrl(dev->hue, meta->hue); + } dprintk(dev, 2, " %s brightness %u contrast %u saturation %u hue %d\n", __func__, meta->brightness, meta->contrast, diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index 57edb42463e8..358a66ab8e48 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -464,14 +464,21 @@ static void airspy_disconnect(struct usb_interface *intf) dev_dbg(s->dev, "\n"); - mutex_lock(&s->vb_queue_lock); + /* + * vb2_video_unregister_device() releases the vb2 queue, which + * triggers airspy_stop_streaming() if streaming is active. + * stop_streaming() dereferences s->udev via airspy_ctrl_msg() and + * airspy_free_stream_bufs(), so it must run before s->udev is + * cleared. vb2_video_unregister_device() locks vb_queue_lock + * internally and stop_streaming() locks v4l2_lock, so neither may + * be held by the caller. + */ + v4l2_device_disconnect(&s->v4l2_dev); + vb2_video_unregister_device(&s->vdev); + mutex_lock(&s->v4l2_lock); - /* No need to keep the urbs around after disconnection */ s->udev = NULL; - v4l2_device_disconnect(&s->v4l2_dev); - video_unregister_device(&s->vdev); mutex_unlock(&s->v4l2_lock); - mutex_unlock(&s->vb_queue_lock); v4l2_device_put(&s->v4l2_dev); } diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index 9929ce5dcdcd..8ab100db01ab 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -124,6 +124,17 @@ struct au0828_board au0828_boards[] = { }, }, }, + [AU0828_BOARD_MONOPRICE_106456] = { + /* + * Monoprice 106456 USB ATSC/QAM tuner (board rev TV22AD-A), + * a.k.a. AnyTV AUTV002, USB ID 05e1:0400. Same AU8522 demod + + * NXP TDA18271HDC2 tuner @ 0x60 as the Hauppauge Woodbury. + */ + .name = "Monoprice 106456 USB ATSC/QAM (TV22AD-A)", + .tuner_type = TUNER_NXP_TDA18271, + .tuner_addr = 0x60, + .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, + }, [AU0828_BOARD_HAUPPAUGE_HVR1265] = { .name = "Hauppauge HVR1265", .tuner_type = TUNER_XC5000, @@ -294,6 +305,7 @@ void au0828_gpio_setup(struct au0828_dev *dev) case AU0828_BOARD_HAUPPAUGE_WOODBURY: case AU0828_BOARD_HAUPPAUGE_HVR1265: case AU0828_BOARD_HAUPPAUGE_IMPACTVCBE: + case AU0828_BOARD_MONOPRICE_106456: /* GPIO's * 4 - CS5340 * 5 - AU8522 Demodulator @@ -378,6 +390,8 @@ struct usb_device_id au0828_usb_id_table[] = { .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL }, { USB_DEVICE(0x05e1, 0x0480), .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, + { USB_DEVICE(0x05e1, 0x0400), + .driver_info = AU0828_BOARD_MONOPRICE_106456 }, { USB_DEVICE(0x2040, 0x8200), .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY }, { USB_DEVICE(0x2040, 0x7260), diff --git a/drivers/media/usb/au0828/au0828-cards.h b/drivers/media/usb/au0828/au0828-cards.h index a438aeb334a0..a4a283731f7d 100644 --- a/drivers/media/usb/au0828/au0828-cards.h +++ b/drivers/media/usb/au0828/au0828-cards.h @@ -13,3 +13,4 @@ #define AU0828_BOARD_HAUPPAUGE_WOODBURY 5 #define AU0828_BOARD_HAUPPAUGE_IMPACTVCBE 6 #define AU0828_BOARD_HAUPPAUGE_HVR1265 7 +#define AU0828_BOARD_MONOPRICE_106456 8 diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 31123e6f9fc3..9c95b7ceaecd 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -600,6 +600,7 @@ int au0828_dvb_register(struct au0828_dev *dev) &mxl5007t_hvr950q_config); break; case AU0828_BOARD_HAUPPAUGE_WOODBURY: + case AU0828_BOARD_MONOPRICE_106456: dvb->frontend = dvb_attach(au8522_attach, &hauppauge_woodbury_config, &dev->i2c_adap); diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 9c71b32552df..b24ceef497e4 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -443,6 +443,11 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) int ret; struct cx231xx *dev = snd_pcm_substream_chip(substream); + if (!dev) { + pr_err("cx231xx: called with null device\n"); + return -ENODEV; + } + dev_dbg(dev->dev, "closing device\n"); /* inform hardware to stop streaming */ diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 2cd4e333bc4b..70aa99fead27 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -898,7 +898,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, if (rc) return rc; - if (vb2_is_busy(&dev->vidq)) { + if (vb2_is_busy(&dev->vidq) || vb2_is_busy(&dev->vbiq)) { dev_err(dev->dev, "%s: queue busy\n", __func__); return -EBUSY; } @@ -933,7 +933,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) if (dev->norm == norm) return 0; - if (vb2_is_busy(&dev->vidq)) + if (vb2_is_busy(&dev->vidq) || vb2_is_busy(&dev->vbiq)) return -EBUSY; dev->norm = norm; diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index fbfb74eab475..b94b00456bcd 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2677,6 +2677,28 @@ const struct em28xx_board em28xx_boards[] = { .gpio = mygica_utv3_tuner_audio_gpio, } }, }, + /* eb1a:8286 StarTech SVID2USB232 + * Empia EM28281 with integrated TVP5150-compatible video decoder. + * Composite and S-Video inputs, stereo line-in audio. + */ + [EM28281_BOARD_STARTECH_SVID2USB232] = { + .name = "StarTech SVID2USB232", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .has_dvb = 0, + .decoder = EM28XX_BUILTIN, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, + .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, + .input = { { + .type = EM28XX_VMUX_COMPOSITE, + .vmux = EM2828X_COMPOSITE, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = EM2828X_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, [EM2828X_BOARD_HAUPPAUGE_USB_LIVE2] = { .name = "Hauppauge USB Live2", .vchannels = 2, @@ -2946,6 +2968,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2874_BOARD_HAUPPAUGE_USB_QUADHD }, { USB_DEVICE(0x2040, 0xc220), .driver_info = EM2828X_BOARD_HAUPPAUGE_USB_LIVE2 }, + { USB_DEVICE(0xeb1a, 0x8286), + .driver_info = EM28281_BOARD_STARTECH_SVID2USB232 }, { USB_DEVICE(0x2040, 0x0360), .driver_info = EM2828X_BOARD_HAUPPAUGE_935_V2 }, { USB_DEVICE(0x2040, 0x8360), @@ -3758,7 +3782,7 @@ void em28xx_free_device(struct kref *ref) { struct em28xx *dev = kref_to_dev(ref); - dev_info(&dev->intf->dev, "Freeing device\n"); + pr_info("%s: Freeing device\n", dev->name); if (!dev->disconnected) em28xx_release_resources(dev); @@ -3859,6 +3883,11 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; + case CHIP_ID_EM28281: + chip_name = "em28281"; + dev->wait_after_write = 0; + dev->eeprom_addrwidth_16bit = 1; + break; case CHIP_ID_EM2883: chip_name = "em2882/3"; dev->wait_after_write = 0; @@ -4082,7 +4111,7 @@ static void em28xx_check_usb_descriptor(struct em28xx *dev, dev->analog_ep_bulk = e->bEndpointAddress; } return; - }; + } } /* diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 5bbb082dbed9..0b998e7cafef 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -632,7 +632,7 @@ void em2828X_decoder_vmux(struct em28xx *dev, unsigned int vin) default: dev_dbg(&dev->intf->dev, "EM2828X_SVIDEO\n"); break; - }; + } em28xx_write_reg(dev, 0x24, 0x00); em28xx_write_reg(dev, 0x25, 0x02); @@ -1265,6 +1265,8 @@ void em28xx_close_extension(struct em28xx *dev) ops->fini(dev); } } + if (dev->dev_next) + list_del(&dev->dev_next->devlist); list_del(&dev->devlist); mutex_unlock(&em28xx_devlist_mutex); } diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 938f1980d448..8482fc4045ea 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -29,7 +29,7 @@ #include <media/dmxdev.h> #include <media/tuner.h> #include "tuner-simple.h" -#include <linux/gpio.h> +#include <linux/gpio/legacy.h> #include "lgdt330x.h" #include "lgdt3305.h" diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 68a0fcc2fa72..8931733a8e24 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -283,6 +283,7 @@ enum em28xx_chip_id { CHIP_ID_EM2884 = 68, CHIP_ID_EM28174 = 113, CHIP_ID_EM28178 = 114, + CHIP_ID_EM28281 = 145, CHIP_ID_EM2828X = 148, }; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index da0422c65e5f..c418add65bb5 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1213,6 +1213,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) { struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct em28xx_dmaqueue *dmaq = vq->type == V4L2_BUF_TYPE_VBI_CAPTURE ? + &dev->vbiq : &dev->vidq; + unsigned long flags = 0; struct v4l2_frequency f; struct v4l2_fh *owner; int rc = 0; @@ -1227,7 +1230,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) */ rc = res_get(dev, vq->type); if (rc) - return rc; + goto exit; if (v4l2->streaming_users == 0) { /* First active streaming user, so allocate all the URBs */ @@ -1250,7 +1253,7 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) em28xx_urb_data_copy); if (rc < 0) { res_free(dev, vq->type); - return rc; + goto exit; } /* @@ -1275,7 +1278,18 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) } v4l2->streaming_users++; + return 0; + +exit: + spin_lock_irqsave(&dev->slock, flags); + while (!list_empty(&dmaq->active)) { + struct em28xx_buffer *buf; + buf = list_entry(dmaq->active.next, struct em28xx_buffer, list); + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + spin_unlock_irqrestore(&dev->slock, flags); return rc; } @@ -2275,18 +2289,27 @@ static int radio_s_tuner(struct file *file, void *priv, } /* - * em28xx_free_v4l2() - Free struct em28xx_v4l2 + * em28xx_free_v4l2() - v4l2_device release callback * - * @ref: struct kref for struct em28xx_v4l2 + * @v4l2_dev: pointer to struct v4l2_device embedded in struct em28xx_v4l2 * - * Called when all users of struct em28xx_v4l2 are gone + * Called by the v4l2 core when the last reference to the v4l2_device is + * released. At this point no userspace file handle nor video_device node + * keeps the v4l2 instance alive anymore, so it is safe to release all + * v4l2-related resources and drop the em28xx device reference taken when + * the v4l2 extension was initialized. */ -static void em28xx_free_v4l2(struct kref *ref) +static void em28xx_free_v4l2(struct v4l2_device *v4l2_dev) { - struct em28xx_v4l2 *v4l2 = container_of(ref, struct em28xx_v4l2, ref); + struct em28xx_v4l2 *v4l2 = + container_of(v4l2_dev, struct em28xx_v4l2, v4l2_dev); + struct em28xx *dev = v4l2->dev; - v4l2->dev->v4l2 = NULL; + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); + v4l2_device_unregister(v4l2_dev); + dev->v4l2 = NULL; kfree(v4l2); + kref_put(&dev->ref, em28xx_free_device); } /* @@ -2323,9 +2346,8 @@ static int em28xx_v4l2_open(struct file *filp) return -ENODEV; } - em28xx_videodbg("open dev=%s type=%s users=%d\n", - video_device_node_name(vdev), v4l2_type_names[fh_type], - v4l2->users); + em28xx_videodbg("open dev=%s type=%s\n", + video_device_node_name(vdev), v4l2_type_names[fh_type]); ret = v4l2_fh_open(filp); if (ret) { @@ -2336,7 +2358,7 @@ static int em28xx_v4l2_open(struct file *filp) return ret; } - if (v4l2->users == 0) { + if (v4l2_fh_is_singular_file(filp)) { em28xx_set_mode(dev, EM28XX_ANALOG_MODE); if (vdev->vfl_type != VFL_TYPE_RADIO) @@ -2354,10 +2376,6 @@ static int em28xx_v4l2_open(struct file *filp) v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_radio); } - kref_get(&dev->ref); - kref_get(&v4l2->ref); - v4l2->users++; - mutex_unlock(&dev->lock); return 0; @@ -2398,27 +2416,27 @@ static int em28xx_v4l2_fini(struct em28xx *dev) if (video_is_registered(&v4l2->radio_dev)) { dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->radio_dev)); - video_unregister_device(&v4l2->radio_dev); + vb2_video_unregister_device(&v4l2->radio_dev); } if (video_is_registered(&v4l2->vbi_dev)) { dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->vbi_dev)); - video_unregister_device(&v4l2->vbi_dev); + vb2_video_unregister_device(&v4l2->vbi_dev); } if (video_is_registered(&v4l2->vdev)) { dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->vdev)); - video_unregister_device(&v4l2->vdev); + vb2_video_unregister_device(&v4l2->vdev); } - v4l2_ctrl_handler_free(&v4l2->ctrl_handler); - v4l2_device_unregister(&v4l2->v4l2_dev); - - kref_put(&v4l2->ref, em28xx_free_v4l2); - mutex_unlock(&dev->lock); - kref_put(&dev->ref, em28xx_free_device); + /* + * Drop the initial reference taken at v4l2_device_register() time. + * The em28xx_free_v4l2() release callback will be invoked once all + * userspace file handles to the video device nodes are closed. + */ + v4l2_device_put(&v4l2->v4l2_dev); return 0; } @@ -2460,13 +2478,13 @@ static int em28xx_v4l2_close(struct file *filp) struct em28xx_v4l2 *v4l2 = dev->v4l2; struct usb_device *udev = interface_to_usbdev(dev->intf); int err; + bool last_user; - em28xx_videodbg("users=%d\n", v4l2->users); - - vb2_fop_release(filp); mutex_lock(&dev->lock); + last_user = v4l2_fh_is_singular_file(filp); + _vb2_fop_release(filp, NULL); - if (v4l2->users == 1) { + if (last_user) { /* No sense to try to write to the device */ if (dev->disconnected) goto exit; @@ -2489,10 +2507,7 @@ static int em28xx_v4l2_close(struct file *filp) } exit: - v4l2->users--; - kref_put(&v4l2->ref, em28xx_free_v4l2); mutex_unlock(&dev->lock); - kref_put(&dev->ref, em28xx_free_device); return 0; } @@ -2711,7 +2726,6 @@ static int em28xx_v4l2_init(struct em28xx *dev) mutex_unlock(&dev->lock); return -ENOMEM; } - kref_init(&v4l2->ref); v4l2->dev = dev; dev->v4l2 = v4l2; @@ -2722,9 +2736,21 @@ static int em28xx_v4l2_init(struct em28xx *dev) if (ret < 0) { dev_err(&dev->intf->dev, "Call to v4l2_device_register() failed!\n"); - goto err; + dev->v4l2 = NULL; + kfree(v4l2); + mutex_unlock(&dev->lock); + return ret; } + /* + * From this point on, em28xx_free_v4l2() will be used to release + * v4l2-related resources when the v4l2_device refcount reaches + * zero. Take a reference to the em28xx device so that it cannot + * be freed before the v4l2 instance is released. + */ + v4l2->v4l2_dev.release = em28xx_free_v4l2; + kref_get(&dev->ref); + hdl = &v4l2->ctrl_handler; v4l2_ctrl_handler_init(hdl, 9); v4l2->v4l2_dev.ctrl_handler = hdl; @@ -3048,8 +3074,6 @@ static int em28xx_v4l2_init(struct em28xx *dev) dev_info(&dev->intf->dev, "V4L2 extension successfully initialized\n"); - kref_get(&dev->ref); - mutex_unlock(&dev->lock); return 0; @@ -3058,27 +3082,29 @@ unregister_dev: dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->radio_dev)); - video_unregister_device(&v4l2->radio_dev); + vb2_video_unregister_device(&v4l2->radio_dev); } if (video_is_registered(&v4l2->vbi_dev)) { dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->vbi_dev)); - video_unregister_device(&v4l2->vbi_dev); + vb2_video_unregister_device(&v4l2->vbi_dev); } if (video_is_registered(&v4l2->vdev)) { dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n", video_device_node_name(&v4l2->vdev)); - video_unregister_device(&v4l2->vdev); + vb2_video_unregister_device(&v4l2->vdev); } - v4l2_ctrl_handler_free(&v4l2->ctrl_handler); - v4l2_device_unregister(&v4l2->v4l2_dev); -err: - dev->v4l2 = NULL; - kref_put(&v4l2->ref, em28xx_free_v4l2); mutex_unlock(&dev->lock); + + /* + * Drop the initial reference. em28xx_free_v4l2() will be called + * once the last video_device node release has decremented the + * v4l2_device refcount to zero. + */ + v4l2_device_put(&v4l2->v4l2_dev); return ret; } diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 711f281613f5..8eee639b0940 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -150,6 +150,7 @@ #define EM2828X_BOARD_HAUPPAUGE_955_V2 110 #define EM2828X_BOARD_HAUPPAUGE_975_V2 111 #define EM28178_BOARD_PCTV_461E_V3 112 +#define EM28281_BOARD_STARTECH_SVID2USB232 113 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -558,7 +559,6 @@ struct em28xx_eeprom { #define EM28XX_RESOURCE_VBI 0x02 struct em28xx_v4l2 { - struct kref ref; struct em28xx *dev; struct v4l2_device v4l2_dev; @@ -582,7 +582,6 @@ struct em28xx_v4l2 { int sensor_yres; int sensor_xtal; - int users; /* user count for exclusive use */ int streaming_users; /* number of actively streaming users */ u32 frequency; /* selected tuner frequency */ diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c index 25b3ee25aaa4..453ab5c3aa03 100644 --- a/drivers/media/usb/go7007/go7007-driver.c +++ b/drivers/media/usb/go7007/go7007-driver.c @@ -264,17 +264,17 @@ int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs) ret = go7007_init_encoder(go); mutex_unlock(&go->hw_lock); if (ret < 0) - return ret; + goto err_unregister_v4l2_dev; ret = go7007_v4l2_ctrl_init(go); if (ret < 0) - return ret; + goto err_free_controls; if (!go->i2c_adapter_online && go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { ret = go7007_i2c_init(go); if (ret < 0) - return ret; + goto err_free_controls; go->i2c_adapter_online = 1; } if (go->i2c_adapter_online) { @@ -304,13 +304,19 @@ int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs) ret = go7007_v4l2_init(go); if (ret < 0) - return ret; + goto err_free_controls; if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) { go->audio_enabled = 1; go7007_snd_init(go); } return 0; + +err_free_controls: + v4l2_ctrl_handler_free(&go->hdl); +err_unregister_v4l2_dev: + v4l2_device_unregister(&go->v4l2_dev); + return ret; } EXPORT_SYMBOL(go7007_register_encoder); diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index 86ce593e0c54..8cf959c20e30 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -13,6 +13,7 @@ */ #include <linux/module.h> +#include <linux/bitops.h> #include <linux/time.h> #include <linux/mm.h> #include <linux/device.h> @@ -58,14 +59,16 @@ struct code_gen { #define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 } #define CODE_ADD(name, val, length) do { \ - name.b -= (length); \ - name.a |= (val) << name.b; \ - while (name.b <= 24) { \ - *name.p = name.a >> 24; \ - ++name.p; \ - name.a <<= 8; \ - name.b += 8; \ - name.len += 8; \ + if (length) { \ + name.b -= (length); \ + name.a |= (val) << name.b; \ + while (name.b <= 24) { \ + *name.p = name.a >> 24; \ + ++name.p; \ + name.a <<= 8; \ + name.b += 8; \ + name.len += 8; \ + } \ } \ } while (0) @@ -707,11 +710,10 @@ done: static int vti_bitlen(struct go7007 *go) { - unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; + unsigned int max_time_incr = go->sensor_framerate / go->fps_scale; + int bitlen = fls(max_time_incr); - for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i) - ; - return i + 1; + return bitlen ?: 1; } static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf, @@ -1209,7 +1211,7 @@ static int seqhead_to_package(struct go7007 *go, __le16 *code, int space, 0xbf08, fps, 0xbf09, 0, 0xbff2, vop_time_increment_bitlength, - 0xbff3, (1 << vop_time_increment_bitlength) - 1, + 0xbff3, GENMASK(vop_time_increment_bitlength - 1, 0), 0xbfe6, 0, 0xbfe7, (fps / 1000) << 8, 0, 0, diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c index e4b9f37be77b..01d547ad678d 100644 --- a/drivers/media/usb/go7007/snd-go7007.c +++ b/drivers/media/usb/go7007/snd-go7007.c @@ -195,6 +195,13 @@ static const struct snd_device_ops go7007_snd_device_ops = { .dev_free = go7007_snd_free, }; +static void go7007_snd_card_free(struct snd_card *card) +{ + struct go7007 *go = card->private_data; + + v4l2_device_put(&go->v4l2_dev); +} + int go7007_snd_init(struct go7007 *go) { static int dev; @@ -245,6 +252,8 @@ int go7007_snd_init(struct go7007 *go) gosnd->substream = NULL; go->snd_context = gosnd; v4l2_device_get(&go->v4l2_dev); + gosnd->card->private_data = go; + gosnd->card->private_free = go7007_snd_card_free; ++dev; return 0; @@ -263,7 +272,6 @@ int go7007_snd_remove(struct go7007 *go) snd_card_disconnect(gosnd->card); snd_card_free_when_closed(gosnd->card); - v4l2_device_put(&go->v4l2_dev); return 0; } EXPORT_SYMBOL(go7007_snd_remove); diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 0b8182edf8e4..3917913c3b47 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -2277,6 +2277,11 @@ static int s2255_probe(struct usb_interface *interface, } /* check the firmware is valid */ fw_size = dev->fw_data->fw->size; + if (fw_size < 8) { + dev_err(&interface->dev, "Firmware invalid: too small.\n"); + retval = -ENODEV; + goto errorFWMARKER; + } pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; if (*pdata != S2255_FW_MARKER) { diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c index f9462a9ca761..5058cada0d0a 100644 --- a/drivers/media/usb/stk1160/stk1160-core.c +++ b/drivers/media/usb/stk1160/stk1160-core.c @@ -263,7 +263,7 @@ static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev, static int stk1160_probe(struct usb_interface *interface, const struct usb_device_id *id) { - int rc = 0; + int rc; unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct usb_device *udev; @@ -290,15 +290,13 @@ static int stk1160_probe(struct usb_interface *interface, * Also, check if device speed is fast enough. */ rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size); - if (rc < 0) { - kfree(alt_max_pkt_size); - return rc; - } + if (rc < 0) + goto free_array; dev = kzalloc_obj(struct stk1160); if (dev == NULL) { - kfree(alt_max_pkt_size); - return -ENOMEM; + rc = -ENOMEM; + goto free_array; } dev->alt_max_pkt_size = alt_max_pkt_size; @@ -379,8 +377,9 @@ unreg_v4l2: free_ctrl: v4l2_ctrl_handler_free(&dev->ctrl_handler); free_err: - kfree(alt_max_pkt_size); kfree(dev); +free_array: + kfree(alt_max_pkt_size); return rc; } diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index f4baf9263286..020b75fc5b2d 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -48,6 +48,9 @@ static inline void print_err_status(struct stk1160 *dev, case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break; + case -ESHUTDOWN: + errmsg = "host controller removed"; + break; case -ETIME: errmsg = "Device does not respond"; break; diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c index 333bd305a4f9..ae0a14e5ed2a 100644 --- a/drivers/media/usb/usbtv/usbtv-audio.c +++ b/drivers/media/usb/usbtv/usbtv-audio.c @@ -317,6 +317,13 @@ static const struct snd_pcm_ops snd_usbtv_pcm_ops = { .pointer = snd_usbtv_pointer, }; +static void usbtv_audio_card_free(struct snd_card *card) +{ + struct usbtv *usbtv = card->private_data; + + v4l2_device_put(&usbtv->v4l2_dev); +} + int usbtv_audio_init(struct usbtv *usbtv) { int rv; @@ -331,6 +338,10 @@ int usbtv_audio_init(struct usbtv *usbtv) if (rv < 0) return rv; + v4l2_device_get(&usbtv->v4l2_dev); + card->private_data = usbtv; + card->private_free = usbtv_audio_card_free; + strscpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver)); strscpy(card->shortname, "usbtv", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 888a2e213b08..f36d60e6ff41 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -898,9 +898,18 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) sd->subdev_notifier = NULL; if (sd->asc_list.next) { - list_for_each_entry_safe(asc, asc_tmp, &sd->asc_list, - asc_subdev_entry) { - v4l2_async_unbind_subdev_one(asc->notifier, asc); + if (list_empty(&sd->asc_list)) { + /* + * If the sub-device was registered through other means + * than v4l2-async, there are no async connections but + * the sub-device may still well be registered. + * Unregister it now. + */ + v4l2_device_unregister_subdev(sd); + } else { + list_for_each_entry_safe(asc, asc_tmp, &sd->asc_list, + asc_subdev_entry) + v4l2_async_unbind_subdev_one(asc->notifier, asc); } } diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index ba047d7d8601..1214e7744ac0 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -16,6 +16,9 @@ static const union v4l2_ctrl_ptr ptr_null; +#define V4L2_HEVC_MAX_SHORT_TERM_REF_PIC_SETS 64 +#define V4L2_HEVC_MAX_LONG_TERM_REF_PICS_SPS 32 + static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes) { @@ -1214,6 +1217,10 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_HEVC_SPS: p_hevc_sps = p; + if (p_hevc_sps->num_short_term_ref_pic_sets > + V4L2_HEVC_MAX_SHORT_TERM_REF_PIC_SETS) + return -EINVAL; + if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_PCM_ENABLED)) { p_hevc_sps->pcm_sample_bit_depth_luma_minus1 = 0; p_hevc_sps->pcm_sample_bit_depth_chroma_minus1 = 0; @@ -1224,6 +1231,9 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, if (!(p_hevc_sps->flags & V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT)) p_hevc_sps->num_long_term_ref_pics_sps = 0; + else if (p_hevc_sps->num_long_term_ref_pics_sps > + V4L2_HEVC_MAX_LONG_TERM_REF_PICS_SPS) + return -EINVAL; break; case V4L2_CTRL_TYPE_HEVC_PPS: @@ -1280,6 +1290,11 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, if (p_hevc_st_rps->flags & ~V4L2_HEVC_EXT_SPS_ST_RPS_FLAG_INTER_REF_PIC_SET_PRED) return -EINVAL; + if (p_hevc_st_rps->num_negative_pics > 16 || + p_hevc_st_rps->num_positive_pics > 16 || + p_hevc_st_rps->num_negative_pics + + p_hevc_st_rps->num_positive_pics > 16) + return -EINVAL; break; case V4L2_CTRL_TYPE_HEVC_EXT_SPS_LT_RPS: diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 62a3a452f788..570df3c415b0 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -633,6 +633,8 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode, if (!link->remote_node) goto err_put_remote_endpoint; + fwnode_handle_put(fwnode); + return 0; err_put_remote_endpoint: diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c index 115bb37577a1..adff564bf3fd 100644 --- a/drivers/platform/x86/intel/int3472/discrete.c +++ b/drivers/platform/x86/intel/int3472/discrete.c @@ -164,6 +164,24 @@ static const struct int3472_gpio_map int3472_gpio_map[] = { .con_id = "dvdd", .enable_time_us = 45 * USEC_PER_MSEC, }, + { /* imx471 expects "vana" as con_id for power enable */ + .hid = "SONY471A", + .type_from = INT3472_GPIO_TYPE_POWER_ENABLE, + .type_to = INT3472_GPIO_TYPE_POWER_ENABLE, + .con_id = "vana", + .enable_time_us = GPIO_REGULATOR_ENABLE_TIME, + }, + { + /* + * imx471 (on Lenovo ThinkPads X1 G14) expects "vana" as con_id + * for power enable + */ + .hid = "TBE20A0", + .type_from = INT3472_GPIO_TYPE_POWER_ENABLE, + .type_to = INT3472_GPIO_TYPE_POWER_ENABLE, + .con_id = "vana", + .enable_time_us = GPIO_REGULATOR_ENABLE_TIME, + }, }; static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3472, u8 *type, diff --git a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h index 4732b45b25ee..fbcd73b711ba 100644 --- a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h +++ b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf.h @@ -20,7 +20,7 @@ * Data structures. * ****************************************************************/ -/** +/* * @brief Data structure for the circular buffer. */ typedef struct ia_css_circbuf_s ia_css_circbuf_t; @@ -29,7 +29,7 @@ struct ia_css_circbuf_s { ia_css_circbuf_elem_t *elems; /* an array of elements */ }; -/** +/* * @brief Create the circular buffer. * * @param cb The pointer to the circular buffer. @@ -41,7 +41,7 @@ void ia_css_circbuf_create( ia_css_circbuf_elem_t *elems, ia_css_circbuf_desc_t *desc); -/** +/* * @brief Destroy the circular buffer. * * @param cb The pointer to the circular buffer. @@ -49,7 +49,7 @@ void ia_css_circbuf_create( void ia_css_circbuf_destroy( ia_css_circbuf_t *cb); -/** +/* * @brief Pop a value out of the circular buffer. * Get a value at the head of the circular buffer. * The user should call "ia_css_circbuf_is_empty()" @@ -62,7 +62,7 @@ void ia_css_circbuf_destroy( uint32_t ia_css_circbuf_pop( ia_css_circbuf_t *cb); -/** +/* * @brief Extract a value out of the circular buffer. * Get a value at an arbitrary position in the circular * buffer. The user should call "ia_css_circbuf_is_empty()" @@ -82,7 +82,7 @@ uint32_t ia_css_circbuf_extract( * Inline functions. * ****************************************************************/ -/** +/* * @brief Set the "val" field in the element. * * @param elem The pointer to the element. @@ -97,7 +97,7 @@ static inline void ia_css_circbuf_elem_set_val( elem->val = val; } -/** +/* * @brief Initialize the element. * * @param elem The pointer to the element. @@ -109,7 +109,7 @@ static inline void ia_css_circbuf_elem_init( ia_css_circbuf_elem_set_val(elem, 0); } -/** +/* * @brief Copy an element. * * @param src The element as the copy source. @@ -125,7 +125,7 @@ static inline void ia_css_circbuf_elem_cpy( ia_css_circbuf_elem_set_val(dest, src->val); } -/** +/* * @brief Get position in the circular buffer. * * @param cb The pointer to the circular buffer. @@ -151,7 +151,7 @@ static inline uint8_t ia_css_circbuf_get_pos_at_offset( return (base + offset) % cb->desc->size; } -/** +/* * @brief Get the offset between two positions in the circular buffer. * Get the offset from the source position to the terminal position, * along the direction in which the new elements come in. @@ -178,7 +178,7 @@ static inline int ia_css_circbuf_get_offset( return offset; } -/** +/* * @brief Get the maximum number of elements. * * @param cb The pointer to the circular buffer. @@ -196,7 +196,7 @@ static inline uint32_t ia_css_circbuf_get_size( return cb->desc->size; } -/** +/* * @brief Get the number of available elements. * * @param cb The pointer to the circular buffer. @@ -216,7 +216,7 @@ static inline uint32_t ia_css_circbuf_get_num_elems( return (uint32_t)num; } -/** +/* * @brief Test if the circular buffer is empty. * * @param cb The pointer to the circular buffer. @@ -234,7 +234,7 @@ static inline bool ia_css_circbuf_is_empty( return ia_css_circbuf_desc_is_empty(cb->desc); } -/** +/* * @brief Test if the circular buffer is full. * * @param cb The pointer to the circular buffer. @@ -251,7 +251,7 @@ static inline bool ia_css_circbuf_is_full(ia_css_circbuf_t *cb) return ia_css_circbuf_desc_is_full(cb->desc); } -/** +/* * @brief Write a new element into the circular buffer. * Write a new element WITHOUT checking whether the * circular buffer is full or not. So it also overwrites @@ -275,7 +275,7 @@ static inline void ia_css_circbuf_write( cb->desc->end = ia_css_circbuf_get_pos_at_offset(cb, cb->desc->end, 1); } -/** +/* * @brief Push a value in the circular buffer. * Put a new value at the tail of the circular buffer. * The user should call "ia_css_circbuf_is_full()" @@ -300,7 +300,7 @@ static inline void ia_css_circbuf_push( ia_css_circbuf_write(cb, elem); } -/** +/* * @brief Get the number of free elements. * * @param cb The pointer to the circular buffer. @@ -316,7 +316,7 @@ static inline uint32_t ia_css_circbuf_get_free_elems( return ia_css_circbuf_desc_get_free_elems(cb->desc); } -/** +/* * @brief Peek an element in Circular Buffer. * * @param cb The pointer to the circular buffer. @@ -328,7 +328,7 @@ uint32_t ia_css_circbuf_peek( ia_css_circbuf_t *cb, int offset); -/** +/* * @brief Get an element in Circular Buffer. * * @param cb The pointer to the circular buffer. @@ -340,7 +340,7 @@ uint32_t ia_css_circbuf_peek_from_start( ia_css_circbuf_t *cb, int offset); -/** +/* * @brief Increase Size of a Circular Buffer. * Use 'CAUTION' before using this function, This was added to * support / fix issue with increasing size for tagger only diff --git a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h index 971e07f2acc5..090e2e764042 100644 --- a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h +++ b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_comm.h @@ -24,7 +24,7 @@ * Portable Data structures * ****************************************************************/ -/** +/* * @brief Data structure for the circular descriptor. */ typedef struct ia_css_circbuf_desc_s ia_css_circbuf_desc_t; @@ -40,7 +40,7 @@ struct ia_css_circbuf_desc_s { static_assert(sizeof(struct ia_css_circbuf_desc_s) == SIZE_OF_IA_CSS_CIRCBUF_DESC_S_STRUCT); -/** +/* * @brief Data structure for the circular buffer element. */ typedef struct ia_css_circbuf_elem_s ia_css_circbuf_elem_t; diff --git a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_desc.h b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_desc.h index 64f754f1d49b..3306a7a0fa5e 100644 --- a/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_desc.h +++ b/drivers/staging/media/atomisp/pci/base/circbuf/interface/ia_css_circbuf_desc.h @@ -17,7 +17,7 @@ * Inline functions. * ****************************************************************/ -/** +/* * @brief Test if the circular buffer is empty. * * @param cb_desc The pointer to the circular buffer descriptor. @@ -33,7 +33,7 @@ static inline bool ia_css_circbuf_desc_is_empty( return (cb_desc->end == cb_desc->start); } -/** +/* * @brief Test if the circular buffer descriptor is full. * * @param cb_desc The pointer to the circular buffer @@ -50,7 +50,7 @@ static inline bool ia_css_circbuf_desc_is_full( return ((cb_desc->end + 1) % cb_desc->size) == cb_desc->start; } -/** +/* * @brief Initialize the circular buffer descriptor * * @param cb_desc The pointer circular buffer descriptor @@ -64,7 +64,7 @@ static inline void ia_css_circbuf_desc_init( cb_desc->size = size; } -/** +/* * @brief Get a position in the circular buffer descriptor. * * @param cb The pointer to the circular buffer descriptor. @@ -89,7 +89,7 @@ static inline uint8_t ia_css_circbuf_desc_get_pos_at_offset( return (base + offset) % cb_desc->size; } -/** +/* * @brief Get the offset between two positions in the circular buffer * descriptor. * Get the offset from the source position to the terminal position, @@ -116,7 +116,7 @@ static inline int ia_css_circbuf_desc_get_offset( return offset; } -/** +/* * @brief Get the number of available elements. * * @param cb_desc The pointer to the circular buffer. @@ -137,7 +137,7 @@ static inline uint32_t ia_css_circbuf_desc_get_num_elems( return (uint32_t)num; } -/** +/* * @brief Get the number of free elements. * * @param cb_desc The pointer to the circular buffer descriptor. diff --git a/drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h b/drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h index 24cd99a659ca..dce8dd23b47c 100644 --- a/drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h +++ b/drivers/staging/media/atomisp/pci/camera/util/interface/ia_css_util.h @@ -81,7 +81,7 @@ bool ia_css_util_res_leq( struct ia_css_resolution b); /* ISP2401 */ -/** +/* * @brief Check if resolution is zero * * @param[in] resolution The resolution to check diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_private.h b/drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_private.h index 989f55bec519..43bb352a8e05 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_private.h +++ b/drivers/staging/media/atomisp/pci/css_2401_system/host/csi_rx_private.h @@ -21,7 +21,7 @@ * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Refer to "csi_rx_public.h" for details. */ @@ -35,7 +35,7 @@ static inline hrt_data csi_rx_fe_ctrl_reg_load( hrt_data)); } -/** +/* * @brief Store a value to the register. * Refer to "ibuf_ctrl_public.h" for details. */ @@ -51,7 +51,7 @@ static inline void csi_rx_fe_ctrl_reg_store( value); } -/** +/* * @brief Load the register value. * Refer to "csi_rx_public.h" for details. */ @@ -65,7 +65,7 @@ static inline hrt_data csi_rx_be_ctrl_reg_load( hrt_data)); } -/** +/* * @brief Store a value to the register. * Refer to "ibuf_ctrl_public.h" for details. */ @@ -88,7 +88,7 @@ static inline void csi_rx_be_ctrl_reg_store( * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the state of the csi rx fe dlane process. * Refer to "csi_rx_public.h" for details. */ @@ -103,7 +103,7 @@ static inline void csi_rx_fe_ctrl_get_dlane_state( csi_rx_fe_ctrl_reg_load(ID, _HRT_CSI_RX_DLY_CNT_SETTLE_DLANE_REG_IDX(lane)); } -/** +/* * @brief Get the csi rx fe state. * Refer to "csi_rx_public.h" for details. */ @@ -142,7 +142,7 @@ static inline void csi_rx_fe_ctrl_get_state( } } -/** +/* * @brief dump the csi rx fe state. * Refer to "csi_rx_public.h" for details. */ @@ -180,7 +180,7 @@ static inline void csi_rx_fe_ctrl_dump_state( } } -/** +/* * @brief Get the csi rx be state. * Refer to "csi_rx_public.h" for details. */ @@ -243,7 +243,7 @@ static inline void csi_rx_be_ctrl_get_state( } } -/** +/* * @brief Dump the csi rx be state. * Refer to "csi_rx_public.h" for details. */ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h b/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h index 4bd8209aaa01..85439d561ba3 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h +++ b/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_irq_private.h @@ -15,7 +15,7 @@ | Native command interface (NCI) | + -------------------------------------------------------*/ -/** +/* * @brief Get the isys irq status. * Refer to "isys_irq.h" for details. */ @@ -34,7 +34,7 @@ void isys_irqc_state_get( */ } -/** +/* * @brief Dump the isys irq status. * Refer to "isys_irq.h" for details. */ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_private.h b/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_private.h index 8e295cd78129..88a763365631 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_private.h +++ b/drivers/staging/media/atomisp/pci/css_2401_system/host/isys_stream2mmio_private.h @@ -27,7 +27,7 @@ * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the stream2mmio-controller state. * Refer to "stream2mmio_public.h" for details. */ @@ -45,7 +45,7 @@ STORAGE_CLASS_STREAM2MMIO_C void stream2mmio_get_state( stream2mmio_get_sid_state(ID, i, &state->sid_state[i]); } -/** +/* * @brief Get the state of the stream2mmio-controller sidess. * Refer to "stream2mmio_public.h" for details. */ @@ -76,7 +76,7 @@ STORAGE_CLASS_STREAM2MMIO_C void stream2mmio_get_sid_state( stream2mmio_reg_load(ID, sid_id, STREAM2MMIO_BLOCK_WHEN_NO_CMD_REG_ID); } -/** +/* * @brief Dump the state of the stream2mmio-controller sidess. * Refer to "stream2mmio_public.h" for details. */ @@ -92,7 +92,7 @@ STORAGE_CLASS_STREAM2MMIO_C void stream2mmio_print_sid_state( ia_css_print("\t \t block when no cmd 0x%x\n", state->block_when_no_cmd); } -/** +/* * @brief Dump the ibuf-controller state. * Refer to "stream2mmio_public.h" for details. */ @@ -119,7 +119,7 @@ STORAGE_CLASS_STREAM2MMIO_C void stream2mmio_dump_state( * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Refer to "stream2mmio_public.h" for details. */ @@ -137,7 +137,7 @@ STORAGE_CLASS_STREAM2MMIO_C hrt_data stream2mmio_reg_load( (reg_bank_offset + reg_idx) * sizeof(hrt_data)); } -/** +/* * @brief Store a value to the register. * Refer to "stream2mmio_public.h" for details. */ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h b/drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h index b8b98106bd31..0faf6ffdf55d 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h +++ b/drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h @@ -16,7 +16,7 @@ * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Refer to "pixelgen_public.h" for details. */ @@ -30,7 +30,7 @@ STORAGE_CLASS_PIXELGEN_C hrt_data pixelgen_ctrl_reg_load( hrt_data)); } -/** +/* * @brief Store a value to the register. * Refer to "pixelgen_ctrl_public.h" for details. */ @@ -53,7 +53,7 @@ STORAGE_CLASS_PIXELGEN_C void pixelgen_ctrl_reg_store( * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the pixelgen state. * Refer to "pixelgen_public.h" for details. */ @@ -117,7 +117,7 @@ STORAGE_CLASS_PIXELGEN_C void pixelgen_ctrl_get_state( pixelgen_ctrl_reg_load(ID, _PXG_TPG_B2_REG_IDX); } -/** +/* * @brief Dump the pixelgen state. * Refer to "pixelgen_public.h" for details. */ diff --git a/drivers/staging/media/atomisp/pci/css_2401_system/pixelgen_global.h b/drivers/staging/media/atomisp/pci/css_2401_system/pixelgen_global.h index 59e0b44bfdc3..b5a6a8f0c3d2 100644 --- a/drivers/staging/media/atomisp/pci/css_2401_system/pixelgen_global.h +++ b/drivers/staging/media/atomisp/pci/css_2401_system/pixelgen_global.h @@ -9,7 +9,7 @@ #include <type_support.h> -/** +/* * Pixel-generator. ("pixelgen_global.h") */ /* diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_common/timed_ctrl_global.h b/drivers/staging/media/atomisp/pci/hive_isp_css_common/timed_ctrl_global.h index 2dc0fb88399f..e4c136660b1e 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_common/timed_ctrl_global.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_common/timed_ctrl_global.h @@ -11,7 +11,7 @@ #include "timed_controller_defs.h" -/** +/* * Order of the input bits for the timed controller taken from * ISP_CSS_2401 System Architecture Description valid for * 2400, 2401. diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/device_access/device_access.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/device_access/device_access.h index ca33a1e03d8d..f5b0ff414395 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/device_access/device_access.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/device_access/device_access.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h index 2002960f078e..e8ce556bfd6a 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/csi_rx_public.h @@ -12,7 +12,7 @@ * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the csi rx frontend state. * Get the state of the csi rx frontend regiester-set. * @@ -22,7 +22,7 @@ void csi_rx_fe_ctrl_get_state( const csi_rx_frontend_ID_t ID, csi_rx_fe_ctrl_state_t *state); -/** +/* * @brief Dump the csi rx frontend state. * Dump the state of the csi rx frontend regiester-set. * @@ -32,7 +32,7 @@ void csi_rx_fe_ctrl_get_state( void csi_rx_fe_ctrl_dump_state( const csi_rx_frontend_ID_t ID, csi_rx_fe_ctrl_state_t *state); -/** +/* * @brief Get the state of the csi rx fe dlane. * Get the state of the register set per dlane process. * @@ -44,7 +44,7 @@ void csi_rx_fe_ctrl_get_dlane_state( const csi_rx_frontend_ID_t ID, const u32 lane, csi_rx_fe_ctrl_lane_t *dlane_state); -/** +/* * @brief Get the csi rx backend state. * Get the state of the csi rx backend regiester-set. * @@ -54,7 +54,7 @@ void csi_rx_fe_ctrl_get_dlane_state( void csi_rx_be_ctrl_get_state( const csi_rx_backend_ID_t ID, csi_rx_be_ctrl_state_t *state); -/** +/* * @brief Dump the csi rx backend state. * Dump the state of the csi rx backend regiester-set. * @@ -71,7 +71,7 @@ void csi_rx_be_ctrl_dump_state( * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Load the value of the register of the csi rx fe. * @@ -83,7 +83,7 @@ void csi_rx_be_ctrl_dump_state( hrt_data csi_rx_fe_ctrl_reg_load( const csi_rx_frontend_ID_t ID, const hrt_address reg); -/** +/* * @brief Store a value to the register. * Store a value to the register of the csi rx fe. * @@ -96,7 +96,7 @@ void csi_rx_fe_ctrl_reg_store( const csi_rx_frontend_ID_t ID, const hrt_address reg, const hrt_data value); -/** +/* * @brief Load the register value. * Load the value of the register of the csirx be. * @@ -108,7 +108,7 @@ void csi_rx_fe_ctrl_reg_store( hrt_data csi_rx_be_ctrl_reg_load( const csi_rx_backend_ID_t ID, const hrt_address reg); -/** +/* * @brief Store a value to the register. * Store a value to the register of the csi rx be. * diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_stream2mmio_public.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_stream2mmio_public.h index 7ed55d427cf6..e4f77e975f4e 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_stream2mmio_public.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/isys_stream2mmio_public.h @@ -12,7 +12,7 @@ * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the stream2mmio-controller state. * Get the state of the stream2mmio-controller regiester-set. * @@ -23,7 +23,7 @@ STORAGE_CLASS_STREAM2MMIO_H void stream2mmio_get_state( const stream2mmio_ID_t ID, stream2mmio_state_t *state); -/** +/* * @brief Get the state of the stream2mmio-controller sidess. * Get the state of the register set per buf-controller sidess. * @@ -42,7 +42,7 @@ STORAGE_CLASS_STREAM2MMIO_H void stream2mmio_get_sid_state( * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Load the value of the register of the stream2mmio-controller. * @@ -57,7 +57,7 @@ STORAGE_CLASS_STREAM2MMIO_H hrt_data stream2mmio_reg_load( const stream2mmio_sid_ID_t sid_id, const uint32_t reg_idx); -/** +/* * @brief Dump the SID processor state. * Dump the state of the sid regiester-set. * @@ -65,7 +65,7 @@ STORAGE_CLASS_STREAM2MMIO_H hrt_data stream2mmio_reg_load( */ STORAGE_CLASS_STREAM2MMIO_H void stream2mmio_print_sid_state( stream2mmio_sid_state_t *state); -/** +/* * @brief Dump the stream2mmio state. * Dump the state of the ibuf-controller regiester-set. * @@ -75,7 +75,7 @@ STORAGE_CLASS_STREAM2MMIO_H void stream2mmio_print_sid_state( STORAGE_CLASS_STREAM2MMIO_H void stream2mmio_dump_state( const stream2mmio_ID_t ID, stream2mmio_state_t *state); -/** +/* * @brief Store a value to the register. * Store a value to the registe of the stream2mmio-controller. * diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h index dc31ce3cd741..6aabf0b1995f 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/pixelgen_public.h @@ -12,7 +12,7 @@ * Native command interface (NCI). * *****************************************************/ -/** +/* * @brief Get the pixelgen state. * Get the state of the pixelgen regiester-set. * @@ -22,7 +22,7 @@ STORAGE_CLASS_PIXELGEN_H void pixelgen_ctrl_get_state( const pixelgen_ID_t ID, pixelgen_ctrl_state_t *state); -/** +/* * @brief Dump the pixelgen state. * Dump the state of the pixelgen regiester-set. * @@ -39,7 +39,7 @@ STORAGE_CLASS_PIXELGEN_H void pixelgen_ctrl_dump_state( * Device level interface (DLI). * *****************************************************/ -/** +/* * @brief Load the register value. * Load the value of the register of the pixelgen * @@ -51,7 +51,7 @@ STORAGE_CLASS_PIXELGEN_H void pixelgen_ctrl_dump_state( STORAGE_CLASS_PIXELGEN_H hrt_data pixelgen_ctrl_reg_load( const pixelgen_ID_t ID, const hrt_address reg); -/** +/* * @brief Store a value to the register. * Store a value to the registe of the pixelgen * diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/tag_public.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/tag_public.h index ad83ff97bbd6..1652c9f79349 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/tag_public.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/host/tag_public.h @@ -7,7 +7,7 @@ #ifndef __TAG_PUBLIC_H_INCLUDED__ #define __TAG_PUBLIC_H_INCLUDED__ -/** +/* * @brief Creates the tag description from the given parameters. * @param[in] num_captures * @param[in] skip @@ -21,7 +21,7 @@ sh_css_create_tag_descr(int num_captures, unsigned int exp_id, struct sh_css_tag_descr *tag_descr); -/** +/* * @brief Encodes the members of tag description into a 32-bit value. * @param[in] tag Pointer to the tag description * @return (unsigned int) Encoded 32-bit tag-info diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/platform_support.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/platform_support.h index 473d8d4fb9ba..20a5faad0716 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/platform_support.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/platform_support.h @@ -7,7 +7,7 @@ #ifndef __PLATFORM_SUPPORT_H_INCLUDED__ #define __PLATFORM_SUPPORT_H_INCLUDED__ -/** +/* * @file * Platform specific includes and functionality. */ diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h index 097be6bd3cb5..cbd290121a28 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/type_support.h @@ -7,7 +7,7 @@ #ifndef __TYPE_SUPPORT_H_INCLUDED__ #define __TYPE_SUPPORT_H_INCLUDED__ -/** +/* * @file * Platform specific types. * diff --git a/drivers/staging/media/atomisp/pci/ia_css_frame_public.h b/drivers/staging/media/atomisp/pci/ia_css_frame_public.h index 7acfedb541d8..936b17950b3a 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_frame_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_frame_public.h @@ -119,7 +119,7 @@ struct ia_css_frame_info { .raw_bayer_order = IA_CSS_BAYER_ORDER_NUM, \ } -/** +/* * Specifies the DVS loop delay in "frame periods" */ enum ia_css_frame_delay { diff --git a/drivers/staging/media/atomisp/pci/ia_css_host_data.h b/drivers/staging/media/atomisp/pci/ia_css_host_data.h index 0e45650cc1ab..547542577902 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_host_data.h +++ b/drivers/staging/media/atomisp/pci/ia_css_host_data.h @@ -10,7 +10,7 @@ #include <ia_css_types.h> /* ia_css_pipe */ -/** +/* * @brief Allocate structure ia_css_host_data. * * @param[in] size Size of the requested host data @@ -22,7 +22,7 @@ struct ia_css_host_data * ia_css_host_data_allocate(size_t size); -/** +/* * @brief Free structure ia_css_host_data. * * @param[in] me Pointer to structure, if a NULL is passed functions diff --git a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h index 2bb06b0ff5db..1d1b704b2bc6 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h +++ b/drivers/staging/media/atomisp/pci/ia_css_pipe_public.h @@ -44,7 +44,7 @@ enum ia_css_pipe_mode { /* Temporary define */ #define IA_CSS_PIPE_MODE_NUM (IA_CSS_PIPE_MODE_YUVPP + 1) -/** +/* * Enumeration of pipe versions. * the order should match with definition in sh_css_defs.h */ @@ -55,7 +55,7 @@ enum ia_css_pipe_version { IA_CSS_PIPE_VERSION_2_7 = 4 /** ISP2.7 pipe */ }; -/** +/* * Pipe configuration structure. * Resolution properties are filled by Driver, kernel configurations are * set by AIC @@ -123,7 +123,7 @@ struct ia_css_pipe_config { to retrieve shading gains which correspond to bayer data. */ }; -/** +/* * Default settings for newly created pipe configurations. */ #define DEFAULT_PIPE_CONFIG { \ @@ -175,7 +175,7 @@ struct ia_css_pipe_info { output at the first valid frame. */ }; -/** +/* * Defaults for ia_css_pipe_info structs. */ #define DEFAULT_PIPE_INFO {\ diff --git a/drivers/staging/media/atomisp/pci/ia_css_prbs.h b/drivers/staging/media/atomisp/pci/ia_css_prbs.h index abdbcb8fda53..3bb1e5dbb4fc 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_prbs.h +++ b/drivers/staging/media/atomisp/pci/ia_css_prbs.h @@ -19,7 +19,7 @@ enum ia_css_prbs_id { IA_CSS_PRBS_ID2 }; -/** +/* * Maximum number of PRBS IDs. * * Make sure the value of this define gets changed to reflect the correct @@ -27,7 +27,7 @@ enum ia_css_prbs_id { */ #define N_CSS_PRBS_IDS (IA_CSS_PRBS_ID2 + 1) -/** +/* * PRBS configuration structure. * * Seed the for the Pseudo Random Bit Sequence. diff --git a/drivers/staging/media/atomisp/pci/ia_css_stream.h b/drivers/staging/media/atomisp/pci/ia_css_stream.h index c8de632a8e12..578dc45785fc 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_stream.h +++ b/drivers/staging/media/atomisp/pci/ia_css_stream.h @@ -13,7 +13,7 @@ #include "ia_css_types.h" #include "ia_css_stream_public.h" -/** +/* * structure to hold all internal stream related information */ struct ia_css_stream { diff --git a/drivers/staging/media/atomisp/pci/ia_css_timer.h b/drivers/staging/media/atomisp/pci/ia_css_timer.h index da752834adf4..5c73e8c61588 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_timer.h +++ b/drivers/staging/media/atomisp/pci/ia_css_timer.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. @@ -42,7 +42,10 @@ struct ia_css_time_meas { clock_value_t end_timer_value; /** measured time in ticks */ }; -/**@brief SIZE_OF_IA_CSS_CLOCK_TICK_STRUCT checks to ensure correct alignment for struct ia_css_clock_tick. */ +/* + * @brief SIZE_OF_IA_CSS_CLOCK_TICK_STRUCT checks to ensure correct alignment + * for struct ia_css_clock_tick. + */ #define SIZE_OF_IA_CSS_CLOCK_TICK_STRUCT sizeof(clock_value_t) /* @brief checks to ensure correct alignment for ia_css_time_meas. */ #define SIZE_OF_IA_CSS_TIME_MEAS_STRUCT (sizeof(clock_value_t) \ diff --git a/drivers/staging/media/atomisp/pci/ia_css_types.h b/drivers/staging/media/atomisp/pci/ia_css_types.h index 2b7db9cda23a..7065eded7a33 100644 --- a/drivers/staging/media/atomisp/pci/ia_css_types.h +++ b/drivers/staging/media/atomisp/pci/ia_css_types.h @@ -53,7 +53,7 @@ #include "isp/kernels/output/output_1.0/ia_css_output_types.h" #define IA_CSS_DVS_STAT_GRID_INFO_SUPPORTED -/** Should be removed after Driver adaptation will be done */ +/* Should be removed after Driver adaptation will be done */ #define IA_CSS_VERSION_MAJOR 2 #define IA_CSS_VERSION_MINOR 0 @@ -421,7 +421,7 @@ struct ia_css_dvs_6axis_config { u32 *ycoords_uv; }; -/** +/* * This specifies the coordinates (x,y) */ struct ia_css_point { @@ -429,7 +429,7 @@ struct ia_css_point { s32 y; /** y coordinate */ }; -/** +/* * Digital zoom: * This feature is currently available only for video, but will become * available for preview and capture as well. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_types.h index 374261d25520..ee2cf2877b7d 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/conversion/conversion_1.0/ia_css_conversion_types.h @@ -7,7 +7,7 @@ #ifndef __IA_CSS_CONVERSION_TYPES_H #define __IA_CSS_CONVERSION_TYPES_H -/** +/* * Conversion Kernel parameters. * Deinterleave bayer quad into isys format * diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_types.h index 0b977eb7ad71..bbd97c71a6fd 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/eed1_8/ia_css_eed1_8_types.h @@ -13,7 +13,7 @@ #include "type_support.h" -/** +/* * \brief EED1_8 public parameters. * \details Struct with all parameters for the EED1.8 kernel that can be set * from the CSS API. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h index e32290d1c86b..d6785724fe97 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/hdr/ia_css_hdr_types.h @@ -10,44 +10,46 @@ #define IA_CSS_HDR_MAX_NUM_INPUT_FRAMES (3) -/** +/* * \brief HDR Irradiance Parameters * \detail Currently HDR parameters are used only for testing purposes */ struct ia_css_hdr_irradiance_params { - int test_irr; /** Test parameter */ - int match_shift[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Histogram matching shift parameter */ - int match_mul[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Histogram matching multiplication parameter */ - int thr_low[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Weight map soft threshold low bound parameter */ - int thr_high[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Weight map soft threshold high bound parameter */ - int thr_coeff[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Soft threshold linear function coefficien */ - int thr_shift[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - - 1]; /** Soft threshold precision shift parameter */ - int weight_bpp; /** Weight map bits per pixel */ + /* Test parameter */ + int test_irr; + /* Histogram matching shift parameter */ + int match_shift[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Histogram matching multiplication parameter */ + int match_mul[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Weight map soft threshold low bound parameter */ + int thr_low[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Weight map soft threshold high bound parameter */ + int thr_high[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Soft threshold linear function coefficien */ + int thr_coeff[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Soft threshold precision shift parameter */ + int thr_shift[IA_CSS_HDR_MAX_NUM_INPUT_FRAMES - 1]; + /* Weight map bits per pixel */ + int weight_bpp; }; -/** +/* * \brief HDR Deghosting Parameters * \detail Currently HDR parameters are used only for testing purposes */ struct ia_css_hdr_deghost_params { - int test_deg; /** Test parameter */ + int test_deg; /* Test parameter */ }; -/** +/* * \brief HDR Exclusion Parameters * \detail Currently HDR parameters are used only for testing purposes */ struct ia_css_hdr_exclusion_params { - int test_excl; /** Test parameter */ + int test_excl; /* Test parameter */ }; -/** +/* * \brief HDR public parameters. * \details Struct with all parameters for HDR that can be seet from * the CSS API. Currently, only test parameters are defined. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_param.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_param.h index c9a3f7bfaa90..de535503b70e 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_param.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_param.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_types.h index c1c93b2245c5..69a40a15264b 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/common/ia_css_common_io_types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h index e6ce0cba44b9..72310781cf7e 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_param.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_param.h index 429fcdb73f60..9fabb8b2d3b8 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_param.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_param.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_types.h index 485ad17cb29b..1daafd96a0cd 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io_types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr3/ia_css_tnr3_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr3/ia_css_tnr3_types.h index 42b760ffac67..676a633336a2 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr3/ia_css_tnr3_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr3/ia_css_tnr3_types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. @@ -12,7 +12,7 @@ Copyright (c) 2010 - 2015, Intel Corporation. * CSS-API header file for Temporal Noise Reduction v3 (TNR3) kernel */ -/** +/* * \brief Number of piecewise linear segments. * \details The parameters to TNR3 are specified as a piecewise linear segment. * The number of such segments is fixed at 3. diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_types.h index c012c1865d1e..fc4b9033951c 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3_types.h @@ -11,25 +11,25 @@ * CSS-API header file for Extra Noise Reduction (XNR) parameters. */ -/** +/* * \brief Scale of the XNR sigma parameters. * \details The define specifies which fixed-point value represents 1.0. */ #define IA_CSS_XNR3_SIGMA_SCALE BIT(10) -/** +/* * \brief Scale of the XNR coring parameters. * \details The define specifies which fixed-point value represents 1.0. */ #define IA_CSS_XNR3_CORING_SCALE BIT(15) -/** +/* * \brief Scale of the XNR blending parameter. * \details The define specifies which fixed-point value represents 1.0. */ #define IA_CSS_XNR3_BLENDING_SCALE BIT(11) -/** +/* * \brief XNR3 Sigma Parameters. * \details Sigma parameters define the strength of the XNR filter. * A higher number means stronger filtering. There are two values for each of @@ -46,7 +46,7 @@ struct ia_css_xnr3_sigma_params { int v1; /** Sigma for V range similarity in bright area */ }; -/** +/* * \brief XNR3 Coring Parameters * \details Coring parameters define the "coring" strength, which is a soft * thresholding technique to avoid false coloring. There are two values for @@ -61,7 +61,7 @@ struct ia_css_xnr3_coring_params { int v1; /** Coring threshold of V channel in bright area */ }; -/** +/* * \brief XNR3 Blending Parameters * \details Blending parameters define the blending strength of filtered * output pixels with the original chroma pixels from before xnr3. The @@ -75,7 +75,7 @@ struct ia_css_xnr3_blending_params { int strength; /** Blending strength */ }; -/** +/* * \brief XNR3 public parameters. * \details Struct with all parameters for the XNR3 kernel that can be set * from the CSS API. diff --git a/drivers/staging/media/atomisp/pci/isp/modes/interface/input_buf.isp.h b/drivers/staging/media/atomisp/pci/isp/modes/interface/input_buf.isp.h index 6a0257359e69..d6ed1fbb0e8e 100644 --- a/drivers/staging/media/atomisp/pci/isp/modes/interface/input_buf.isp.h +++ b/drivers/staging/media/atomisp/pci/isp/modes/interface/input_buf.isp.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h index 9c682f2ecbb2..5f768af9bc1d 100644 --- a/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h +++ b/drivers/staging/media/atomisp/pci/runtime/binary/interface/ia_css_binary.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq.h b/drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq.h index 3e7dadca6d70..618172f17b63 100644 --- a/drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq.h +++ b/drivers/staging/media/atomisp/pci/runtime/bufq/interface/ia_css_bufq.h @@ -13,7 +13,7 @@ #include "ia_css_err.h" #define BUFQ_EVENT_SIZE 4 -/** +/* * @brief Query the internal frame ID. * * @param[in] key The query key. @@ -29,7 +29,7 @@ bool ia_css_query_internal_queue_id( enum sh_css_queue_id *val ); -/** +/* * @brief Map buffer type to a internal queue id. * * @param[in] thread id Thread in which the buffer type has to be mapped or unmapped @@ -43,13 +43,13 @@ void ia_css_queue_map( bool map ); -/** +/* * @brief Initialize buffer type to a queue id mapping * @return none */ void ia_css_queue_map_init(void); -/** +/* * @brief initializes bufq module * It create instances of * -host to SP buffer queue which is a list with predefined size, @@ -62,7 +62,7 @@ void ia_css_queue_map_init(void); */ void ia_css_bufq_init(void); -/** +/* * @brief Enqueues an item into host to SP buffer queue * * @param thread_index[in] Thread in which the item to be enqueued @@ -77,7 +77,7 @@ int ia_css_bufq_enqueue_buffer( int queue_id, uint32_t item); -/** +/* * @brief Dequeues an item from SP to host buffer queue. * * @param queue_id[in] Specifies the index of the queue in the list where @@ -90,7 +90,7 @@ int ia_css_bufq_dequeue_buffer( int queue_id, uint32_t *item); -/** +/* * @brief Enqueue an event item into host to SP communication event queue. * * @param[in] evt_id The event ID. @@ -107,7 +107,7 @@ int ia_css_bufq_enqueue_psys_event( uint8_t evt_payload_2 ); -/** +/* * @brief Dequeue an item from SP to host communication event queue. * * @param item Object to be dequeued into this item. @@ -119,7 +119,7 @@ int ia_css_bufq_dequeue_psys_event( ); -/** +/* * @brief Enqueue an event item into host to SP EOF event queue. * * @param[in] evt_id The event ID. @@ -129,7 +129,7 @@ int ia_css_bufq_dequeue_psys_event( int ia_css_bufq_enqueue_isys_event( uint8_t evt_id); -/** +/* * @brief Dequeue an item from SP to host communication EOF event queue. * @@ -140,7 +140,7 @@ int ia_css_bufq_enqueue_isys_event( int ia_css_bufq_dequeue_isys_event( u8 item[BUFQ_EVENT_SIZE]); -/** +/* * @brief Enqueue a tagger command item into tagger command queue.. * * @param item Object to be enqueue. @@ -150,7 +150,7 @@ int ia_css_bufq_dequeue_isys_event( int ia_css_bufq_enqueue_tag_cmd( uint32_t item); -/** +/* * @brief Uninitializes bufq module. * * @return 0 or error code upon error. @@ -158,7 +158,7 @@ int ia_css_bufq_enqueue_tag_cmd( */ int ia_css_bufq_deinit(void); -/** +/* * @brief Dump queue states * * @return None diff --git a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h index 2d0e906530af..b7ff809eeeab 100644 --- a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h +++ b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug.h @@ -312,7 +312,7 @@ void ia_css_debug_dump_stream_config( const struct ia_css_stream_config *config, int num_pipes); -/** +/* * @brief Initialize the debug mode. * * WARNING: @@ -324,7 +324,7 @@ void ia_css_debug_dump_stream_config( */ bool ia_css_debug_mode_init(void); -/** +/* * @brief Disable the DMA channel. * * @param[in] dma_ID The ID of the target DMA. @@ -344,7 +344,7 @@ bool ia_css_debug_mode_disable_dma_channel( int dma_ID, int channel_id, int request_type); -/** +/* * @brief Enable the DMA channel. * * @param[in] dma_ID The ID of the target DMA. @@ -363,7 +363,7 @@ bool ia_css_debug_mode_enable_dma_channel( int channel_id, int request_type); -/** +/* * @brief Dump tracer data. * [Currently support is only for SKC] * @@ -373,7 +373,7 @@ bool ia_css_debug_mode_enable_dma_channel( void ia_css_debug_dump_trace(void); /* ISP2401 */ -/** +/* * @brief Program counter dumping (in loop) * * @param[in] id The ID of the SP diff --git a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_pipe.h b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_pipe.h index 80c58cb934d5..6f6cd77ce91d 100644 --- a/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_pipe.h +++ b/drivers/staging/media/atomisp/pci/runtime/debug/interface/ia_css_debug_pipe.h @@ -13,21 +13,21 @@ #include <ia_css_stream_public.h> #include "ia_css_pipeline.h" -/** +/* * @brief Internal debug support for constructing a pipe graph. * * @return None */ void ia_css_debug_pipe_graph_dump_prologue(void); -/** +/* * @brief Internal debug support for constructing a pipe graph. * * @return None */ void ia_css_debug_pipe_graph_dump_epilogue(void); -/** +/* * @brief Internal debug support for constructing a pipe graph. * @param[in] stage Pipeline stage. * @param[in] id Pipe id. @@ -38,7 +38,7 @@ void ia_css_debug_pipe_graph_dump_stage( struct ia_css_pipeline_stage *stage, enum ia_css_pipe_id id); -/** +/* * @brief Internal debug support for constructing a pipe graph. * @param[in] out_frame Output frame of SP raw copy. * @@ -47,7 +47,7 @@ void ia_css_debug_pipe_graph_dump_stage( void ia_css_debug_pipe_graph_dump_sp_raw_copy( struct ia_css_frame *out_frame); -/** +/* * @brief Internal debug support for constructing a pipe graph. * @param[in] stream_config info about sensor and input formatter. * diff --git a/drivers/staging/media/atomisp/pci/runtime/eventq/interface/ia_css_eventq.h b/drivers/staging/media/atomisp/pci/runtime/eventq/interface/ia_css_eventq.h index 9b058e296c93..f8ce32e9b90d 100644 --- a/drivers/staging/media/atomisp/pci/runtime/eventq/interface/ia_css_eventq.h +++ b/drivers/staging/media/atomisp/pci/runtime/eventq/interface/ia_css_eventq.h @@ -9,7 +9,7 @@ #include "ia_css_queue.h" /* queue APIs */ -/** +/* * @brief HOST receives event from SP. * * @param[in] eventq_handle eventq_handle. @@ -22,7 +22,7 @@ int ia_css_eventq_recv( ia_css_queue_t *eventq_handle, uint8_t *payload); -/** +/* * @brief The Host sends the event to SP. * The caller of this API will be blocked until the event * is sent. diff --git a/drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param_types.h b/drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param_types.h index d6d60508c1bf..095d1853670f 100644 --- a/drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param_types.h +++ b/drivers/staging/media/atomisp/pci/runtime/isp_param/interface/ia_css_isp_param_types.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/** +/* Support for Intel Camera Imaging ISP subsystem. Copyright (c) 2010 - 2015, Intel Corporation. diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h index 29eebe8f9078..8870ff294c1e 100644 --- a/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h +++ b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h @@ -15,7 +15,7 @@ #include <system_global.h> #include "ia_css_isys_comm.h" -/** +/* * Virtual Input System. (Input System 2401) */ typedef isp2401_input_system_cfg_t ia_css_isys_descr_t; @@ -28,7 +28,7 @@ enum mipi_port_id ia_css_isys_port_to_mipi_port( enum mipi_port_id api_port); -/** +/* * @brief Register one (virtual) stream. This is used to track when all * virtual streams are configured inside the input system. The CSI RX is * only started when all registered streams are configured. @@ -43,7 +43,7 @@ int ia_css_isys_csi_rx_register_stream( enum mipi_port_id port, uint32_t isys_stream_id); -/** +/* * @brief Unregister one (virtual) stream. This is used to track when all * virtual streams are configured inside the input system. The CSI RX is * only started when all registered streams are configured. @@ -97,7 +97,7 @@ int ia_css_isys_convert_stream_format_to_mipi_format( mipi_predictor_t compression, unsigned int *fmt_type); -/** +/* * Virtual Input System. (Input System 2401) */ ia_css_isys_error_t ia_css_isys_stream_create( diff --git a/drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h b/drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h index 8b7cbf31a1a2..04d9f1fdb5b0 100644 --- a/drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h +++ b/drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h @@ -219,7 +219,7 @@ int ia_css_pipeline_get_output_stage( */ bool ia_css_pipeline_uses_params(struct ia_css_pipeline *pipeline); -/** +/* * @brief get the SP thread ID. * * @param[in] key The query key, typical use is pipe_num. @@ -231,7 +231,7 @@ bool ia_css_pipeline_uses_params(struct ia_css_pipeline *pipeline); */ bool ia_css_pipeline_get_sp_thread_id(unsigned int key, unsigned int *val); -/** +/* * @brief Get the pipeline io status * * @param[in] None @@ -240,7 +240,7 @@ bool ia_css_pipeline_get_sp_thread_id(unsigned int key, unsigned int *val); */ struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void); -/** +/* * @brief Map an SP thread to this pipeline * * @param[in] pipe_num @@ -249,7 +249,7 @@ struct sh_css_sp_pipeline_io_status *ia_css_pipeline_get_pipe_io_status(void); */ void ia_css_pipeline_map(unsigned int pipe_num, bool map); -/** +/* * @brief Checks whether the pipeline is mapped to SP threads * * @param[in] Query key, typical use is pipe_num @@ -260,7 +260,7 @@ void ia_css_pipeline_map(unsigned int pipe_num, bool map); */ bool ia_css_pipeline_is_mapped(unsigned int key); -/** +/* * @brief Print pipeline thread mapping * * @param[in] none diff --git a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h index 00b903d950df..4c86c19811bb 100644 --- a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h +++ b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr.h @@ -17,12 +17,12 @@ #define STORAGE_CLASS_RMGR_C static inline #endif /* __INLINE_RMGR__ */ -/** +/* * @brief Initialize resource manager (host/common) */ int ia_css_rmgr_init(void); -/** +/* * @brief Uninitialize resource manager (host/common) */ void ia_css_rmgr_uninit(void); diff --git a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr_vbuf.h b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr_vbuf.h index 6820bfc77432..68285334bc88 100644 --- a/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr_vbuf.h +++ b/drivers/staging/media/atomisp/pci/runtime/rmgr/interface/ia_css_rmgr_vbuf.h @@ -12,7 +12,7 @@ #include <ia_css_types.h> #include <system_local.h> -/** +/* * @brief Data structure for the resource handle (host, vbuf) */ struct ia_css_rmgr_vbuf_handle { @@ -21,7 +21,7 @@ struct ia_css_rmgr_vbuf_handle { u32 size; }; -/** +/* * @brief Data structure for the resource pool (host, vbuf) */ struct ia_css_rmgr_vbuf_pool { @@ -32,14 +32,14 @@ struct ia_css_rmgr_vbuf_pool { struct ia_css_rmgr_vbuf_handle **handles; }; -/** +/* * @brief VBUF resource pools */ extern struct ia_css_rmgr_vbuf_pool *vbuf_ref; extern struct ia_css_rmgr_vbuf_pool *vbuf_write; extern struct ia_css_rmgr_vbuf_pool *hmm_buffer_pool; -/** +/* * @brief Initialize the resource pool (host, vbuf) * * @param pool The pointer to the pool @@ -47,7 +47,7 @@ extern struct ia_css_rmgr_vbuf_pool *hmm_buffer_pool; STORAGE_CLASS_RMGR_H int ia_css_rmgr_init_vbuf( struct ia_css_rmgr_vbuf_pool *pool); -/** +/* * @brief Uninitialize the resource pool (host, vbuf) * * @param pool The pointer to the pool @@ -55,7 +55,7 @@ STORAGE_CLASS_RMGR_H int ia_css_rmgr_init_vbuf( STORAGE_CLASS_RMGR_H void ia_css_rmgr_uninit_vbuf( struct ia_css_rmgr_vbuf_pool *pool); -/** +/* * @brief Acquire a handle from the pool (host, vbuf) * * @param pool The pointer to the pool @@ -65,7 +65,7 @@ STORAGE_CLASS_RMGR_H void ia_css_rmgr_acq_vbuf( struct ia_css_rmgr_vbuf_pool *pool, struct ia_css_rmgr_vbuf_handle **handle); -/** +/* * @brief Release a handle to the pool (host, vbuf) * * @param pool The pointer to the pool @@ -75,14 +75,14 @@ STORAGE_CLASS_RMGR_H void ia_css_rmgr_rel_vbuf( struct ia_css_rmgr_vbuf_pool *pool, struct ia_css_rmgr_vbuf_handle **handle); -/** +/* * @brief Retain the reference count for a handle (host, vbuf) * * @param handle The pointer to the handle */ void ia_css_rmgr_refcount_retain_vbuf(struct ia_css_rmgr_vbuf_handle **handle); -/** +/* * @brief Release the reference count for a handle (host, vbuf) * * @param handle The pointer to the handle diff --git a/drivers/staging/media/atomisp/pci/runtime/tagger/interface/ia_css_tagger_common.h b/drivers/staging/media/atomisp/pci/runtime/tagger/interface/ia_css_tagger_common.h index 79006c325de6..9208c650fde7 100644 --- a/drivers/staging/media/atomisp/pci/runtime/tagger/interface/ia_css_tagger_common.h +++ b/drivers/staging/media/atomisp/pci/runtime/tagger/interface/ia_css_tagger_common.h @@ -10,14 +10,14 @@ #include <system_local.h> #include <type_support.h> -/** +/* * @brief The tagger's circular buffer. * * Should be one less than NUM_CONTINUOUS_FRAMES in sh_css_internal.h */ #define MAX_CB_ELEMS_FOR_TAGGER 14 -/** +/* * @brief Data structure for the tagger buffer element. */ typedef struct { diff --git a/drivers/staging/media/atomisp/pci/sh_css_internal.h b/drivers/staging/media/atomisp/pci/sh_css_internal.h index 9155a83fcc03..ec68c16d4272 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_internal.h +++ b/drivers/staging/media/atomisp/pci/sh_css_internal.h @@ -80,7 +80,7 @@ #define SH_CSS_MAX_SP_THREADS 5 -/** +/* * The C99 standard does not specify the exact object representation of structs; * the representation is compiler dependent. * @@ -638,7 +638,7 @@ struct sh_css_sp_output { unsigned int sw_interrupt_value[SH_CSS_NUM_SDW_IRQS]; }; -/** +/* * @brief Data structure for the circular buffer. * The circular buffer is empty if "start == end". The * circular buffer is full if "(end + 1) % size == start". diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.h b/drivers/staging/media/atomisp/pci/sh_css_sp.h index 78aec5b7e8fa..6985ca200f09 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.h +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.h @@ -68,7 +68,7 @@ sh_css_read_host2sp_command(void); void sh_css_init_host2sp_frame_data(void); -/** +/* * @brief Update the offline frame information in host_sp_communication. * * @param[in] frame_num The offline frame number. @@ -80,7 +80,7 @@ sh_css_update_host2sp_offline_frame( struct ia_css_frame *frame, struct ia_css_metadata *metadata); -/** +/* * @brief Update the mipi frame information in host_sp_communication. * * @param[in] frame_num The mipi frame number. @@ -91,7 +91,7 @@ sh_css_update_host2sp_mipi_frame( unsigned int frame_num, struct ia_css_frame *frame); -/** +/* * @brief Update the mipi metadata information in host_sp_communication. * * @param[in] frame_num The mipi frame number. @@ -102,7 +102,7 @@ sh_css_update_host2sp_mipi_metadata( unsigned int frame_num, struct ia_css_metadata *metadata); -/** +/* * @brief Update the nr of mipi frames to use in host_sp_communication. * * @param[in] num_frames The number of mipi frames to use. @@ -110,7 +110,7 @@ sh_css_update_host2sp_mipi_metadata( void sh_css_update_host2sp_num_mipi_frames(unsigned int num_frames); -/** +/* * @brief Update the nr of offline frames to use in host_sp_communication. * * @param[in] num_frames The number of raw frames to use. @@ -170,7 +170,7 @@ sh_css_sp_set_disable_continuous_viewfinder(bool flag); void sh_css_sp_reset_global_vars(void); -/** +/* * @brief Initialize the DMA software-mask in the debug mode. * This API should be ONLY called in the debugging mode. * And it should be always called before the first call of @@ -185,7 +185,7 @@ sh_css_sp_reset_global_vars(void); bool sh_css_sp_init_dma_sw_reg(int dma_id); -/** +/* * @brief Set the DMA software-mask in the debug mode. * This API should be ONLYL called in the debugging mode. Must * call "sh_css_set_dma_sw_reg(...)" before this diff --git a/drivers/staging/media/atomisp/pci/system_global.h b/drivers/staging/media/atomisp/pci/system_global.h index e8a29f73d67a..ee1d9b66ccb1 100644 --- a/drivers/staging/media/atomisp/pci/system_global.h +++ b/drivers/staging/media/atomisp/pci/system_global.h @@ -293,7 +293,7 @@ typedef enum { } stream2mmio_sid_ID_t; /* end of Stream2MMIO */ -/** +/* * Input System 2401: CSI-MIPI recevier. */ typedef enum { @@ -324,7 +324,7 @@ typedef enum { N_ISYS2401_DMA_ID } isys2401_dma_ID_t; -/** +/* * Pixel-generator. ("system_global.h") */ typedef enum { diff --git a/drivers/staging/media/av7110/av7110.c b/drivers/staging/media/av7110/av7110.c index 862aee993889..06c43b5f8a87 100644 --- a/drivers/staging/media/av7110/av7110.c +++ b/drivers/staging/media/av7110/av7110.c @@ -942,16 +942,16 @@ static int av7110_start_feed(struct dvb_demux_feed *feed) (feed->pes_type <= DMX_PES_PCR)) { switch (demux->dmx.frontend->source) { case DMX_MEMORY_FE: - if (feed->ts_type & TS_DECODER) - if (feed->pes_type < 2 && - !(demux->pids[0] & 0x8000) && - !(demux->pids[1] & 0x8000)) { - dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); - dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); - ret = av7110_av_start_play(av7110, RP_AV); - if (!ret) - demux->playing = 1; - } + if (feed->pes_type >= 2 || + (demux->pids[0] & 0x8000) || + (demux->pids[1] & 0x8000)) + break; + + dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); + dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout); + ret = av7110_av_start_play(av7110, RP_AV); + if (!ret) + demux->playing = 1; break; default: ret = dvb_feed_start_pid(feed); diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c index 310e3f24e571..48a35bda4237 100644 --- a/drivers/staging/media/ipu7/ipu7.c +++ b/drivers/staging/media/ipu7/ipu7.c @@ -2343,7 +2343,7 @@ static int ipu7_init_fw_code_region_by_sys(struct ipu7_bus_device *sys, return ret; } - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { dev_err(dev, "Failed to get runtime PM\n"); return ret; @@ -2702,7 +2702,7 @@ static int ipu7_resume(struct device *dev) if (ret) dev_err(dev, "IPC reset protocol failed!\n"); - ret = pm_runtime_get_sync(&isp->psys->auxdev.dev); + ret = pm_runtime_resume_and_get(&isp->psys->auxdev.dev); if (ret < 0) { dev_err(dev, "Failed to get runtime PM\n"); return 0; diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c index a039d925c0fe..c18bf352b199 100644 --- a/drivers/staging/media/meson/vdec/vdec.c +++ b/drivers/staging/media/meson/vdec/vdec.c @@ -504,8 +504,8 @@ vdec_try_fmt_common(struct amvdec_session *sess, u32 size, case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: fmt_out = find_format(fmts, size, pixmp->pixelformat); if (!fmt_out) { - pixmp->pixelformat = V4L2_PIX_FMT_MPEG2; - fmt_out = find_format(fmts, size, pixmp->pixelformat); + pixmp->pixelformat = fmts[0].pixfmt; + fmt_out = &fmts[0]; } break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index bbd186b8035b..96acd52e380c 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -285,8 +285,10 @@ static int cedrus_init_ctrls(struct cedrus_dev *dev, struct cedrus_ctx *ctx) ctrl_size = sizeof(ctrl) * CEDRUS_CONTROLS_COUNT + 1; ctx->ctrls = kzalloc(ctrl_size, GFP_KERNEL); - if (!ctx->ctrls) + if (!ctx->ctrls) { + v4l2_ctrl_handler_free(hdl); return -ENOMEM; + } j = 0; for (i = 0; i < CEDRUS_CONTROLS_COUNT; i++) { diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 456134a9e8cf..01622013c109 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1257,6 +1257,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) struct device_node *parent; struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; unsigned int lanes; + int err; int ret = 0; ports = of_get_child_by_name(node, "ports"); @@ -1267,8 +1268,8 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) if (!of_node_name_eq(port, "port")) continue; - ret = of_property_read_u32(port, "reg", &port_num); - if (ret < 0) + err = of_property_read_u32(port, "reg", &port_num); + if (err < 0) continue; if (port_num > vi->soc->vi_max_channels) { @@ -1289,10 +1290,10 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) ep = of_graph_get_endpoint_by_regs(parent, 0, 0); of_node_put(parent); - ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), + err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &v4l2_ep); of_node_put(ep); - if (ret) + if (err) continue; lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; @@ -1468,7 +1469,6 @@ static int tegra_vi_graph_build(struct tegra_vi_channel *chan, struct tegra_vi *vi = chan->vi; struct tegra_vi_graph_entity *ent; struct fwnode_handle *ep = NULL; - struct v4l2_fwnode_link link; struct media_entity *local = entity->entity; struct media_entity *remote; struct media_pad *local_pad; @@ -1478,70 +1478,64 @@ static int tegra_vi_graph_build(struct tegra_vi_channel *chan, dev_dbg(vi->dev, "creating links for entity %s\n", local->name); - while (1) { - ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode, - ep); - if (!ep) - break; + fwnode_graph_for_each_endpoint(entity->asd.match.fwnode, ep) { + struct fwnode_handle *remote_parent __free(fwnode_handle) = NULL; + struct fwnode_handle *sink_ep __free(fwnode_handle) = NULL; + int src_idx, sink_idx; - ret = v4l2_fwnode_parse_link(ep, &link); - if (ret < 0) { - dev_err(vi->dev, "failed to parse link for %pOF: %d\n", - to_of_node(ep), ret); + src_idx = media_entity_get_fwnode_pad(local, ep, + MEDIA_PAD_FL_SOURCE); + if (src_idx < 0) { + dev_dbg(vi->dev, "no source pad found for %pfw\n", ep); continue; } - if (link.local_port >= local->num_pads) { - dev_err(vi->dev, "invalid port number %u on %pOF\n", - link.local_port, to_of_node(link.local_node)); - v4l2_fwnode_put_link(&link); - ret = -EINVAL; - break; + remote_parent = fwnode_graph_get_remote_port_parent(ep); + if (!remote_parent) { + dev_dbg(vi->dev, "no remote parent found for %pfw\n", + ep); + continue; } - local_pad = &local->pads[link.local_port]; + local_pad = &local->pads[src_idx]; /* Remote node is vi node. So use channel video entity and pad * as remote/sink. */ - if (link.remote_node == of_fwnode_handle(vi->dev->of_node)) { + if (remote_parent == of_fwnode_handle(vi->dev->of_node)) { remote = &chan->video.entity; remote_pad = &chan->pad; goto create_link; } - /* - * Skip sink ports, they will be processed from the other end - * of the link. - */ - if (local_pad->flags & MEDIA_PAD_FL_SINK) { - dev_dbg(vi->dev, "skipping sink port %pOF:%u\n", - to_of_node(link.local_node), link.local_port); - v4l2_fwnode_put_link(&link); - continue; - } - /* find the remote entity from notifier list */ ent = tegra_vi_graph_find_entity(&chan->notifier.done_list, - link.remote_node); + remote_parent); if (!ent) { - dev_err(vi->dev, "no entity found for %pOF\n", - to_of_node(link.remote_node)); - v4l2_fwnode_put_link(&link); + fwnode_handle_put(ep); + dev_err(vi->dev, "no entity found for %pfw\n", + remote_parent); ret = -ENODEV; break; } remote = ent->entity; - if (link.remote_port >= remote->num_pads) { - dev_err(vi->dev, "invalid port number %u on %pOF\n", - link.remote_port, - to_of_node(link.remote_node)); - v4l2_fwnode_put_link(&link); - ret = -EINVAL; - break; + + sink_ep = fwnode_graph_get_remote_endpoint(ep); + if (!sink_ep) { + dev_dbg(vi->dev, "no sink ep found for %pfw\n", + ep); + continue; + } + + sink_idx = media_entity_get_fwnode_pad(remote, sink_ep, + MEDIA_PAD_FL_SINK); + if (sink_idx < 0) { + dev_dbg(vi->dev, "no sink pad found for %pfw\n", + sink_ep); + continue; } - remote_pad = &remote->pads[link.remote_port]; + remote_pad = &remote->pads[sink_idx]; create_link: dev_dbg(vi->dev, "creating %s:%u -> %s:%u link\n", @@ -1551,8 +1545,8 @@ create_link: ret = media_create_pad_link(local, local_pad->index, remote, remote_pad->index, link_flags); - v4l2_fwnode_put_link(&link); if (ret < 0) { + fwnode_handle_put(ep); dev_err(vi->dev, "failed to create %s:%u -> %s:%u link: %d\n", local->name, local_pad->index, @@ -1561,7 +1555,6 @@ create_link: } } - fwnode_handle_put(ep); return ret; } diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c index 9ff1f1750a15..5fba11e31e1d 100644 --- a/drivers/staging/media/tegra-video/vip.c +++ b/drivers/staging/media/tegra-video/vip.c @@ -126,7 +126,7 @@ static int tegra_vip_channel_of_parse(struct tegra_vip *vip) if (!ep) { err = -EINVAL; dev_err_probe(dev, err, "%pOF: error getting endpoint node\n", np); - goto err_node_put; + return err; } fwh = of_fwnode_handle(ep); @@ -134,14 +134,14 @@ static int tegra_vip_channel_of_parse(struct tegra_vip *vip) of_node_put(ep); if (err) { dev_err_probe(dev, err, "%pOF: failed to parse v4l2 endpoint\n", np); - goto err_node_put; + return err; } num_pads = of_graph_get_endpoint_count(np); if (num_pads != TEGRA_VIP_PADS_NUM) { err = -EINVAL; dev_err_probe(dev, err, "%pOF: need 2 pads, got %d\n", np, num_pads); - goto err_node_put; + return err; } vip->chan.of_node = of_node_get(np); @@ -149,10 +149,6 @@ static int tegra_vip_channel_of_parse(struct tegra_vip *vip) vip->chan.pads[TEGRA_VIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; return 0; - -err_node_put: - of_node_put(np); - return err; } static int tegra_vip_channel_init(struct tegra_vip *vip) diff --git a/include/media/cec.h b/include/media/cec.h index 0c8e86115b6f..4c8b0950b377 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -85,7 +85,6 @@ struct cec_event_entry { struct cec_event ev; }; -#define CEC_NUM_CORE_EVENTS 2 #define CEC_NUM_EVENTS CEC_EVENT_PIN_5V_HIGH struct cec_fh { @@ -101,7 +100,6 @@ struct cec_fh { struct list_head events[CEC_NUM_EVENTS]; /* queued events */ u16 queued_events[CEC_NUM_EVENTS]; unsigned int total_queued_events; - struct cec_event_entry core_events[CEC_NUM_CORE_EVENTS]; struct list_head msgs; /* queued messages */ unsigned int queued_msgs; }; @@ -223,6 +221,8 @@ struct cec_adap_ops { * @tx_error_log_cnt: number of logged Error transmits since the adapter was * enabled. Used to avoid flooding the kernel log if this * happens a lot. + * @error_inj_tx_timeouts: error injection: the next @error_inj_tx_timeouts + * transmits will time out. * @notifier: CEC notifier * @pin: CEC pin status struct * @cec_dir: debugfs cec directory @@ -283,6 +283,8 @@ struct cec_adapter { u32 tx_low_drive_log_cnt; u32 tx_error_log_cnt; + u32 error_inj_tx_timeouts; + #ifdef CONFIG_CEC_NOTIFIER struct cec_notifier *notifier; #endif diff --git a/include/media/drv-intf/s3c_camif.h b/include/media/drv-intf/s3c_camif.h index f746851a5ce6..00d83620ea5f 100644 --- a/include/media/drv-intf/s3c_camif.h +++ b/include/media/drv-intf/s3c_camif.h @@ -31,8 +31,6 @@ struct s3c_camif_sensor_info { struct s3c_camif_plat_data { struct s3c_camif_sensor_info sensor; - int (*gpio_get)(void); - int (*gpio_put)(void); }; #endif /* MEDIA_S3C_CAMIF_ */ diff --git a/include/media/drv-intf/saa7146.h b/include/media/drv-intf/saa7146.h index 71ce63c99cb4..b8f2fe5680f0 100644 --- a/include/media/drv-intf/saa7146.h +++ b/include/media/drv-intf/saa7146.h @@ -77,13 +77,10 @@ struct saa7146_pci_extension_data { void *ext_priv; /* most likely a name string */ }; -#define MAKE_EXTENSION_PCI(x_var, x_vendor, x_device) \ - { \ - .vendor = PCI_VENDOR_ID_PHILIPS, \ - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, \ - .subvendor = x_vendor, \ - .subdevice = x_device, \ - .driver_data = (unsigned long)& x_var, \ +#define MAKE_EXTENSION_PCI(x_var, x_vendor, x_device) \ + { \ + PCI_VDEVICE_SUB(PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, (x_vendor), (x_device)),\ + .driver_data = (unsigned long)&(x_var), \ } struct saa7146_extension diff --git a/include/media/media-entity.h b/include/media/media-entity.h index d9b72cd87d52..fa393e840669 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -1387,6 +1387,7 @@ void media_remove_intf_links(struct media_interface *intf); * @entity: entity where the @operation will be called * @operation: type of the operation. Should be the name of a member of * struct &media_entity_operations. + * @args: arguments for the operation. * * This helper function will check if @operation is not %NULL. On such case, * it will issue a call to @operation\(@entity, @args\). diff --git a/include/media/rc-map.h b/include/media/rc-map.h index d90e4611b066..d95ed3e96de2 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -262,7 +262,6 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" #define RC_MAP_GOTVIEW7135 "rc-gotview7135" #define RC_MAP_HAUPPAUGE "rc-hauppauge" -#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" #define RC_MAP_HISI_POPLAR "rc-hisi-poplar" #define RC_MAP_HISI_TV_DEMO "rc-hisi-tv-demo" #define RC_MAP_IMON_MCE "rc-imon-mce" @@ -309,7 +308,6 @@ struct rc_map *rc_map_get(const char *name); #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" #define RC_MAP_PURPLETV "rc-purpletv" #define RC_MAP_PV951 "rc-pv951" -#define RC_MAP_RC5_TV "rc-rc5-tv" #define RC_MAP_RC6_MCE "rc-rc6-mce" #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" #define RC_MAP_REDDO "rc-reddo" diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 54c83b18d555..a13dca7c609f 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -736,8 +736,8 @@ long int video_usercopy(struct file *file, unsigned int cmd, * @cmd: Ioctl name. * @arg: Ioctl argument. * - * Method used to hancle an ioctl. Should be used to fill the - * &v4l2_ioctl_ops.unlocked_ioctl on all V4L2 drivers. + * Method used to handle an ioctl. Should be used to fill the + * &v4l2_file_operations.unlocked_ioctl on all V4L2 drivers. */ long int video_ioctl2(struct file *file, unsigned int cmd, unsigned long int arg); diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h index 71d2864fb235..d51e10c10fc0 100644 --- a/include/media/videobuf2-v4l2.h +++ b/include/media/videobuf2-v4l2.h @@ -72,6 +72,19 @@ struct vb2_v4l2_buffer { */ struct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp); +/** + * vb2_querybuf() - Query video buffer information + * @q: pointer to &struct vb2_queue with videobuf2 queue. + * @b: buffer structure passed from userspace to + * &v4l2_ioctl_ops->vidioc_querybuf handler in driver + * + * Should be called from vidioc_querybuf ioctl handler in driver. + * This function will verify the passed v4l2_buffer structure and fill the + * relevant information for the userspace. + * + * The return values from this function are intended to be directly returned + * from vidioc_querybuf handler in driver. + */ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b); /** diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h index 81a05c9c0706..fdfc97a6e4ec 100644 --- a/include/uapi/linux/cec.h +++ b/include/uapi/linux/cec.h @@ -403,6 +403,8 @@ struct cec_log_addrs { #define CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU (1 << 1) /* CDC-Only device: supports only CDC messages */ #define CEC_LOG_ADDRS_FL_CDC_ONLY (1 << 2) +/* Configuration failed */ +#define CEC_LOG_ADDRS_FL_CONFIG_FAILED (1 << 3) /** * struct cec_drm_connector_info - tells which drm connector is |
