From 01c7a8167d497469f4da392c3c009ebf3169bf43 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Fri, 9 Oct 2020 06:16:21 +0200 Subject: media: MAINTAINERS: rectify ZR36067 VIDEO FOR LINUX DRIVER section Commit 754f0f1ba8d9 ("media: MAINTAINERS: change maintainer of the zoran driver") added a new section in MAINTAINERS with an invalid file entry and at the wrong place for alphabetic ordering. Hence, ./scripts/get_maintainer.pl --self-test=patterns complains: warning: no file matches F: Documentation/media/v4l-drivers/zoran.rst Point the file entry to the right location and move the section to the right place in MAINTAINERS. Signed-off-by: Lukas Bulwahn Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index e73636b75f29..aa8ee8f69bc6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19419,6 +19419,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs.git F: Documentation/filesystems/zonefs.rst F: fs/zonefs/ +ZPOOL COMPRESSED PAGE STORAGE API +M: Dan Streetman +L: linux-mm@kvack.org +S: Maintained +F: include/linux/zpool.h +F: mm/zpool.c + ZR36067 VIDEO FOR LINUX DRIVER M: Corentin Labbe L: mjpeg-users@lists.sourceforge.net @@ -19429,13 +19436,6 @@ Q: https://patchwork.linuxtv.org/project/linux-media/list/ F: Documentation/driver-api/media/drivers/zoran.rst F: drivers/staging/media/zoran/ -ZPOOL COMPRESSED PAGE STORAGE API -M: Dan Streetman -L: linux-mm@kvack.org -S: Maintained -F: include/linux/zpool.h -F: mm/zpool.c - ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER M: Minchan Kim M: Nitin Gupta -- cgit v1.2.3 From 1342f51ec248324bec6149721e2aac1e4770c794 Mon Sep 17 00:00:00 2001 From: Robert Foss Date: Mon, 19 Oct 2020 20:56:20 +0200 Subject: media: MAINTAINERS: camss: Add Robert Foss as co-maintainer I would like to contribute some of my time to co-maintain the CAMSS driver. I'm currently working to extend CAMSS to new hardware platforms. Signed-off-by: Robert Foss Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index aa8ee8f69bc6..6955a91472af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14466,6 +14466,7 @@ W: https://wireless.wiki.kernel.org/en/users/Drivers/ath9k F: drivers/net/wireless/ath/ath9k/ QUALCOMM CAMERA SUBSYSTEM DRIVER +M: Robert Foss M: Todor Tomov L: linux-media@vger.kernel.org S: Maintained -- cgit v1.2.3 From 7b177d8f50d99f67b3f082d6eae30bab342a6dd7 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Thu, 10 Sep 2020 18:19:49 +0200 Subject: media: dt-bindings: media: mt9v111: Convert to json-schema Convert the mt9v111 bindings document to json-schema and update the MAINTAINERS file accordingly. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/i2c/aptina,mt9v111.txt | 46 ------------- .../bindings/media/i2c/aptina,mt9v111.yaml | 75 ++++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 76 insertions(+), 47 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt b/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt deleted file mode 100644 index bd896e9f67d1..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt +++ /dev/null @@ -1,46 +0,0 @@ -* Aptina MT9V111 CMOS sensor ----------------------------- - -The Aptina MT9V111 is a 1/4-Inch VGA-format digital image sensor with a core -based on Aptina MT9V011 sensor and an integrated Image Flow Processor (IFP). - -The sensor has an active pixel array of 640x480 pixels and can output a number -of image resolution and formats controllable through a simple two-wires -interface. - -Required properties: --------------------- - -- compatible: shall be "aptina,mt9v111". -- clocks: reference to the system clock input provider. - -Optional properties: --------------------- - -- enable-gpios: output enable signal, pin name "OE#". Active low. -- standby-gpios: low power state control signal, pin name "STANDBY". - Active high. -- reset-gpios: chip reset signal, pin name "RESET#". Active low. - -The device node must contain one 'port' child node with one 'endpoint' child -sub-node for its digital output video port, in accordance with the video -interface bindings defined in: -Documentation/devicetree/bindings/media/video-interfaces.txt - -Example: --------- - - &i2c1 { - camera@48 { - compatible = "aptina,mt9v111"; - reg = <0x48>; - - clocks = <&camera_clk>; - - port { - mt9v111_out: endpoint { - remote-endpoint = <&ceu_in>; - }; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml b/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml new file mode 100644 index 000000000000..ff9546e95d05 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/aptina,mt9v111.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Aptina MT9V111 CMOS sensor + +maintainers: + - Jacopo Mondi + +description: | + The Aptina MT9V111 is a 1/4-Inch VGA-format digital image sensor with a core + based on Aptina MT9V011 sensor and an integrated Image Flow Processor (IFP). + + The sensor has an active pixel array of 640x480 pixels and can output a number + of image resolutions and formats controllable through a simple two-wires + interface. + +properties: + compatible: + const: aptina,mt9v111 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + enable-gpios: + description: Enable signal, pin name "OE#". Active low. + maxItems: 1 + + standby-gpios: + description: | + Low power state control signal, pin name "STANDBY". Active high. + maxItems: 1 + + reset-gpios: + description: Chip reset signal, pin name "RESET#". Active low. + maxItems: 1 + + port: + type: object + description: | + Output video port. See ../video-interfaces.txt. + +required: + - compatible + - reg + - clocks + - port + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + camera@48 { + compatible = "aptina,mt9v111"; + reg = <0x48>; + clocks = <&camera_clk>; + + port { + mt9v111_out: endpoint { + remote-endpoint = <&ceu_in>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 6955a91472af..1e06081c965d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11931,7 +11931,7 @@ M: Jacopo Mondi L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.txt +F: Documentation/devicetree/bindings/media/i2c/aptina,mt9v111.yaml F: drivers/media/i2c/mt9v111.c MULTIFUNCTION DEVICES (MFD) -- cgit v1.2.3 From 8d9b35a2da8e0f03df97196557863ce425992b10 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Thu, 10 Sep 2020 18:20:30 +0200 Subject: media: dt-bindings: media: imx214: Convert to json-schema Convert the imx214 bindings document to json-schema and update the MAINTAINERS file accordingly. Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/sony,imx214.txt | 53 -------- .../devicetree/bindings/media/i2c/sony,imx214.yaml | 133 +++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 134 insertions(+), 54 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/sony,imx214.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx214.txt b/Documentation/devicetree/bindings/media/i2c/sony,imx214.txt deleted file mode 100644 index f11f28a5fda4..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/sony,imx214.txt +++ /dev/null @@ -1,53 +0,0 @@ -* Sony 1/3.06-Inch 13.13Mp CMOS Digital Image Sensor - -The Sony imx214 is a 1/3.06-inch CMOS active pixel digital image sensor with -an active array size of 4224H x 3200V. It is programmable through an I2C -interface. -Image data is sent through MIPI CSI-2, through 2 or 4 lanes at a maximum -throughput of 1.2Gbps/lane. - - -Required Properties: -- compatible: Shall be "sony,imx214". -- reg: I2C bus address of the device. Depending on how the sensor is wired, - it shall be <0x10> or <0x1a>; -- enable-gpios: GPIO descriptor for the enable pin. -- vdddo-supply: Chip digital IO regulator (1.8V). -- vdda-supply: Chip analog regulator (2.7V). -- vddd-supply: Chip digital core regulator (1.12V). -- clocks: Reference to the xclk clock. -- clock-frequency: Frequency of the xclk clock. - -Optional Properties: -- flash-leds: See ../video-interfaces.txt -- lens-focus: See ../video-interfaces.txt - -The imx214 device node shall contain one 'port' child node with -an 'endpoint' subnode. For further reading on port node refer to -Documentation/devicetree/bindings/media/video-interfaces.txt. - -Required Properties on endpoint: -- data-lanes: check ../video-interfaces.txt -- link-frequencies: check ../video-interfaces.txt -- remote-endpoint: check ../video-interfaces.txt - -Example: - - camera-sensor@1a { - compatible = "sony,imx214"; - reg = <0x1a>; - vdddo-supply = <&pm8994_lvs1>; - vddd-supply = <&camera_vddd_1v12>; - vdda-supply = <&pm8994_l17>; - lens-focus = <&ad5820>; - enable-gpios = <&msmgpio 25 GPIO_ACTIVE_HIGH>; - clocks = <&mmcc CAMSS_MCLK0_CLK>; - clock-frequency = <24000000>; - port { - imx214_ep: endpoint { - data-lanes = <1 2 3 4>; - link-frequencies = /bits/ 64 <480000000>; - remote-endpoint = <&csiphy0_ep>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml new file mode 100644 index 000000000000..0f5e25fa4e9d --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/sony,imx214.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sony 1/3.06-Inch 13.13MP CMOS Digital Image Sensor + +maintainers: + - Ricardo Ribalda + +description: | + The Sony IMX214 is a 1/3.06-inch CMOS active pixel digital image sensor with + an active array size of 4224H x 3200V. It is programmable through an I2C + interface. Image data is sent through MIPI CSI-2, through 2 or 4 lanes at a + maximum throughput of 1.2Gbps/lane. + +properties: + compatible: + const: sony,imx214 + + reg: + enum: + - 0x10 + - 0x1a + + clocks: + description: Reference to the xclk clock. + maxItems: 1 + + clock-frequency: + description: Frequency of the xclk clock in Hz. + + enable-gpios: + description: GPIO descriptor for the enable pin. + maxItems: 1 + + vdddo-supply: + description: Chip digital IO regulator (1.8V). + maxItems: 1 + + vdda-supply: + description: Chip analog regulator (2.7V). + maxItems: 1 + + vddd-supply: + description: Chip digital core regulator (1.12V). + maxItems: 1 + + flash-leds: + description: See ../video-interfaces.txt + + lens-focus: + description: See ../video-interfaces.txt + + port: + type: object + description: | + Video output port. See ../video-interfaces.txt. + + properties: + endpoint: + type: object + + properties: + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: See ../video-interfaces.txt + anyOf: + - items: + - const: 1 + - const: 2 + - items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + + link-frequencies: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: See ../video-interfaces.txt + + required: + - data-lanes + - link-frequencies + + unevaluatedProperties: false + + additionalProperties: false + +required: + - compatible + - reg + - clocks + - clock-frequency + - enable-gpios + - vdddo-supply + - vdda-supply + - vddd-supply + - port + +additionalProperties: false + +examples: + - | + #include + + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + camera-sensor@1a { + compatible = "sony,imx214"; + reg = <0x1a>; + vdddo-supply = <&pm8994_lvs1>; + vddd-supply = <&camera_vddd_1v12>; + vdda-supply = <&pm8994_l17>; + lens-focus = <&ad5820>; + enable-gpios = <&msmgpio 25 GPIO_ACTIVE_HIGH>; + clocks = <&camera_clk>; + clock-frequency = <24000000>; + + port { + imx214_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <480000000>; + remote-endpoint = <&csiphy0_ep>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 1e06081c965d..0717a87c1b41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16298,7 +16298,7 @@ M: Ricardo Ribalda L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/sony,imx214.txt +F: Documentation/devicetree/bindings/media/i2c/sony,imx214.yaml F: drivers/media/i2c/imx214.c SONY IMX219 SENSOR DRIVER -- cgit v1.2.3 From 898bd5b5a4c526d8e310c398ec13b41c1b805f59 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Thu, 10 Sep 2020 18:20:53 +0200 Subject: media: dt-bindings: media: ov772x: Convert to json-schema Convert the ov772x binding document to json-schema and update the MAINTAINERS file accordingly. Reviewed-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/ov772x.txt | 40 ------------ .../devicetree/bindings/media/i2c/ovti,ov772x.yaml | 74 ++++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 75 insertions(+), 41 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/ov772x.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/ov772x.txt b/Documentation/devicetree/bindings/media/i2c/ov772x.txt deleted file mode 100644 index 0b3ede5b8e6a..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/ov772x.txt +++ /dev/null @@ -1,40 +0,0 @@ -* Omnivision OV7720/OV7725 CMOS sensor - -The Omnivision OV7720/OV7725 sensor supports multiple resolutions output, -such as VGA, QVGA, and any size scaling down from CIF to 40x30. It also can -support the YUV422, RGB565/555/444, GRB422 or raw RGB output formats. - -Required Properties: -- compatible: shall be one of - "ovti,ov7720" - "ovti,ov7725" -- clocks: reference to the xclk input clock. - -Optional Properties: -- reset-gpios: reference to the GPIO connected to the RSTB pin which is - active low, if any. -- powerdown-gpios: reference to the GPIO connected to the PWDN pin which is - active high, if any. - -The device node shall contain one 'port' child node with one child 'endpoint' -subnode for its digital output video port, in accordance with the video -interface bindings defined in Documentation/devicetree/bindings/media/ -video-interfaces.txt. - -Example: - -&i2c0 { - ov772x: camera@21 { - compatible = "ovti,ov7725"; - reg = <0x21>; - reset-gpios = <&axi_gpio_0 0 GPIO_ACTIVE_LOW>; - powerdown-gpios = <&axi_gpio_0 1 GPIO_ACTIVE_LOW>; - clocks = <&xclk>; - - port { - ov772x_0: endpoint { - remote-endpoint = <&vcap1_in0>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml new file mode 100644 index 000000000000..e7e2d31fcc23 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,ov772x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Omnivision OV7720/OV7725 CMOS sensor + +maintainers: + - Jacopo Mondi + +description: | + The Omnivision OV7720/OV7725 sensor supports multiple resolutions output, + such as VGA, QVGA, and any size scaling down from CIF to 40x30. It also can + support the YUV422, RGB565/555/444, GRB422 or raw RGB output formats. + +properties: + compatible: + enum: + - ovti,ov7720 + - ovti,ov7725 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + reset-gpios: + description: | + Reference to the GPIO connected to the RSTB pin which is active low. + maxItems: 1 + + powerdown-gpios: + description: | + Reference to the GPIO connected to the PWDN pin which is active high. + maxItems: 1 + + port: + type: object + description: | + Video output port. See ../video-interfaces.txt. + +required: + - compatible + - reg + - clocks + - port + +additionalProperties: false + +examples: + - | + #include + + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + ov772x: camera@21 { + compatible = "ovti,ov7725"; + reg = <0x21>; + reset-gpios = <&axi_gpio_0 0 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&axi_gpio_0 1 GPIO_ACTIVE_LOW>; + clocks = <&xclk>; + + port { + ov772x_0: endpoint { + remote-endpoint = <&vcap1_in0>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 0717a87c1b41..c6a935e03003 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12958,7 +12958,7 @@ M: Jacopo Mondi L: linux-media@vger.kernel.org S: Odd fixes T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/ov772x.txt +F: Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml F: drivers/media/i2c/ov772x.c F: include/media/i2c/ov772x.h -- cgit v1.2.3 From d7dc892dd46d8d5c733b39c6631a7f616cc95d94 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 23 Sep 2020 10:21:12 +0200 Subject: media: dt-bindings: convert CODA VPU bindings to yaml Convert to YAML and add generic IP core compatibles "cnm,codadx6", "cnm,codahx4", "cnm,coda7541", and "cnm,coda960" in addition to the SoC specific compatibles. The new generic compatibles are already used in the SoC device trees and replace the free form comments. For example: - compatible : should be "fsl,-src" for i.MX SoCs: (a) "fsl,imx27-vpu" for CodaDx6 present in i.MX27 turns into: properties: compatible: oneOf: - items: - const: fsl,imx27-vpu - const: cnm,codadx6 This allows to properly specify the secondary JPEG unit interrupt that is only present on cnm,coda960. Also add the missing "fsl,imx6dl-vpu", "cnm,coda960" compatible. The AXI bus connection to the internal SRAM is different between i.MX6Q and i.MX6DL, which requires the driver to load a different firmware depending on the SoC. Further, specify the power-domain property for i.MX6 and change the clock order from "ahb", "per" to "per", "ahb". This order is currently used in all SoC device trees. Signed-off-by: Philipp Zabel Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/coda.txt | 31 ------- Documentation/devicetree/bindings/media/coda.yaml | 108 ++++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 109 insertions(+), 32 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/coda.txt create mode 100644 Documentation/devicetree/bindings/media/coda.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/coda.txt b/Documentation/devicetree/bindings/media/coda.txt deleted file mode 100644 index 90eb74cc1993..000000000000 --- a/Documentation/devicetree/bindings/media/coda.txt +++ /dev/null @@ -1,31 +0,0 @@ -Chips&Media Coda multi-standard codec IP -======================================== - -Coda codec IPs are present in i.MX SoCs in various versions, -called VPU (Video Processing Unit). - -Required properties: -- compatible : should be "fsl,-src" for i.MX SoCs: - (a) "fsl,imx27-vpu" for CodaDx6 present in i.MX27 - (b) "fsl,imx51-vpu" for CodaHx4 present in i.MX51 - (c) "fsl,imx53-vpu" for CODA7541 present in i.MX53 - (d) "fsl,imx6q-vpu" for CODA960 present in i.MX6q -- reg: should be register base and length as documented in the - SoC reference manual -- interrupts : Should contain the VPU interrupt. For CODA960, - a second interrupt is needed for the MJPEG unit. -- clocks : Should contain the ahb and per clocks, in the order - determined by the clock-names property. -- clock-names : Should be "ahb", "per" -- iram : phandle pointing to the SRAM device node - -Example: - -vpu: vpu@63ff4000 { - compatible = "fsl,imx53-vpu"; - reg = <0x63ff4000 0x1000>; - interrupts = <9>; - clocks = <&clks 63>, <&clks 63>; - clock-names = "ahb", "per"; - iram = <&ocram>; -}; diff --git a/Documentation/devicetree/bindings/media/coda.yaml b/Documentation/devicetree/bindings/media/coda.yaml new file mode 100644 index 000000000000..7bac0057faf7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/coda.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/coda.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Chips&Media Coda multi-standard codec IP + +maintainers: + - Philipp Zabel + +description: |- + Coda codec IPs are present in i.MX SoCs in various versions, + called VPU (Video Processing Unit). + +properties: + compatible: + oneOf: + - items: + - const: fsl,imx27-vpu + - const: cnm,codadx6 + - items: + - const: fsl,imx51-vpu + - const: cnm,codahx4 + - items: + - const: fsl,imx53-vpu + - const: cnm,coda7541 + - items: + - enum: + - fsl,imx6dl-vpu + - fsl,imx6q-vpu + - const: cnm,coda960 + + reg: + maxItems: 1 + + clocks: + items: + - description: PER clock + - description: AHB interface clock + + clock-names: + items: + - const: per + - const: ahb + + resets: + maxItems: 1 + + iram: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle pointing to the SRAM device node + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +allOf: + - if: + properties: + compatible: + contains: + const: cnm,coda960 + then: + properties: + interrupts: + items: + - description: BIT processor interrupt + - description: JPEG unit interrupt + + interrupt-names: + items: + - const: bit + - const: jpeg + else: + properties: + interrupts: + items: + - description: BIT processor interrupt + + - if: + properties: + compatible: + contains: + enum: + - fsl,imx6dl-vpu + - fsl,imx6q-vpu + then: + properties: + power-domains: + $ref: /schemas/types.yaml#/definitions/phandle + description: phandle pointing to the PU power domain + maxItems: 1 + +examples: + - | + vpu: video-codec@63ff4000 { + compatible = "fsl,imx53-vpu", "cnm,coda7541"; + reg = <0x63ff4000 0x1000>; + interrupts = <9>; + clocks = <&clks 63>, <&clks 63>; + clock-names = "per", "ahb"; + iram = <&ocram>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index c6a935e03003..43fb0a939fea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4354,7 +4354,7 @@ CODA V4L2 MEM2MEM DRIVER M: Philipp Zabel L: linux-media@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/media/coda.txt +F: Documentation/devicetree/bindings/media/coda.yaml F: drivers/media/platform/coda/ CODE OF CONDUCT -- cgit v1.2.3 From 5b3ff3be485ec29180368e9a2d61bf6d3dfaf7e6 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Tue, 15 Sep 2020 20:19:44 +0200 Subject: media: MAINTAINERS: Add ADV7604 bindings documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the YAML dt-bindings document for ADV7604. Signed-off-by: Niklas Söderlund Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 43fb0a939fea..811db1d3ca33 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1073,6 +1073,7 @@ M: Hans Verkuil L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/adv7604* +F: Documentation/devicetree/bindings/media/i2c/adv7604.yaml ANALOG DEVICES INC ADV7842 DRIVER M: Hans Verkuil -- cgit v1.2.3 From e6938cc1cb7763a363f62b78147f1f2fb972f49c Mon Sep 17 00:00:00 2001 From: Helen Koike Date: Fri, 6 Nov 2020 13:19:37 +0100 Subject: media: rockchip: rkisp1: destage Rockchip ISP1 driver All the items in the TODO list were addressed, uapi was reviewed, documentation written, checkpatch errors fixed, several bugs fixed. There is no big reason to keep this driver in staging, so move it out. Dt-bindings Verified with: make ARCH=arm64 dt_binding_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/media/rockchip-isp1.yaml Fields of MAINTAINERS file sorted according to output of ./scripts/parse-maintainers.pl --input=MAINTAINERS --output=MAINTAINERS --order [dt-bindings: media: rkisp1: move rockchip-isp1 bindings out of staging] [dt-bindings: media: rkisp1: move rockchip-isp1 bindings out of staging] [hverkuil: fix various checkpatch alignment warnings] Signed-off-by: Helen Koike Acked-by: Rob Herring Reviewed-by: Tomasz Figa Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/rockchip-isp1.yaml | 215 +++ .../userspace-api/media/v4l/pixfmt-meta-rkisp1.rst | 2 +- MAINTAINERS | 5 +- drivers/media/platform/Kconfig | 18 + drivers/media/platform/Makefile | 1 + drivers/media/platform/rockchip/rkisp1/Makefile | 10 + .../platform/rockchip/rkisp1/rkisp1-capture.c | 1431 ++++++++++++++++++ .../media/platform/rockchip/rkisp1/rkisp1-common.c | 37 + .../media/platform/rockchip/rkisp1/rkisp1-common.h | 485 ++++++ .../media/platform/rockchip/rkisp1/rkisp1-dev.c | 581 ++++++++ .../media/platform/rockchip/rkisp1/rkisp1-isp.c | 1160 +++++++++++++++ .../media/platform/rockchip/rkisp1/rkisp1-params.c | 1572 ++++++++++++++++++++ .../media/platform/rockchip/rkisp1/rkisp1-regs.h | 1262 ++++++++++++++++ .../platform/rockchip/rkisp1/rkisp1-resizer.c | 846 +++++++++++ .../media/platform/rockchip/rkisp1/rkisp1-stats.c | 415 ++++++ drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - .../devicetree/bindings/media/rockchip-isp1.yaml | 215 --- drivers/staging/media/rkisp1/Kconfig | 19 - drivers/staging/media/rkisp1/Makefile | 10 - drivers/staging/media/rkisp1/TODO | 8 - drivers/staging/media/rkisp1/rkisp1-capture.c | 1431 ------------------ drivers/staging/media/rkisp1/rkisp1-common.c | 37 - drivers/staging/media/rkisp1/rkisp1-common.h | 485 ------ drivers/staging/media/rkisp1/rkisp1-dev.c | 580 -------- drivers/staging/media/rkisp1/rkisp1-isp.c | 1161 --------------- drivers/staging/media/rkisp1/rkisp1-params.c | 1572 -------------------- drivers/staging/media/rkisp1/rkisp1-regs.h | 1262 ---------------- drivers/staging/media/rkisp1/rkisp1-resizer.c | 846 ----------- drivers/staging/media/rkisp1/rkisp1-stats.c | 415 ------ drivers/staging/media/rkisp1/uapi/rkisp1-config.h | 884 ----------- include/uapi/linux/rkisp1-config.h | 884 +++++++++++ 32 files changed, 8922 insertions(+), 8930 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/rockchip-isp1.yaml create mode 100644 drivers/media/platform/rockchip/rkisp1/Makefile create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-common.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-common.h create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-params.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c create mode 100644 drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c delete mode 100644 drivers/staging/media/rkisp1/Documentation/devicetree/bindings/media/rockchip-isp1.yaml delete mode 100644 drivers/staging/media/rkisp1/Kconfig delete mode 100644 drivers/staging/media/rkisp1/Makefile delete mode 100644 drivers/staging/media/rkisp1/TODO delete mode 100644 drivers/staging/media/rkisp1/rkisp1-capture.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-common.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-common.h delete mode 100644 drivers/staging/media/rkisp1/rkisp1-dev.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-isp.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-params.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-regs.h delete mode 100644 drivers/staging/media/rkisp1/rkisp1-resizer.c delete mode 100644 drivers/staging/media/rkisp1/rkisp1-stats.c delete mode 100644 drivers/staging/media/rkisp1/uapi/rkisp1-config.h create mode 100644 include/uapi/linux/rkisp1-config.h (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/rockchip-isp1.yaml b/Documentation/devicetree/bindings/media/rockchip-isp1.yaml new file mode 100644 index 000000000000..2004c054ed1a --- /dev/null +++ b/Documentation/devicetree/bindings/media/rockchip-isp1.yaml @@ -0,0 +1,215 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR MIT) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/rockchip-isp1.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip SoC Image Signal Processing unit v1 + +maintainers: + - Helen Koike + +description: | + Rockchip ISP1 is the Camera interface for the Rockchip series of SoCs + which contains image processing, scaling, and compression functions. + +properties: + compatible: + const: rockchip,rk3399-cif-isp + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 3 + items: + # isp0 and isp1 + - description: ISP clock + - description: ISP AXI clock + - description: ISP AHB clock + # only for isp1 + - description: ISP Pixel clock + + clock-names: + minItems: 3 + items: + # isp0 and isp1 + - const: isp + - const: aclk + - const: hclk + # only for isp1 + - const: pclk_isp + + iommus: + maxItems: 1 + + phys: + maxItems: 1 + description: phandle for the PHY port + + phy-names: + const: dphy + + power-domains: + maxItems: 1 + + # See ./video-interfaces.txt for details + ports: + type: object + additionalProperties: false + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + port@0: + type: object + description: connection point for sensors at MIPI-DPHY RX0 + additionalProperties: false + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + const: 0 + + patternProperties: + endpoint: + type: object + additionalProperties: false + + properties: + reg: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + remote-endpoint: true + + required: + - reg + - "#address-cells" + - "#size-cells" + + required: + - "#address-cells" + - "#size-cells" + - port@0 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - iommus + - phys + - phy-names + - power-domains + - ports + +if: + properties: + compatible: + contains: + const: rockchip,rk3399-cif-isp +then: + properties: + clocks: + minItems: 3 + maxItems: 4 + clock-names: + minItems: 3 + maxItems: 4 + +additionalProperties: false + +examples: + - | + + #include + #include + #include + + parent0: parent { + #address-cells = <2>; + #size-cells = <2>; + + isp0: isp0@ff910000 { + compatible = "rockchip,rk3399-cif-isp"; + reg = <0x0 0xff910000 0x0 0x4000>; + interrupts = ; + clocks = <&cru SCLK_ISP0>, + <&cru ACLK_ISP0_WRAPPER>, + <&cru HCLK_ISP0_WRAPPER>; + clock-names = "isp", "aclk", "hclk"; + iommus = <&isp0_mmu>; + phys = <&dphy>; + phy-names = "dphy"; + power-domains = <&power RK3399_PD_ISP0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + mipi_in_wcam: endpoint@0 { + reg = <0>; + remote-endpoint = <&wcam_out>; + data-lanes = <1 2>; + }; + + mipi_in_ucam: endpoint@1 { + reg = <1>; + remote-endpoint = <&ucam_out>; + data-lanes = <1>; + }; + }; + }; + }; + + i2c7: i2c { + #address-cells = <1>; + #size-cells = <0>; + + wcam: camera@36 { + compatible = "ovti,ov5695"; + reg = <0x36>; + + port { + wcam_out: endpoint { + remote-endpoint = <&mipi_in_wcam>; + data-lanes = <1 2>; + }; + }; + }; + + ucam: camera@3c { + compatible = "ovti,ov2685"; + reg = <0x3c>; + + port { + ucam_out: endpoint { + remote-endpoint = <&mipi_in_ucam>; + data-lanes = <1>; + }; + }; + }; + }; + }; diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst b/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst index 7e43837ed260..f3671472d410 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst @@ -46,4 +46,4 @@ important tuning tools using software control loop. rkisp1 uAPI data types ====================== -.. kernel-doc:: drivers/staging/media/rkisp1/uapi/rkisp1-config.h +.. kernel-doc:: include/uapi/linux/rkisp1-config.h diff --git a/MAINTAINERS b/MAINTAINERS index 811db1d3ca33..352b8eaa21f7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15034,10 +15034,13 @@ ROCKCHIP ISP V1 DRIVER M: Helen Koike M: Dafna Hirschfeld L: linux-media@vger.kernel.org +L: linux-rockchip@lists.infradead.org S: Maintained F: Documentation/admin-guide/media/rkisp1.rst +F: Documentation/devicetree/bindings/media/rockchip-isp1.yaml F: Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst -F: drivers/staging/media/rkisp1/ +F: drivers/media/platform/rockchip/rkisp1 +F: include/uapi/linux/rkisp1-config.h ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER M: Jacob Chen diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index a3cb104956d5..b161f2ba238f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -147,6 +147,24 @@ config VIDEO_RENESAS_CEU help This is a v4l2 driver for the Renesas CEU Interface +config VIDEO_ROCKCHIP_ISP1 + tristate "Rockchip Image Signal Processing v1 Unit driver" + depends on VIDEO_V4L2 && OF + depends on ARCH_ROCKCHIP || COMPILE_TEST + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select VIDEOBUF2_DMA_CONTIG + select VIDEOBUF2_VMALLOC + select V4L2_FWNODE + select GENERIC_PHY_MIPI_DPHY + default n + help + Enable this to support the Image Signal Processing (ISP) module + present in RK3399 SoCs. + + To compile this driver as a module, choose M here: the module + will be called rockchip-isp1. + source "drivers/media/platform/exynos4-is/Kconfig" source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 62b6cdc8c730..b342714228db 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip/rkisp1/ obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/ obj-y += omap/ diff --git a/drivers/media/platform/rockchip/rkisp1/Makefile b/drivers/media/platform/rockchip/rkisp1/Makefile new file mode 100644 index 000000000000..ab32a77db8f7 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip-isp1.o +rockchip-isp1-objs += rkisp1-capture.o \ + rkisp1-common.o \ + rkisp1-dev.o \ + rkisp1-isp.o \ + rkisp1-resizer.o \ + rkisp1-stats.o \ + rkisp1-params.o diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c new file mode 100644 index 000000000000..b81235afd053 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c @@ -0,0 +1,1431 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - V4l capture device + * + * Copyright (C) 2019 Collabora, Ltd. + * + * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rkisp1-common.h" + +/* + * NOTE: There are two capture video devices in rkisp1, selfpath and mainpath. + * + * differences between selfpath and mainpath + * available mp sink input: isp + * available sp sink input : isp, dma(TODO) + * available mp sink pad fmts: yuv422, raw + * available sp sink pad fmts: yuv422, yuv420...... + * available mp source fmts: yuv, raw, jpeg(TODO) + * available sp source fmts: yuv, rgb + */ + +#define RKISP1_SP_DEV_NAME RKISP1_DRIVER_NAME "_selfpath" +#define RKISP1_MP_DEV_NAME RKISP1_DRIVER_NAME "_mainpath" + +#define RKISP1_MIN_BUFFERS_NEEDED 3 + +enum rkisp1_plane { + RKISP1_PLANE_Y = 0, + RKISP1_PLANE_CB = 1, + RKISP1_PLANE_CR = 2 +}; + +/* + * @fourcc: pixel format + * @fmt_type: helper filed for pixel format + * @uv_swap: if cb cr swaped, for yuv + * @write_format: defines how YCbCr self picture data is written to memory + * @output_format: defines sp output format + * @mbus: the mbus code on the src resizer pad that matches the pixel format + */ +struct rkisp1_capture_fmt_cfg { + u32 fourcc; + u8 uv_swap; + u32 write_format; + u32 output_format; + u32 mbus; +}; + +struct rkisp1_capture_ops { + void (*config)(struct rkisp1_capture *cap); + void (*stop)(struct rkisp1_capture *cap); + void (*enable)(struct rkisp1_capture *cap); + void (*disable)(struct rkisp1_capture *cap); + void (*set_data_path)(struct rkisp1_capture *cap); + bool (*is_stopped)(struct rkisp1_capture *cap); +}; + +struct rkisp1_capture_config { + const struct rkisp1_capture_fmt_cfg *fmts; + int fmt_size; + struct { + u32 y_size_init; + u32 cb_size_init; + u32 cr_size_init; + u32 y_base_ad_init; + u32 cb_base_ad_init; + u32 cr_base_ad_init; + u32 y_offs_cnt_init; + u32 cb_offs_cnt_init; + u32 cr_offs_cnt_init; + } mi; +}; + +/* + * The supported pixel formats for mainpath. NOTE, pixel formats with identical 'mbus' + * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes + */ +static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = { + /* yuv422 */ + { + .fourcc = V4L2_PIX_FMT_YUYV, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_YUV422P, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_YVU422M, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, + /* yuv400 */ + { + .fourcc = V4L2_PIX_FMT_GREY, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, + /* yuv420 */ + { + .fourcc = V4L2_PIX_FMT_NV21, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV21M, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV12M, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_YUV420, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_YVU420, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, + /* raw */ + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_SRGGB8_1X8, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_SGRBG8_1X8, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_SGBRG8_1X8, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, + .mbus = MEDIA_BUS_FMT_SBGGR8_1X8, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SRGGB10_1X10, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SGRBG10_1X10, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SGBRG10_1X10, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SBGGR10_1X10, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SRGGB12_1X12, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SGRBG12_1X12, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SGBRG12_1X12, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, + .mbus = MEDIA_BUS_FMT_SBGGR12_1X12, + }, +}; + +/* + * The supported pixel formats for selfpath. NOTE, pixel formats with identical 'mbus' + * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes + */ +static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = { + /* yuv422 */ + { + .fourcc = V4L2_PIX_FMT_YUYV, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_INT, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_YUV422P, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_YVU422M, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, + /* yuv400 */ + { + .fourcc = V4L2_PIX_FMT_GREY, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV400, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, + /* rgb */ + { + .fourcc = V4L2_PIX_FMT_XBGR32, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565, + .mbus = MEDIA_BUS_FMT_YUYV8_2X8, + }, + /* yuv420 */ + { + .fourcc = V4L2_PIX_FMT_NV21, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV21M, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_NV12M, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_YUV420, + .uv_swap = 0, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, { + .fourcc = V4L2_PIX_FMT_YVU420, + .uv_swap = 1, + .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, + .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, + .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, + }, +}; + +static const struct rkisp1_capture_config rkisp1_capture_config_mp = { + .fmts = rkisp1_mp_fmts, + .fmt_size = ARRAY_SIZE(rkisp1_mp_fmts), + .mi = { + .y_size_init = RKISP1_CIF_MI_MP_Y_SIZE_INIT, + .cb_size_init = RKISP1_CIF_MI_MP_CB_SIZE_INIT, + .cr_size_init = RKISP1_CIF_MI_MP_CR_SIZE_INIT, + .y_base_ad_init = RKISP1_CIF_MI_MP_Y_BASE_AD_INIT, + .cb_base_ad_init = RKISP1_CIF_MI_MP_CB_BASE_AD_INIT, + .cr_base_ad_init = RKISP1_CIF_MI_MP_CR_BASE_AD_INIT, + .y_offs_cnt_init = RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT, + .cb_offs_cnt_init = RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT, + .cr_offs_cnt_init = RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT, + }, +}; + +static const struct rkisp1_capture_config rkisp1_capture_config_sp = { + .fmts = rkisp1_sp_fmts, + .fmt_size = ARRAY_SIZE(rkisp1_sp_fmts), + .mi = { + .y_size_init = RKISP1_CIF_MI_SP_Y_SIZE_INIT, + .cb_size_init = RKISP1_CIF_MI_SP_CB_SIZE_INIT, + .cr_size_init = RKISP1_CIF_MI_SP_CR_SIZE_INIT, + .y_base_ad_init = RKISP1_CIF_MI_SP_Y_BASE_AD_INIT, + .cb_base_ad_init = RKISP1_CIF_MI_SP_CB_BASE_AD_INIT, + .cr_base_ad_init = RKISP1_CIF_MI_SP_CR_BASE_AD_INIT, + .y_offs_cnt_init = RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT, + .cb_offs_cnt_init = RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT, + .cr_offs_cnt_init = RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT, + }, +}; + +static inline struct rkisp1_vdev_node * +rkisp1_vdev_to_node(struct video_device *vdev) +{ + return container_of(vdev, struct rkisp1_vdev_node, vdev); +} + +int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, + struct v4l2_subdev_mbus_code_enum *code) +{ + const struct rkisp1_capture_fmt_cfg *fmts = cap->config->fmts; + /* + * initialize curr_mbus to non existing mbus code 0 to ensure it is + * different from fmts[0].mbus + */ + u32 curr_mbus = 0; + int i, n = 0; + + for (i = 0; i < cap->config->fmt_size; i++) { + if (fmts[i].mbus == curr_mbus) + continue; + + curr_mbus = fmts[i].mbus; + if (n++ == code->index) { + code->code = curr_mbus; + return 0; + } + } + return -EINVAL; +} + +/* ---------------------------------------------------------------------------- + * Stream operations for self-picture path (sp) and main-picture path (mp) + */ + +static void rkisp1_mi_config_ctrl(struct rkisp1_capture *cap) +{ + u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); + + mi_ctrl &= ~GENMASK(17, 16); + mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64; + + mi_ctrl &= ~GENMASK(19, 18); + mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64; + + mi_ctrl |= RKISP1_CIF_MI_CTRL_INIT_BASE_EN | + RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN; + + rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static u32 rkisp1_pixfmt_comp_size(const struct v4l2_pix_format_mplane *pixm, + unsigned int component) +{ + /* + * If packed format, then plane_fmt[0].sizeimage is the sum of all + * components, so we need to calculate just the size of Y component. + * See rkisp1_fill_pixfmt(). + */ + if (!component && pixm->num_planes == 1) + return pixm->plane_fmt[0].bytesperline * pixm->height; + return pixm->plane_fmt[component].sizeimage; +} + +static void rkisp1_irq_frame_end_enable(struct rkisp1_capture *cap) +{ + u32 mi_imsc = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_IMSC); + + mi_imsc |= RKISP1_CIF_MI_FRAME(cap); + rkisp1_write(cap->rkisp1, mi_imsc, RKISP1_CIF_MI_IMSC); +} + +static void rkisp1_mp_config(struct rkisp1_capture *cap) +{ + const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; + struct rkisp1_device *rkisp1 = cap->rkisp1; + u32 reg; + + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), + cap->config->mi.y_size_init); + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), + cap->config->mi.cb_size_init); + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), + cap->config->mi.cr_size_init); + + rkisp1_irq_frame_end_enable(cap); + + /* set uv swapping for semiplanar formats */ + if (cap->pix.info->comp_planes == 2) { + reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); + if (cap->pix.cfg->uv_swap) + reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; + else + reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; + rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); + } + + rkisp1_mi_config_ctrl(cap); + + reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); + reg &= ~RKISP1_MI_CTRL_MP_FMT_MASK; + reg |= cap->pix.cfg->write_format; + rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); + + reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); + reg |= RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE; + rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_sp_config(struct rkisp1_capture *cap) +{ + const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; + struct rkisp1_device *rkisp1 = cap->rkisp1; + u32 mi_ctrl, reg; + + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), + cap->config->mi.y_size_init); + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), + cap->config->mi.cb_size_init); + rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), + cap->config->mi.cr_size_init); + + rkisp1_write(rkisp1, pixm->width, RKISP1_CIF_MI_SP_Y_PIC_WIDTH); + rkisp1_write(rkisp1, pixm->height, RKISP1_CIF_MI_SP_Y_PIC_HEIGHT); + rkisp1_write(rkisp1, cap->sp_y_stride, RKISP1_CIF_MI_SP_Y_LLENGTH); + + rkisp1_irq_frame_end_enable(cap); + + /* set uv swapping for semiplanar formats */ + if (cap->pix.info->comp_planes == 2) { + reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); + if (cap->pix.cfg->uv_swap) + reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; + else + reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; + rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); + } + + rkisp1_mi_config_ctrl(cap); + + mi_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); + mi_ctrl &= ~RKISP1_MI_CTRL_SP_FMT_MASK; + mi_ctrl |= cap->pix.cfg->write_format | + RKISP1_MI_CTRL_SP_INPUT_YUV422 | + cap->pix.cfg->output_format | + RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE; + rkisp1_write(rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_mp_disable(struct rkisp1_capture *cap) +{ + u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); + + mi_ctrl &= ~(RKISP1_CIF_MI_CTRL_MP_ENABLE | + RKISP1_CIF_MI_CTRL_RAW_ENABLE); + rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_sp_disable(struct rkisp1_capture *cap) +{ + u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); + + mi_ctrl &= ~RKISP1_CIF_MI_CTRL_SP_ENABLE; + rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_mp_enable(struct rkisp1_capture *cap) +{ + u32 mi_ctrl; + + rkisp1_mp_disable(cap); + + mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); + if (v4l2_is_format_bayer(cap->pix.info)) + mi_ctrl |= RKISP1_CIF_MI_CTRL_RAW_ENABLE; + /* YUV */ + else + mi_ctrl |= RKISP1_CIF_MI_CTRL_MP_ENABLE; + + rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_sp_enable(struct rkisp1_capture *cap) +{ + u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); + + mi_ctrl |= RKISP1_CIF_MI_CTRL_SP_ENABLE; + rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); +} + +static void rkisp1_mp_sp_stop(struct rkisp1_capture *cap) +{ + if (!cap->is_streaming) + return; + rkisp1_write(cap->rkisp1, + RKISP1_CIF_MI_FRAME(cap), RKISP1_CIF_MI_ICR); + cap->ops->disable(cap); +} + +static bool rkisp1_mp_is_stopped(struct rkisp1_capture *cap) +{ + u32 en = RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED | + RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED; + + return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & en); +} + +static bool rkisp1_sp_is_stopped(struct rkisp1_capture *cap) +{ + return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & + RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED); +} + +static void rkisp1_mp_set_data_path(struct rkisp1_capture *cap) +{ + u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); + + dpcl = dpcl | RKISP1_CIF_VI_DPCL_CHAN_MODE_MP | + RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI; + rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); +} + +static void rkisp1_sp_set_data_path(struct rkisp1_capture *cap) +{ + u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); + + dpcl |= RKISP1_CIF_VI_DPCL_CHAN_MODE_SP; + rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); +} + +static struct rkisp1_capture_ops rkisp1_capture_ops_mp = { + .config = rkisp1_mp_config, + .enable = rkisp1_mp_enable, + .disable = rkisp1_mp_disable, + .stop = rkisp1_mp_sp_stop, + .set_data_path = rkisp1_mp_set_data_path, + .is_stopped = rkisp1_mp_is_stopped, +}; + +static struct rkisp1_capture_ops rkisp1_capture_ops_sp = { + .config = rkisp1_sp_config, + .enable = rkisp1_sp_enable, + .disable = rkisp1_sp_disable, + .stop = rkisp1_mp_sp_stop, + .set_data_path = rkisp1_sp_set_data_path, + .is_stopped = rkisp1_sp_is_stopped, +}; + +/* ---------------------------------------------------------------------------- + * Frame buffer operations + */ + +static int rkisp1_dummy_buf_create(struct rkisp1_capture *cap) +{ + const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; + struct rkisp1_dummy_buffer *dummy_buf = &cap->buf.dummy; + + dummy_buf->size = max3(rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), + rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), + rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); + + /* The driver never access vaddr, no mapping is required */ + dummy_buf->vaddr = dma_alloc_attrs(cap->rkisp1->dev, + dummy_buf->size, + &dummy_buf->dma_addr, + GFP_KERNEL, + DMA_ATTR_NO_KERNEL_MAPPING); + if (!dummy_buf->vaddr) + return -ENOMEM; + + return 0; +} + +static void rkisp1_dummy_buf_destroy(struct rkisp1_capture *cap) +{ + dma_free_attrs(cap->rkisp1->dev, + cap->buf.dummy.size, cap->buf.dummy.vaddr, + cap->buf.dummy.dma_addr, DMA_ATTR_NO_KERNEL_MAPPING); +} + +static void rkisp1_set_next_buf(struct rkisp1_capture *cap) +{ + cap->buf.curr = cap->buf.next; + cap->buf.next = NULL; + + if (!list_empty(&cap->buf.queue)) { + u32 *buff_addr; + + cap->buf.next = list_first_entry(&cap->buf.queue, struct rkisp1_buffer, queue); + list_del(&cap->buf.next->queue); + + buff_addr = cap->buf.next->buff_addr; + + rkisp1_write(cap->rkisp1, + buff_addr[RKISP1_PLANE_Y], + cap->config->mi.y_base_ad_init); + rkisp1_write(cap->rkisp1, + buff_addr[RKISP1_PLANE_CB], + cap->config->mi.cb_base_ad_init); + rkisp1_write(cap->rkisp1, + buff_addr[RKISP1_PLANE_CR], + cap->config->mi.cr_base_ad_init); + } else { + /* + * Use the dummy space allocated by dma_alloc_coherent to + * throw data if there is no available buffer. + */ + rkisp1_write(cap->rkisp1, + cap->buf.dummy.dma_addr, + cap->config->mi.y_base_ad_init); + rkisp1_write(cap->rkisp1, + cap->buf.dummy.dma_addr, + cap->config->mi.cb_base_ad_init); + rkisp1_write(cap->rkisp1, + cap->buf.dummy.dma_addr, + cap->config->mi.cr_base_ad_init); + } + + /* Set plane offsets */ + rkisp1_write(cap->rkisp1, 0, cap->config->mi.y_offs_cnt_init); + rkisp1_write(cap->rkisp1, 0, cap->config->mi.cb_offs_cnt_init); + rkisp1_write(cap->rkisp1, 0, cap->config->mi.cr_offs_cnt_init); +} + +/* + * This function is called when a frame end comes. The next frame + * is processing and we should set up buffer for next-next frame, + * otherwise it will overflow. + */ +static void rkisp1_handle_buffer(struct rkisp1_capture *cap) +{ + struct rkisp1_isp *isp = &cap->rkisp1->isp; + struct rkisp1_buffer *curr_buf; + + spin_lock(&cap->buf.lock); + curr_buf = cap->buf.curr; + + if (curr_buf) { + curr_buf->vb.sequence = isp->frame_sequence; + curr_buf->vb.vb2_buf.timestamp = ktime_get_boottime_ns(); + curr_buf->vb.field = V4L2_FIELD_NONE; + vb2_buffer_done(&curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } else { + cap->rkisp1->debug.frame_drop[cap->id]++; + } + + rkisp1_set_next_buf(cap); + spin_unlock(&cap->buf.lock); +} + +void rkisp1_capture_isr(struct rkisp1_device *rkisp1) +{ + unsigned int i; + u32 status; + + status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS); + rkisp1_write(rkisp1, status, RKISP1_CIF_MI_ICR); + + for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) { + struct rkisp1_capture *cap = &rkisp1->capture_devs[i]; + + if (!(status & RKISP1_CIF_MI_FRAME(cap))) + continue; + if (!cap->is_stopping) { + rkisp1_handle_buffer(cap); + continue; + } + /* + * Make sure stream is actually stopped, whose state + * can be read from the shadow register, before + * wake_up() thread which would immediately free all + * frame buffers. stop() takes effect at the next + * frame end that sync the configurations to shadow + * regs. + */ + if (!cap->ops->is_stopped(cap)) { + cap->ops->stop(cap); + continue; + } + cap->is_stopping = false; + cap->is_streaming = false; + wake_up(&cap->done); + } +} + +/* ---------------------------------------------------------------------------- + * Vb2 operations + */ + +static int rkisp1_vb2_queue_setup(struct vb2_queue *queue, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + struct rkisp1_capture *cap = queue->drv_priv; + const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; + unsigned int i; + + if (*num_planes) { + if (*num_planes != pixm->num_planes) + return -EINVAL; + + for (i = 0; i < pixm->num_planes; i++) + if (sizes[i] < pixm->plane_fmt[i].sizeimage) + return -EINVAL; + } else { + *num_planes = pixm->num_planes; + for (i = 0; i < pixm->num_planes; i++) + sizes[i] = pixm->plane_fmt[i].sizeimage; + } + + return 0; +} + +static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_buffer *ispbuf = + container_of(vbuf, struct rkisp1_buffer, vb); + struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; + const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; + unsigned int i; + + memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr)); + for (i = 0; i < pixm->num_planes; i++) + ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); + + /* Convert to non-MPLANE */ + if (pixm->num_planes == 1) { + ispbuf->buff_addr[RKISP1_PLANE_CB] = + ispbuf->buff_addr[RKISP1_PLANE_Y] + + rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y); + ispbuf->buff_addr[RKISP1_PLANE_CR] = + ispbuf->buff_addr[RKISP1_PLANE_CB] + + rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB); + } + + /* + * uv swap can be supported for planar formats by switching + * the address of cb and cr + */ + if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap) + swap(ispbuf->buff_addr[RKISP1_PLANE_CR], + ispbuf->buff_addr[RKISP1_PLANE_CB]); + + spin_lock_irq(&cap->buf.lock); + list_add_tail(&ispbuf->queue, &cap->buf.queue); + spin_unlock_irq(&cap->buf.lock); +} + +static int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb) +{ + struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; + unsigned int i; + + for (i = 0; i < cap->pix.fmt.num_planes; i++) { + unsigned long size = cap->pix.fmt.plane_fmt[i].sizeimage; + + if (vb2_plane_size(vb, i) < size) { + dev_err(cap->rkisp1->dev, + "User buffer too small (%ld < %ld)\n", + vb2_plane_size(vb, i), size); + return -EINVAL; + } + vb2_set_plane_payload(vb, i, size); + } + + return 0; +} + +static void rkisp1_return_all_buffers(struct rkisp1_capture *cap, + enum vb2_buffer_state state) +{ + struct rkisp1_buffer *buf; + + spin_lock_irq(&cap->buf.lock); + if (cap->buf.curr) { + vb2_buffer_done(&cap->buf.curr->vb.vb2_buf, state); + cap->buf.curr = NULL; + } + if (cap->buf.next) { + vb2_buffer_done(&cap->buf.next->vb.vb2_buf, state); + cap->buf.next = NULL; + } + while (!list_empty(&cap->buf.queue)) { + buf = list_first_entry(&cap->buf.queue, + struct rkisp1_buffer, queue); + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } + spin_unlock_irq(&cap->buf.lock); +} + +/* + * Most of registers inside rockchip ISP1 have shadow register since + * they must be not be changed during processing a frame. + * Usually, each sub-module updates its shadow register after + * processing the last pixel of a frame. + */ +static void rkisp1_cap_stream_enable(struct rkisp1_capture *cap) +{ + struct rkisp1_device *rkisp1 = cap->rkisp1; + struct rkisp1_capture *other = &rkisp1->capture_devs[cap->id ^ 1]; + + cap->ops->set_data_path(cap); + cap->ops->config(cap); + + /* Setup a buffer for the next frame */ + spin_lock_irq(&cap->buf.lock); + rkisp1_set_next_buf(cap); + cap->ops->enable(cap); + /* It's safe to config ACTIVE and SHADOW regs for the + * first stream. While when the second is starting, do NOT + * force update because it also update the first one. + * + * The latter case would drop one more buf(that is 2) since + * there's not buf in shadow when the second FE received. This's + * also required because the second FE maybe corrupt especially + * when run at 120fps. + */ + if (!other->is_streaming) { + /* force cfg update */ + rkisp1_write(rkisp1, + RKISP1_CIF_MI_INIT_SOFT_UPD, RKISP1_CIF_MI_INIT); + rkisp1_set_next_buf(cap); + } + spin_unlock_irq(&cap->buf.lock); + cap->is_streaming = true; +} + +static void rkisp1_cap_stream_disable(struct rkisp1_capture *cap) +{ + int ret; + + /* Stream should stop in interrupt. If it dosn't, stop it by force. */ + cap->is_stopping = true; + ret = wait_event_timeout(cap->done, + !cap->is_streaming, + msecs_to_jiffies(1000)); + if (!ret) { + cap->rkisp1->debug.stop_timeout[cap->id]++; + cap->ops->stop(cap); + cap->is_stopping = false; + cap->is_streaming = false; + } +} + +/* + * rkisp1_pipeline_stream_disable - disable nodes in the pipeline + * + * Call s_stream(false) in the reverse order from + * rkisp1_pipeline_stream_enable() and disable the DMA engine. + * Should be called before media_pipeline_stop() + */ +static void rkisp1_pipeline_stream_disable(struct rkisp1_capture *cap) + __must_hold(&cap->rkisp1->stream_lock) +{ + struct rkisp1_device *rkisp1 = cap->rkisp1; + + rkisp1_cap_stream_disable(cap); + + /* + * If the other capture is streaming, isp and sensor nodes shouldn't + * be disabled, skip them. + */ + if (rkisp1->pipe.streaming_count < 2) { + v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, + false); + v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); + } + + v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, + false); +} + +/* + * rkisp1_pipeline_stream_enable - enable nodes in the pipeline + * + * Enable the DMA Engine and call s_stream(true) through the pipeline. + * Should be called after media_pipeline_start() + */ +static int rkisp1_pipeline_stream_enable(struct rkisp1_capture *cap) + __must_hold(&cap->rkisp1->stream_lock) +{ + struct rkisp1_device *rkisp1 = cap->rkisp1; + int ret; + + rkisp1_cap_stream_enable(cap); + + ret = v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, + s_stream, true); + if (ret) + goto err_disable_cap; + + /* + * If the other capture is streaming, isp and sensor nodes are already + * enabled, skip them. + */ + if (rkisp1->pipe.streaming_count > 1) + return 0; + + ret = v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, true); + if (ret) + goto err_disable_rsz; + + ret = v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, + true); + if (ret) + goto err_disable_isp; + + return 0; + +err_disable_isp: + v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); +err_disable_rsz: + v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, + false); +err_disable_cap: + rkisp1_cap_stream_disable(cap); + + return ret; +} + +static void rkisp1_vb2_stop_streaming(struct vb2_queue *queue) +{ + struct rkisp1_capture *cap = queue->drv_priv; + struct rkisp1_vdev_node *node = &cap->vnode; + struct rkisp1_device *rkisp1 = cap->rkisp1; + int ret; + + mutex_lock(&cap->rkisp1->stream_lock); + + rkisp1_pipeline_stream_disable(cap); + + rkisp1_return_all_buffers(cap, VB2_BUF_STATE_ERROR); + + v4l2_pipeline_pm_put(&node->vdev.entity); + ret = pm_runtime_put(rkisp1->dev); + if (ret < 0) + dev_err(rkisp1->dev, "power down failed error:%d\n", ret); + + rkisp1_dummy_buf_destroy(cap); + + media_pipeline_stop(&node->vdev.entity); + + mutex_unlock(&cap->rkisp1->stream_lock); +} + +static int +rkisp1_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) +{ + struct rkisp1_capture *cap = queue->drv_priv; + struct media_entity *entity = &cap->vnode.vdev.entity; + int ret; + + mutex_lock(&cap->rkisp1->stream_lock); + + ret = media_pipeline_start(entity, &cap->rkisp1->pipe); + if (ret) { + dev_err(cap->rkisp1->dev, "start pipeline failed %d\n", ret); + goto err_ret_buffers; + } + + ret = rkisp1_dummy_buf_create(cap); + if (ret) + goto err_pipeline_stop; + + ret = pm_runtime_get_sync(cap->rkisp1->dev); + if (ret < 0) { + pm_runtime_put_noidle(cap->rkisp1->dev); + dev_err(cap->rkisp1->dev, "power up failed %d\n", ret); + goto err_destroy_dummy; + } + ret = v4l2_pipeline_pm_get(entity); + if (ret) { + dev_err(cap->rkisp1->dev, "open cif pipeline failed %d\n", ret); + goto err_pipe_pm_put; + } + + ret = rkisp1_pipeline_stream_enable(cap); + if (ret) + goto err_v4l2_pm_put; + + mutex_unlock(&cap->rkisp1->stream_lock); + + return 0; + +err_v4l2_pm_put: + v4l2_pipeline_pm_put(entity); +err_pipe_pm_put: + pm_runtime_put(cap->rkisp1->dev); +err_destroy_dummy: + rkisp1_dummy_buf_destroy(cap); +err_pipeline_stop: + media_pipeline_stop(entity); +err_ret_buffers: + rkisp1_return_all_buffers(cap, VB2_BUF_STATE_QUEUED); + mutex_unlock(&cap->rkisp1->stream_lock); + + return ret; +} + +static struct vb2_ops rkisp1_vb2_ops = { + .queue_setup = rkisp1_vb2_queue_setup, + .buf_queue = rkisp1_vb2_buf_queue, + .buf_prepare = rkisp1_vb2_buf_prepare, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = rkisp1_vb2_stop_streaming, + .start_streaming = rkisp1_vb2_start_streaming, +}; + +/* ---------------------------------------------------------------------------- + * IOCTLs operations + */ + +static const struct v4l2_format_info * +rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm, + enum rkisp1_stream_id id) +{ + struct v4l2_plane_pix_format *plane_y = &pixm->plane_fmt[0]; + const struct v4l2_format_info *info; + unsigned int i; + u32 stride; + + memset(pixm->plane_fmt, 0, sizeof(pixm->plane_fmt)); + info = v4l2_format_info(pixm->pixelformat); + pixm->num_planes = info->mem_planes; + stride = info->bpp[0] * pixm->width; + /* Self path supports custom stride but Main path doesn't */ + if (id == RKISP1_MAINPATH || plane_y->bytesperline < stride) + plane_y->bytesperline = stride; + plane_y->sizeimage = plane_y->bytesperline * pixm->height; + + /* normalize stride to pixels per line */ + stride = DIV_ROUND_UP(plane_y->bytesperline, info->bpp[0]); + + for (i = 1; i < info->comp_planes; i++) { + struct v4l2_plane_pix_format *plane = &pixm->plane_fmt[i]; + + /* bytesperline for other components derive from Y component */ + plane->bytesperline = DIV_ROUND_UP(stride, info->hdiv) * + info->bpp[i]; + plane->sizeimage = plane->bytesperline * + DIV_ROUND_UP(pixm->height, info->vdiv); + } + + /* + * If pixfmt is packed, then plane_fmt[0] should contain the total size + * considering all components. plane_fmt[i] for i > 0 should be ignored + * by userspace as mem_planes == 1, but we are keeping information there + * for convenience. + */ + if (info->mem_planes == 1) + for (i = 1; i < info->comp_planes; i++) + plane_y->sizeimage += pixm->plane_fmt[i].sizeimage; + + return info; +} + +static const struct rkisp1_capture_fmt_cfg * +rkisp1_find_fmt_cfg(const struct rkisp1_capture *cap, const u32 pixelfmt) +{ + unsigned int i; + + for (i = 0; i < cap->config->fmt_size; i++) { + if (cap->config->fmts[i].fourcc == pixelfmt) + return &cap->config->fmts[i]; + } + return NULL; +} + +static void rkisp1_try_fmt(const struct rkisp1_capture *cap, + struct v4l2_pix_format_mplane *pixm, + const struct rkisp1_capture_fmt_cfg **fmt_cfg, + const struct v4l2_format_info **fmt_info) +{ + const struct rkisp1_capture_config *config = cap->config; + const struct rkisp1_capture_fmt_cfg *fmt; + const struct v4l2_format_info *info; + const unsigned int max_widths[] = { RKISP1_RSZ_MP_SRC_MAX_WIDTH, + RKISP1_RSZ_SP_SRC_MAX_WIDTH }; + const unsigned int max_heights[] = { RKISP1_RSZ_MP_SRC_MAX_HEIGHT, + RKISP1_RSZ_SP_SRC_MAX_HEIGHT}; + + fmt = rkisp1_find_fmt_cfg(cap, pixm->pixelformat); + if (!fmt) { + fmt = config->fmts; + pixm->pixelformat = fmt->fourcc; + } + + pixm->width = clamp_t(u32, pixm->width, + RKISP1_RSZ_SRC_MIN_WIDTH, max_widths[cap->id]); + pixm->height = clamp_t(u32, pixm->height, + RKISP1_RSZ_SRC_MIN_HEIGHT, max_heights[cap->id]); + + pixm->field = V4L2_FIELD_NONE; + pixm->colorspace = V4L2_COLORSPACE_DEFAULT; + pixm->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + pixm->quantization = V4L2_QUANTIZATION_DEFAULT; + + info = rkisp1_fill_pixfmt(pixm, cap->id); + + if (fmt_cfg) + *fmt_cfg = fmt; + if (fmt_info) + *fmt_info = info; +} + +static void rkisp1_set_fmt(struct rkisp1_capture *cap, + struct v4l2_pix_format_mplane *pixm) +{ + rkisp1_try_fmt(cap, pixm, &cap->pix.cfg, &cap->pix.info); + cap->pix.fmt = *pixm; + + /* SP supports custom stride in number of pixels of the Y plane */ + if (cap->id == RKISP1_SELFPATH) + cap->sp_y_stride = pixm->plane_fmt[0].bytesperline / + cap->pix.info->bpp[0]; +} + +static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct rkisp1_capture *cap = video_drvdata(file); + + rkisp1_try_fmt(cap, &f->fmt.pix_mp, NULL, NULL); + + return 0; +} + +static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct rkisp1_capture *cap = video_drvdata(file); + const struct rkisp1_capture_fmt_cfg *fmt = NULL; + unsigned int i, n = 0; + + if (!f->mbus_code) { + if (f->index >= cap->config->fmt_size) + return -EINVAL; + + fmt = &cap->config->fmts[f->index]; + f->pixelformat = fmt->fourcc; + return 0; + } + + for (i = 0; i < cap->config->fmt_size; i++) { + if (cap->config->fmts[i].mbus != f->mbus_code) + continue; + + if (n++ == f->index) { + f->pixelformat = cap->config->fmts[i].fourcc; + return 0; + } + } + return -EINVAL; +} + +static int rkisp1_s_fmt_vid_cap_mplane(struct file *file, + void *priv, struct v4l2_format *f) +{ + struct rkisp1_capture *cap = video_drvdata(file); + struct rkisp1_vdev_node *node = + rkisp1_vdev_to_node(&cap->vnode.vdev); + + if (vb2_is_busy(&node->buf_queue)) + return -EBUSY; + + rkisp1_set_fmt(cap, &f->fmt.pix_mp); + + return 0; +} + +static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct rkisp1_capture *cap = video_drvdata(file); + + f->fmt.pix_mp = cap->pix.fmt; + + return 0; +} + +static int +rkisp1_querycap(struct file *file, void *priv, struct v4l2_capability *cap) +{ + struct rkisp1_capture *cap_dev = video_drvdata(file); + struct rkisp1_device *rkisp1 = cap_dev->rkisp1; + + strscpy(cap->driver, rkisp1->dev->driver->name, sizeof(cap->driver)); + strscpy(cap->card, rkisp1->dev->driver->name, sizeof(cap->card)); + strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); + + return 0; +} + +static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane, + .vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane, + .vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane, + .vidioc_enum_fmt_vid_cap = rkisp1_enum_fmt_vid_cap_mplane, + .vidioc_querycap = rkisp1_querycap, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int rkisp1_capture_link_validate(struct media_link *link) +{ + struct video_device *vdev = + media_entity_to_video_device(link->sink->entity); + struct v4l2_subdev *sd = + media_entity_to_v4l2_subdev(link->source->entity); + struct rkisp1_capture *cap = video_get_drvdata(vdev); + const struct rkisp1_capture_fmt_cfg *fmt = + rkisp1_find_fmt_cfg(cap, cap->pix.fmt.pixelformat); + struct v4l2_subdev_format sd_fmt; + int ret; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = link->source->index; + ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + if (sd_fmt.format.height != cap->pix.fmt.height || + sd_fmt.format.width != cap->pix.fmt.width || + sd_fmt.format.code != fmt->mbus) + return -EPIPE; + + return 0; +} + +/* ---------------------------------------------------------------------------- + * core functions + */ + +static const struct media_entity_operations rkisp1_media_ops = { + .link_validate = rkisp1_capture_link_validate, +}; + +static const struct v4l2_file_operations rkisp1_fops = { + .open = v4l2_fh_open, + .release = vb2_fop_release, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .mmap = vb2_fop_mmap, +}; + +static void rkisp1_unregister_capture(struct rkisp1_capture *cap) +{ + media_entity_cleanup(&cap->vnode.vdev.entity); + vb2_video_unregister_device(&cap->vnode.vdev); +} + +void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1) +{ + struct rkisp1_capture *mp = &rkisp1->capture_devs[RKISP1_MAINPATH]; + struct rkisp1_capture *sp = &rkisp1->capture_devs[RKISP1_SELFPATH]; + + rkisp1_unregister_capture(mp); + rkisp1_unregister_capture(sp); +} + +static int rkisp1_register_capture(struct rkisp1_capture *cap) +{ + const char * const dev_names[] = {RKISP1_MP_DEV_NAME, + RKISP1_SP_DEV_NAME}; + struct v4l2_device *v4l2_dev = &cap->rkisp1->v4l2_dev; + struct video_device *vdev = &cap->vnode.vdev; + struct rkisp1_vdev_node *node; + struct vb2_queue *q; + int ret; + + strscpy(vdev->name, dev_names[cap->id], sizeof(vdev->name)); + node = rkisp1_vdev_to_node(vdev); + mutex_init(&node->vlock); + + vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops; + vdev->release = video_device_release_empty; + vdev->fops = &rkisp1_fops; + vdev->minor = -1; + vdev->v4l2_dev = v4l2_dev; + vdev->lock = &node->vlock; + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; + vdev->entity.ops = &rkisp1_media_ops; + video_set_drvdata(vdev, cap); + vdev->vfl_dir = VFL_DIR_RX; + node->pad.flags = MEDIA_PAD_FL_SINK; + + q = &node->buf_queue; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->io_modes = VB2_MMAP | VB2_DMABUF; + q->drv_priv = cap; + q->ops = &rkisp1_vb2_ops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct rkisp1_buffer); + q->min_buffers_needed = RKISP1_MIN_BUFFERS_NEEDED; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &node->vlock; + q->dev = cap->rkisp1->dev; + ret = vb2_queue_init(q); + if (ret) { + dev_err(cap->rkisp1->dev, + "vb2 queue init failed (err=%d)\n", ret); + return ret; + } + + vdev->queue = q; + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(cap->rkisp1->dev, + "failed to register %s, ret=%d\n", vdev->name, ret); + return ret; + } + v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name, + vdev->num); + + ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); + if (ret) { + video_unregister_device(vdev); + return ret; + } + + return 0; +} + +static void +rkisp1_capture_init(struct rkisp1_device *rkisp1, enum rkisp1_stream_id id) +{ + struct rkisp1_capture *cap = &rkisp1->capture_devs[id]; + struct v4l2_pix_format_mplane pixm; + + memset(cap, 0, sizeof(*cap)); + cap->id = id; + cap->rkisp1 = rkisp1; + + INIT_LIST_HEAD(&cap->buf.queue); + init_waitqueue_head(&cap->done); + spin_lock_init(&cap->buf.lock); + if (cap->id == RKISP1_SELFPATH) { + cap->ops = &rkisp1_capture_ops_sp; + cap->config = &rkisp1_capture_config_sp; + } else { + cap->ops = &rkisp1_capture_ops_mp; + cap->config = &rkisp1_capture_config_mp; + } + + cap->is_streaming = false; + + memset(&pixm, 0, sizeof(pixm)); + pixm.pixelformat = V4L2_PIX_FMT_YUYV; + pixm.width = RKISP1_DEFAULT_WIDTH; + pixm.height = RKISP1_DEFAULT_HEIGHT; + rkisp1_set_fmt(cap, &pixm); +} + +int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1) +{ + struct rkisp1_capture *cap; + unsigned int i, j; + int ret; + + for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); i++) { + rkisp1_capture_init(rkisp1, i); + cap = &rkisp1->capture_devs[i]; + cap->rkisp1 = rkisp1; + ret = rkisp1_register_capture(cap); + if (ret) + goto err_unreg_capture_devs; + } + + return 0; + +err_unreg_capture_devs: + for (j = 0; j < i; j++) { + cap = &rkisp1->capture_devs[j]; + rkisp1_unregister_capture(cap); + } + + return ret; +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c new file mode 100644 index 000000000000..cf889666e166 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - Common definitions + * + * Copyright (C) 2019 Collabora, Ltd. + */ + +#include + +#include "rkisp1-common.h" + +static const struct v4l2_rect rkisp1_sd_min_crop = { + .width = RKISP1_ISP_MIN_WIDTH, + .height = RKISP1_ISP_MIN_HEIGHT, + .top = 0, + .left = 0, +}; + +void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop, + const struct v4l2_rect *bounds) +{ + v4l2_rect_set_min_size(crop, &rkisp1_sd_min_crop); + v4l2_rect_map_inside(crop, bounds); +} + +void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, + const struct v4l2_mbus_framefmt *bounds) +{ + struct v4l2_rect crop_bounds = { + .left = 0, + .top = 0, + .width = bounds->width, + .height = bounds->height, + }; + + rkisp1_sd_adjust_crop_rect(crop, &crop_bounds); +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h new file mode 100644 index 000000000000..3a134e97161c --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Rockchip ISP1 Driver - Common definitions + * + * Copyright (C) 2019 Collabora, Ltd. + * + * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef _RKISP1_COMMON_H +#define _RKISP1_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rkisp1-regs.h" + +/* + * flags on the 'direction' field in struct 'rkisp1_isp_mbus_info' that indicate + * on which pad the media bus format is supported + */ +#define RKISP1_ISP_SD_SRC BIT(0) +#define RKISP1_ISP_SD_SINK BIT(1) + +/* min and max values for the widths and heights of the entities */ +#define RKISP1_ISP_MAX_WIDTH 4032 +#define RKISP1_ISP_MAX_HEIGHT 3024 +#define RKISP1_ISP_MIN_WIDTH 32 +#define RKISP1_ISP_MIN_HEIGHT 32 + +#define RKISP1_RSZ_MP_SRC_MAX_WIDTH 4416 +#define RKISP1_RSZ_MP_SRC_MAX_HEIGHT 3312 +#define RKISP1_RSZ_SP_SRC_MAX_WIDTH 1920 +#define RKISP1_RSZ_SP_SRC_MAX_HEIGHT 1920 +#define RKISP1_RSZ_SRC_MIN_WIDTH 32 +#define RKISP1_RSZ_SRC_MIN_HEIGHT 16 + +/* the default width and height of all the entities */ +#define RKISP1_DEFAULT_WIDTH 800 +#define RKISP1_DEFAULT_HEIGHT 600 + +#define RKISP1_DRIVER_NAME "rkisp1" +#define RKISP1_BUS_INFO "platform:" RKISP1_DRIVER_NAME + +/* maximum number of clocks */ +#define RKISP1_MAX_BUS_CLK 8 + +/* a bitmask of the ready stats */ +#define RKISP1_STATS_MEAS_MASK (RKISP1_CIF_ISP_AWB_DONE | \ + RKISP1_CIF_ISP_AFM_FIN | \ + RKISP1_CIF_ISP_EXP_END | \ + RKISP1_CIF_ISP_HIST_MEASURE_RDY) + +/* enum for the resizer pads */ +enum rkisp1_rsz_pad { + RKISP1_RSZ_PAD_SINK, + RKISP1_RSZ_PAD_SRC, + RKISP1_RSZ_PAD_MAX +}; + +/* enum for the capture id */ +enum rkisp1_stream_id { + RKISP1_MAINPATH, + RKISP1_SELFPATH, +}; + +/* bayer patterns */ +enum rkisp1_fmt_raw_pat_type { + RKISP1_RAW_RGGB = 0, + RKISP1_RAW_GRBG, + RKISP1_RAW_GBRG, + RKISP1_RAW_BGGR, +}; + +/* enum for the isp pads */ +enum rkisp1_isp_pad { + RKISP1_ISP_PAD_SINK_VIDEO, + RKISP1_ISP_PAD_SINK_PARAMS, + RKISP1_ISP_PAD_SOURCE_VIDEO, + RKISP1_ISP_PAD_SOURCE_STATS, + RKISP1_ISP_PAD_MAX +}; + +/* + * struct rkisp1_sensor_async - A container for the v4l2_async_subdev to add to the notifier + * of the v4l2-async API + * + * @asd: async_subdev variable for the sensor + * @lanes: number of lanes + * @mbus_type: type of bus (currently only CSI2 is supported) + * @mbus_flags: media bus (V4L2_MBUS_*) flags + * @sd: a pointer to v4l2_subdev struct of the sensor + * @pixel_rate_ctrl: pixel rate of the sensor, used to initialize the phy + * @dphy: a pointer to the phy + */ +struct rkisp1_sensor_async { + struct v4l2_async_subdev asd; + unsigned int lanes; + enum v4l2_mbus_type mbus_type; + unsigned int mbus_flags; + struct v4l2_subdev *sd; + struct v4l2_ctrl *pixel_rate_ctrl; + struct phy *dphy; +}; + +/* + * struct rkisp1_isp - ISP subdev entity + * + * @sd: v4l2_subdev variable + * @rkisp1: pointer to rkisp1_device + * @pads: media pads + * @pad_cfg: pads configurations + * @sink_fmt: input format + * @src_fmt: output format + * @ops_lock: ops serialization + * @is_dphy_errctrl_disabled: if dphy errctrl is disabled (avoid endless interrupt) + * @frame_sequence: used to synchronize frame_id between video devices. + */ +struct rkisp1_isp { + struct v4l2_subdev sd; + struct media_pad pads[RKISP1_ISP_PAD_MAX]; + struct v4l2_subdev_pad_config pad_cfg[RKISP1_ISP_PAD_MAX]; + const struct rkisp1_isp_mbus_info *sink_fmt; + const struct rkisp1_isp_mbus_info *src_fmt; + struct mutex ops_lock; /* serialize the subdevice ops */ + bool is_dphy_errctrl_disabled; + __u32 frame_sequence; +}; + +/* + * struct rkisp1_vdev_node - Container for the video nodes: params, stats, mainpath, selfpath + * + * @buf_queue: queue of buffers + * @vlock: lock of the video node + * @vdev: video node + * @pad: media pad + */ +struct rkisp1_vdev_node { + struct vb2_queue buf_queue; + struct mutex vlock; /* ioctl serialization mutex */ + struct video_device vdev; + struct media_pad pad; +}; + +/* + * struct rkisp1_buffer - A container for the vb2 buffers used by the video devices: + * params, stats, mainpath, selfpath + * + * @vb: vb2 buffer + * @queue: entry of the buffer in the queue + * @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath + * @vaddr: virtual address for buffers used by params and stats devices + */ +struct rkisp1_buffer { + struct vb2_v4l2_buffer vb; + struct list_head queue; + union { + u32 buff_addr[VIDEO_MAX_PLANES]; + void *vaddr; + }; +}; + +/* + * struct rkisp1_dummy_buffer - A buffer to write the next frame to in case + * there are no vb2 buffers available. + * + * @vaddr: return value of call to dma_alloc_attrs. + * @dma_addr: dma address of the buffer. + * @size: size of the buffer. + */ +struct rkisp1_dummy_buffer { + void *vaddr; + dma_addr_t dma_addr; + u32 size; +}; + +struct rkisp1_device; + +/* + * struct rkisp1_capture - ISP capture video device + * + * @vnode: video node + * @rkisp1: pointer to rkisp1_device + * @id: id of the capture, one of RKISP1_SELFPATH, RKISP1_MAINPATH + * @ops: list of callbacks to configure the capture device. + * @config: a pointer to the list of registers to configure the capture format. + * @is_streaming: device is streaming + * @is_stopping: stop_streaming callback was called and the device is in the process of + * stopping the streaming. + * @done: when stop_streaming callback is called, the device waits for the next irq + * handler to stop the streaming by waiting on the 'done' wait queue. + * If the irq handler is not called, the stream is stopped by the callback + * after timeout. + * @sp_y_stride: the selfpath allows to configure a y stride that is longer than the image width. + * @buf.lock: lock to protect buf.queue + * @buf.queue: queued buffer list + * @buf.dummy: dummy space to store dropped data + * + * rkisp1 uses shadow registers, so it needs two buffers at a time + * @buf.curr: the buffer used for current frame + * @buf.next: the buffer used for next frame + * @pix.cfg: pixel configuration + * @pix.info: a pointer to the v4l2_format_info of the pixel format + * @pix.fmt: buffer format + */ +struct rkisp1_capture { + struct rkisp1_vdev_node vnode; + struct rkisp1_device *rkisp1; + enum rkisp1_stream_id id; + struct rkisp1_capture_ops *ops; + const struct rkisp1_capture_config *config; + bool is_streaming; + bool is_stopping; + wait_queue_head_t done; + unsigned int sp_y_stride; + struct { + /* protects queue, curr and next */ + spinlock_t lock; + struct list_head queue; + struct rkisp1_dummy_buffer dummy; + struct rkisp1_buffer *curr; + struct rkisp1_buffer *next; + } buf; + struct { + const struct rkisp1_capture_fmt_cfg *cfg; + const struct v4l2_format_info *info; + struct v4l2_pix_format_mplane fmt; + } pix; +}; + +/* + * struct rkisp1_stats - ISP Statistics device + * + * @vnode: video node + * @rkisp1: pointer to the rkisp1 device + * @lock: locks the buffer list 'stat' + * @stat: queue of rkisp1_buffer + * @vdev_fmt: v4l2_format of the metadata format + */ +struct rkisp1_stats { + struct rkisp1_vdev_node vnode; + struct rkisp1_device *rkisp1; + + spinlock_t lock; /* locks the buffers list 'stats' */ + struct list_head stat; + struct v4l2_format vdev_fmt; +}; + +/* + * struct rkisp1_params - ISP input parameters device + * + * @vnode: video node + * @rkisp1: pointer to the rkisp1 device + * @config_lock: locks the buffer list 'params' + * @params: queue of rkisp1_buffer + * @vdev_fmt: v4l2_format of the metadata format + * @quantization: the quantization configured on the isp's src pad + * @raw_type: the bayer pattern on the isp video sink pad + */ +struct rkisp1_params { + struct rkisp1_vdev_node vnode; + struct rkisp1_device *rkisp1; + + spinlock_t config_lock; /* locks the buffers list 'params' */ + struct list_head params; + struct v4l2_format vdev_fmt; + + enum v4l2_quantization quantization; + enum rkisp1_fmt_raw_pat_type raw_type; +}; + +/* + * struct rkisp1_resizer - Resizer subdev + * + * @sd: v4l2_subdev variable + * @id: id of the resizer, one of RKISP1_SELFPATH, RKISP1_MAINPATH + * @rkisp1: pointer to the rkisp1 device + * @pads: media pads + * @pad_cfg: configurations for the pads + * @config: the set of registers to configure the resizer + * @pixel_enc: pixel encoding of the resizer + * @ops_lock: a lock for the subdev ops + */ +struct rkisp1_resizer { + struct v4l2_subdev sd; + enum rkisp1_stream_id id; + struct rkisp1_device *rkisp1; + struct media_pad pads[RKISP1_RSZ_PAD_MAX]; + struct v4l2_subdev_pad_config pad_cfg[RKISP1_RSZ_PAD_MAX]; + const struct rkisp1_rsz_config *config; + enum v4l2_pixel_encoding pixel_enc; + struct mutex ops_lock; /* serialize the subdevice ops */ +}; + +/* + * struct rkisp1_debug - Values to be exposed on debugfs. + * The parameters are counters of the number of times the + * event occurred since the driver was loaded. + * + * @data_loss: loss of data occurred within a line, processing failure + * @outform_size_error: size error is generated in outmux submodule + * @img_stabilization_size_error: size error is generated in image stabilization submodule + * @inform_size_err: size error is generated in inform submodule + * @mipi_error: mipi error occurred + * @stats_error: writing to the 'Interrupt clear register' did not clear + * it in the register 'Masked interrupt status' + * @stop_timeout: upon stream stop, the capture waits 1 second for the isr to stop + * the stream. This param is incremented in case of timeout. + * @frame_drop: a frame was ready but the buffer queue was empty so the frame + * was not sent to userspace + */ +struct rkisp1_debug { + struct dentry *debugfs_dir; + unsigned long data_loss; + unsigned long outform_size_error; + unsigned long img_stabilization_size_error; + unsigned long inform_size_error; + unsigned long irq_delay; + unsigned long mipi_error; + unsigned long stats_error; + unsigned long stop_timeout[2]; + unsigned long frame_drop[2]; +}; + +/* + * struct rkisp1_device - ISP platform device + * + * @base_addr: base register address + * @irq: the irq number + * @dev: a pointer to the struct device + * @clk_size: number of clocks + * @clks: array of clocks + * @v4l2_dev: v4l2_device variable + * @media_dev: media_device variable + * @notifier: a notifier to register on the v4l2-async API to be notified on the sensor + * @active_sensor: sensor in-use, set when streaming on + * @isp: ISP sub-device + * @resizer_devs: resizer sub-devices + * @capture_devs: capture devices + * @stats: ISP statistics metadata capture device + * @params: ISP parameters metadata output device + * @pipe: media pipeline + * @stream_lock: serializes {start/stop}_streaming callbacks between the capture devices. + * @debug: debug params to be exposed on debugfs + */ +struct rkisp1_device { + void __iomem *base_addr; + int irq; + struct device *dev; + unsigned int clk_size; + struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK]; + struct v4l2_device v4l2_dev; + struct media_device media_dev; + struct v4l2_async_notifier notifier; + struct rkisp1_sensor_async *active_sensor; + struct rkisp1_isp isp; + struct rkisp1_resizer resizer_devs[2]; + struct rkisp1_capture capture_devs[2]; + struct rkisp1_stats stats; + struct rkisp1_params params; + struct media_pipeline pipe; + struct mutex stream_lock; /* serialize {start/stop}_streaming cb between capture devices */ + struct rkisp1_debug debug; +}; + +/* + * struct rkisp1_isp_mbus_info - ISP media bus info, Translates media bus code to hardware + * format values + * + * @mbus_code: media bus code + * @pixel_enc: pixel encoding + * @mipi_dt: mipi data type + * @yuv_seq: the order of the Y, Cb, Cr values + * @bus_width: bus width + * @bayer_pat: bayer pattern + * @direction: a bitmask of the flags indicating on which pad the format is supported on + */ +struct rkisp1_isp_mbus_info { + u32 mbus_code; + enum v4l2_pixel_encoding pixel_enc; + u32 mipi_dt; + u32 yuv_seq; + u8 bus_width; + enum rkisp1_fmt_raw_pat_type bayer_pat; + unsigned int direction; +}; + +static inline void +rkisp1_write(struct rkisp1_device *rkisp1, u32 val, unsigned int addr) +{ + writel(val, rkisp1->base_addr + addr); +} + +static inline u32 rkisp1_read(struct rkisp1_device *rkisp1, unsigned int addr) +{ + return readl(rkisp1->base_addr + addr); +} + +/* + * rkisp1_cap_enum_mbus_codes - A helper function that return the i'th supported mbus code + * of the capture entity. This is used to enumerate the supported + * mbus codes on the source pad of the resizer. + * + * @cap: the capture entity + * @code: the mbus code, the function reads the code->index and fills the code->code + */ +int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, + struct v4l2_subdev_mbus_code_enum *code); + +/* + * rkisp1_sd_adjust_crop_rect - adjust a rectangle to fit into another rectangle. + * + * @crop: rectangle to adjust. + * @bounds: rectangle used as bounds. + */ +void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop, + const struct v4l2_rect *bounds); + +/* + * rkisp1_sd_adjust_crop - adjust a rectangle to fit into media bus format + * + * @crop: rectangle to adjust. + * @bounds: media bus format used as bounds. + */ +void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, + const struct v4l2_mbus_framefmt *bounds); + +/* + * rkisp1_isp_mbus_info - get the isp info of the media bus code + * + * @mbus_code: the media bus code + */ +const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code); + +/* rkisp1_params_configure - configure the params when stream starts. + * This function is called by the isp entity upon stream starts. + * The function applies the initial configuration of the parameters. + * + * @params: pointer to rkisp1_params. + * @bayer_pat: the bayer pattern on the isp video sink pad + * @quantization: the quantization configured on the isp's src pad + */ +void rkisp1_params_configure(struct rkisp1_params *params, + enum rkisp1_fmt_raw_pat_type bayer_pat, + enum v4l2_quantization quantization); + +/* rkisp1_params_disable - disable all parameters. + * This function is called by the isp entity upon stream start + * when capturing bayer format. + * + * @params: pointer to rkisp1_params. + */ +void rkisp1_params_disable(struct rkisp1_params *params); + +/* irq handlers */ +void rkisp1_isp_isr(struct rkisp1_device *rkisp1); +void rkisp1_mipi_isr(struct rkisp1_device *rkisp1); +void rkisp1_capture_isr(struct rkisp1_device *rkisp1); +void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris); +void rkisp1_params_isr(struct rkisp1_device *rkisp1); + +/* register/unregisters functions of the entities */ +int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1); +void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1); + +int rkisp1_isp_register(struct rkisp1_device *rkisp1); +void rkisp1_isp_unregister(struct rkisp1_device *rkisp1); + +int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1); +void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1); + +int rkisp1_stats_register(struct rkisp1_device *rkisp1); +void rkisp1_stats_unregister(struct rkisp1_device *rkisp1); + +int rkisp1_params_register(struct rkisp1_device *rkisp1); +void rkisp1_params_unregister(struct rkisp1_device *rkisp1); + +#endif /* _RKISP1_COMMON_H */ diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c new file mode 100644 index 000000000000..9af137e4967f --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - Base driver + * + * Copyright (C) 2019 Collabora, Ltd. + * + * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rkisp1-common.h" + +/* + * ISP Details + * ----------- + * + * ISP Comprises with: + * MIPI serial camera interface + * Image Signal Processing + * Many Image Enhancement Blocks + * Crop + * Resizer + * RBG display ready image + * Image Rotation + * + * ISP Block Diagram + * ----------------- + * rkisp1-resizer.c rkisp1-capture.c + * |====================| |=======================| + * rkisp1-isp.c Main Picture Path + * |==========================| |===============================================| + * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+ + * | | | | | | | | | | | | | + * +--------+ |\ | | | | | | | -->| Crop |->| RSZ |------------->| | + * | MIPI |--->| \ | | | | | | | | | | | | | | + * +--------+ | | | | |IE|IE|IE|IE| | +--------+ +--------+ | Memory | + * |MUX|--->| ISP |->|0 |1 |2 |3 |---+ | Interface | + * +--------+ | | | | | | | | | | +--------+ +--------+ +--------+ | | + * |Parallel|--->| / | | | | | | | | | | | | | | | | + * +--------+ |/ | | | | | | | -->| Crop |->| RSZ |->| RGB |->| | + * | | | | | | | | | | | | Rotate | | | + * +-----------+ +--+--+--+--+ +--------+ +--------+ +--------+ +-----------+ + * ^ + * +--------+ | |===============================================| + * | DMA |------------------------------------+ Self Picture Path + * +--------+ + * + * rkisp1-stats.c rkisp1-params.c + * |===============| |===============| + * +---------------+ +---------------+ + * | | | | + * | ISP | | ISP | + * | | | | + * +---------------+ +---------------+ + * + * + * Media Topology + * -------------- + * +----------+ +----------+ + * | Sensor 2 | | Sensor X | + * ------------ ... ------------ + * | 0 | | 0 | + * +----------+ +----------+ +-----------+ + * \ | | params | + * \ | | (output) | + * +----------+ \ | +-----------+ + * | Sensor 1 | v v | + * ------------ +------+------+ | + * | 0 |----->| 0 | 1 |<---------+ + * +----------+ |------+------| + * | ISP | + * |------+------| + * +-------------| 2 | 3 |----------+ + * | +------+------+ | + * | | | + * v v v + * +- ---------+ +-----------+ +-----------+ + * | 0 | | 0 | | stats | + * ------------- ------------- | (capture) | + * | Resizer | | Resizer | +-----------+ + * ------------| ------------| + * | 1 | | 1 | + * +-----------+ +-----------+ + * | | + * v v + * +-----------+ +-----------+ + * | selfpath | | mainpath | + * | (capture) | | (capture) | + * +-----------+ +-----------+ + */ + +struct rkisp1_match_data { + const char * const *clks; + unsigned int size; +}; + +/* ---------------------------------------------------------------------------- + * Sensor DT bindings + */ + +static int rkisp1_create_links(struct rkisp1_device *rkisp1) +{ + struct media_entity *source, *sink; + unsigned int flags, source_pad; + struct v4l2_subdev *sd; + unsigned int i; + int ret; + + /* sensor links */ + flags = MEDIA_LNK_FL_ENABLED; + list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) { + if (sd == &rkisp1->isp.sd || + sd == &rkisp1->resizer_devs[RKISP1_MAINPATH].sd || + sd == &rkisp1->resizer_devs[RKISP1_SELFPATH].sd) + continue; + + ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode, + MEDIA_PAD_FL_SOURCE); + if (ret < 0) { + dev_err(rkisp1->dev, "failed to find src pad for %s\n", + sd->name); + return ret; + } + source_pad = ret; + + ret = media_create_pad_link(&sd->entity, source_pad, + &rkisp1->isp.sd.entity, + RKISP1_ISP_PAD_SINK_VIDEO, + flags); + if (ret) + return ret; + + flags = 0; + } + + flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; + + /* create ISP->RSZ->CAP links */ + for (i = 0; i < 2; i++) { + source = &rkisp1->isp.sd.entity; + sink = &rkisp1->resizer_devs[i].sd.entity; + ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_VIDEO, + sink, RKISP1_RSZ_PAD_SINK, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + source = sink; + sink = &rkisp1->capture_devs[i].vnode.vdev.entity; + ret = media_create_pad_link(source, RKISP1_RSZ_PAD_SRC, + sink, 0, flags); + if (ret) + return ret; + } + + /* params links */ + source = &rkisp1->params.vnode.vdev.entity; + sink = &rkisp1->isp.sd.entity; + ret = media_create_pad_link(source, 0, sink, + RKISP1_ISP_PAD_SINK_PARAMS, flags); + if (ret) + return ret; + + /* 3A stats links */ + source = &rkisp1->isp.sd.entity; + sink = &rkisp1->stats.vnode.vdev.entity; + return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS, + sink, 0, flags); +} + +static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct rkisp1_device *rkisp1 = + container_of(notifier, struct rkisp1_device, notifier); + struct rkisp1_sensor_async *s_asd = + container_of(asd, struct rkisp1_sensor_async, asd); + + s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, + V4L2_CID_PIXEL_RATE); + s_asd->sd = sd; + s_asd->dphy = devm_phy_get(rkisp1->dev, "dphy"); + if (IS_ERR(s_asd->dphy)) { + if (PTR_ERR(s_asd->dphy) != -EPROBE_DEFER) + dev_err(rkisp1->dev, "Couldn't get the MIPI D-PHY\n"); + return PTR_ERR(s_asd->dphy); + } + + phy_init(s_asd->dphy); + + return 0; +} + +static void rkisp1_subdev_notifier_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct rkisp1_sensor_async *s_asd = + container_of(asd, struct rkisp1_sensor_async, asd); + + phy_exit(s_asd->dphy); +} + +static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier) +{ + struct rkisp1_device *rkisp1 = + container_of(notifier, struct rkisp1_device, notifier); + int ret; + + ret = rkisp1_create_links(rkisp1); + if (ret) + return ret; + + ret = v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev); + if (ret) + return ret; + + dev_dbg(rkisp1->dev, "Async subdev notifier completed\n"); + + return 0; +} + +static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = { + .bound = rkisp1_subdev_notifier_bound, + .unbind = rkisp1_subdev_notifier_unbind, + .complete = rkisp1_subdev_notifier_complete, +}; + +static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) +{ + struct v4l2_async_notifier *ntf = &rkisp1->notifier; + unsigned int next_id = 0; + int ret; + + v4l2_async_notifier_init(ntf); + + while (1) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct rkisp1_sensor_async *rk_asd = NULL; + struct fwnode_handle *ep; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev), + 0, next_id, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + break; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; + + rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL); + if (!rk_asd) { + ret = -ENOMEM; + goto err_parse; + } + + rk_asd->mbus_type = vep.bus_type; + rk_asd->mbus_flags = vep.bus.mipi_csi2.flags; + rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes; + + ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep, + &rk_asd->asd); + if (ret) + goto err_parse; + + dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n", + vep.base.id, rk_asd->lanes); + + next_id = vep.base.id + 1; + + fwnode_handle_put(ep); + + continue; +err_parse: + fwnode_handle_put(ep); + kfree(rk_asd); + v4l2_async_notifier_cleanup(ntf); + return ret; + } + + if (next_id == 0) + dev_dbg(rkisp1->dev, "no remote subdevice found\n"); + ntf->ops = &rkisp1_subdev_notifier_ops; + ret = v4l2_async_notifier_register(&rkisp1->v4l2_dev, ntf); + if (ret) { + v4l2_async_notifier_cleanup(ntf); + return ret; + } + return 0; +} + +/* ---------------------------------------------------------------------------- + * Power + */ + +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev) +{ + struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks); + return pinctrl_pm_select_sleep_state(dev); +} + +static int __maybe_unused rkisp1_runtime_resume(struct device *dev) +{ + struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); + int ret; + + ret = pinctrl_pm_select_default_state(dev); + if (ret) + return ret; + ret = clk_bulk_prepare_enable(rkisp1->clk_size, rkisp1->clks); + if (ret) + return ret; + + return 0; +} + +static const struct dev_pm_ops rkisp1_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL) +}; + +/* ---------------------------------------------------------------------------- + * Core + */ + +static int rkisp1_entities_register(struct rkisp1_device *rkisp1) +{ + int ret; + + ret = rkisp1_isp_register(rkisp1); + if (ret) + return ret; + + ret = rkisp1_resizer_devs_register(rkisp1); + if (ret) + goto err_unreg_isp_subdev; + + ret = rkisp1_capture_devs_register(rkisp1); + if (ret) + goto err_unreg_resizer_devs; + + ret = rkisp1_stats_register(rkisp1); + if (ret) + goto err_unreg_capture_devs; + + ret = rkisp1_params_register(rkisp1); + if (ret) + goto err_unreg_stats; + + ret = rkisp1_subdev_notifier(rkisp1); + if (ret) { + dev_err(rkisp1->dev, + "Failed to register subdev notifier(%d)\n", ret); + goto err_unreg_params; + } + + return 0; +err_unreg_params: + rkisp1_params_unregister(rkisp1); +err_unreg_stats: + rkisp1_stats_unregister(rkisp1); +err_unreg_capture_devs: + rkisp1_capture_devs_unregister(rkisp1); +err_unreg_resizer_devs: + rkisp1_resizer_devs_unregister(rkisp1); +err_unreg_isp_subdev: + rkisp1_isp_unregister(rkisp1); + return ret; +} + +static irqreturn_t rkisp1_isr(int irq, void *ctx) +{ + struct device *dev = ctx; + struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); + + /* + * Call rkisp1_capture_isr() first to handle the frame that + * potentially completed using the current frame_sequence number before + * it is potentially incremented by rkisp1_isp_isr() in the vertical + * sync. + */ + rkisp1_capture_isr(rkisp1); + rkisp1_isp_isr(rkisp1); + rkisp1_mipi_isr(rkisp1); + + return IRQ_HANDLED; +} + +static const char * const rk3399_isp_clks[] = { + "isp", + "aclk", + "hclk", +}; + +static const struct rkisp1_match_data rk3399_isp_clk_data = { + .clks = rk3399_isp_clks, + .size = ARRAY_SIZE(rk3399_isp_clks), +}; + +static const struct of_device_id rkisp1_of_match[] = { + { + .compatible = "rockchip,rk3399-cif-isp", + .data = &rk3399_isp_clk_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, rkisp1_of_match); + +static void rkisp1_debug_init(struct rkisp1_device *rkisp1) +{ + struct rkisp1_debug *debug = &rkisp1->debug; + + debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL); + if (!debug->debugfs_dir) { + dev_dbg(rkisp1->dev, "failed to create debugfs directory\n"); + return; + } + debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir, + &debug->data_loss); + debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir, + &debug->outform_size_error); + debugfs_create_ulong("img_stabilization_size_error", 0444, + debug->debugfs_dir, + &debug->img_stabilization_size_error); + debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir, + &debug->inform_size_error); + debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir, + &debug->irq_delay); + debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir, + &debug->mipi_error); + debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir, + &debug->stats_error); + debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir, + &debug->stop_timeout[RKISP1_MAINPATH]); + debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir, + &debug->stop_timeout[RKISP1_SELFPATH]); + debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir, + &debug->frame_drop[RKISP1_MAINPATH]); + debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir, + &debug->frame_drop[RKISP1_SELFPATH]); +} + +static int rkisp1_probe(struct platform_device *pdev) +{ + const struct rkisp1_match_data *clk_data; + struct device *dev = &pdev->dev; + struct rkisp1_device *rkisp1; + struct v4l2_device *v4l2_dev; + unsigned int i; + int ret, irq; + + clk_data = of_device_get_match_data(&pdev->dev); + if (!clk_data) + return -ENODEV; + + rkisp1 = devm_kzalloc(dev, sizeof(*rkisp1), GFP_KERNEL); + if (!rkisp1) + return -ENOMEM; + + dev_set_drvdata(dev, rkisp1); + rkisp1->dev = dev; + + mutex_init(&rkisp1->stream_lock); + + rkisp1->base_addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(rkisp1->base_addr)) + return PTR_ERR(rkisp1->base_addr); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, rkisp1_isr, IRQF_SHARED, + dev_driver_string(dev), dev); + if (ret) { + dev_err(dev, "request irq failed: %d\n", ret); + return ret; + } + + rkisp1->irq = irq; + + for (i = 0; i < clk_data->size; i++) + rkisp1->clks[i].id = clk_data->clks[i]; + ret = devm_clk_bulk_get(dev, clk_data->size, rkisp1->clks); + if (ret) + return ret; + rkisp1->clk_size = clk_data->size; + + pm_runtime_enable(&pdev->dev); + + strscpy(rkisp1->media_dev.model, RKISP1_DRIVER_NAME, + sizeof(rkisp1->media_dev.model)); + rkisp1->media_dev.dev = &pdev->dev; + strscpy(rkisp1->media_dev.bus_info, RKISP1_BUS_INFO, + sizeof(rkisp1->media_dev.bus_info)); + media_device_init(&rkisp1->media_dev); + + v4l2_dev = &rkisp1->v4l2_dev; + v4l2_dev->mdev = &rkisp1->media_dev; + strscpy(v4l2_dev->name, RKISP1_DRIVER_NAME, sizeof(v4l2_dev->name)); + + ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev); + if (ret) + return ret; + + ret = media_device_register(&rkisp1->media_dev); + if (ret) { + dev_err(dev, "Failed to register media device: %d\n", ret); + goto err_unreg_v4l2_dev; + } + + ret = rkisp1_entities_register(rkisp1); + if (ret) + goto err_unreg_media_dev; + + rkisp1_debug_init(rkisp1); + + return 0; + +err_unreg_media_dev: + media_device_unregister(&rkisp1->media_dev); +err_unreg_v4l2_dev: + v4l2_device_unregister(&rkisp1->v4l2_dev); + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int rkisp1_remove(struct platform_device *pdev) +{ + struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev); + + v4l2_async_notifier_unregister(&rkisp1->notifier); + v4l2_async_notifier_cleanup(&rkisp1->notifier); + + rkisp1_params_unregister(rkisp1); + rkisp1_stats_unregister(rkisp1); + rkisp1_capture_devs_unregister(rkisp1); + rkisp1_resizer_devs_unregister(rkisp1); + rkisp1_isp_unregister(rkisp1); + + media_device_unregister(&rkisp1->media_dev); + v4l2_device_unregister(&rkisp1->v4l2_dev); + + pm_runtime_disable(&pdev->dev); + + debugfs_remove_recursive(rkisp1->debug.debugfs_dir); + return 0; +} + +static struct platform_driver rkisp1_drv = { + .driver = { + .name = RKISP1_DRIVER_NAME, + .of_match_table = of_match_ptr(rkisp1_of_match), + .pm = &rkisp1_pm_ops, + }, + .probe = rkisp1_probe, + .remove = rkisp1_remove, +}; + +module_platform_driver(rkisp1_drv); +MODULE_DESCRIPTION("Rockchip ISP1 platform driver"); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c new file mode 100644 index 000000000000..889982d8ca41 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c @@ -0,0 +1,1160 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - ISP Subdevice + * + * Copyright (C) 2019 Collabora, Ltd. + * + * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rkisp1-common.h" + +#define RKISP1_DEF_SINK_PAD_FMT MEDIA_BUS_FMT_SRGGB10_1X10 +#define RKISP1_DEF_SRC_PAD_FMT MEDIA_BUS_FMT_YUYV8_2X8 + +#define RKISP1_ISP_DEV_NAME RKISP1_DRIVER_NAME "_isp" + +/* + * NOTE: MIPI controller and input MUX are also configured in this file. + * This is because ISP Subdev describes not only ISP submodule (input size, + * format, output size, format), but also a virtual route device. + */ + +/* + * There are many variables named with format/frame in below code, + * please see here for their meaning. + * Cropping in the sink pad defines the image region from the sensor. + * Cropping in the source pad defines the region for the Image Stabilizer (IS) + * + * Cropping regions of ISP + * + * +---------------------------------------------------------+ + * | Sensor image | + * | +---------------------------------------------------+ | + * | | CIF_ISP_ACQ (for black level) | | + * | | sink pad format | | + * | | +--------------------------------------------+ | | + * | | | CIF_ISP_OUT | | | + * | | | sink pad crop | | | + * | | | +---------------------------------+ | | | + * | | | | CIF_ISP_IS | | | | + * | | | | source pad crop and format | | | | + * | | | +---------------------------------+ | | | + * | | +--------------------------------------------+ | | + * | +---------------------------------------------------+ | + * +---------------------------------------------------------+ + */ + +static const struct rkisp1_isp_mbus_info rkisp1_isp_formats[] = { + { + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, + .pixel_enc = V4L2_PIXEL_ENC_YUV, + .direction = RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, + .bayer_pat = RKISP1_RAW_RGGB, + .bus_width = 10, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, + .bayer_pat = RKISP1_RAW_BGGR, + .bus_width = 10, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, + .bayer_pat = RKISP1_RAW_GBRG, + .bus_width = 10, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, + .bayer_pat = RKISP1_RAW_GRBG, + .bus_width = 10, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, + .bayer_pat = RKISP1_RAW_RGGB, + .bus_width = 12, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, + .bayer_pat = RKISP1_RAW_BGGR, + .bus_width = 12, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, + .bayer_pat = RKISP1_RAW_GBRG, + .bus_width = 12, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, + .bayer_pat = RKISP1_RAW_GRBG, + .bus_width = 12, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, + .bayer_pat = RKISP1_RAW_RGGB, + .bus_width = 8, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, + .bayer_pat = RKISP1_RAW_BGGR, + .bus_width = 8, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, + .bayer_pat = RKISP1_RAW_GBRG, + .bus_width = 8, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, + .pixel_enc = V4L2_PIXEL_ENC_BAYER, + .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, + .bayer_pat = RKISP1_RAW_GRBG, + .bus_width = 8, + .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, + }, { + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, + .pixel_enc = V4L2_PIXEL_ENC_YUV, + .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, + .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_YCBYCR, + .bus_width = 16, + .direction = RKISP1_ISP_SD_SINK, + }, { + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, + .pixel_enc = V4L2_PIXEL_ENC_YUV, + .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, + .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_YCRYCB, + .bus_width = 16, + .direction = RKISP1_ISP_SD_SINK, + }, { + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, + .pixel_enc = V4L2_PIXEL_ENC_YUV, + .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, + .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_CBYCRY, + .bus_width = 16, + .direction = RKISP1_ISP_SD_SINK, + }, { + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, + .pixel_enc = V4L2_PIXEL_ENC_YUV, + .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, + .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_CRYCBY, + .bus_width = 16, + .direction = RKISP1_ISP_SD_SINK, + }, +}; + +/* ---------------------------------------------------------------------------- + * Helpers + */ + +const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(rkisp1_isp_formats); i++) { + const struct rkisp1_isp_mbus_info *fmt = &rkisp1_isp_formats[i]; + + if (fmt->mbus_code == mbus_code) + return fmt; + } + + return NULL; +} + +static struct v4l2_subdev *rkisp1_get_remote_sensor(struct v4l2_subdev *sd) +{ + struct media_pad *local, *remote; + struct media_entity *sensor_me; + + local = &sd->entity.pads[RKISP1_ISP_PAD_SINK_VIDEO]; + remote = media_entity_remote_pad(local); + if (!remote) + return NULL; + + sensor_me = remote->entity; + return media_entity_to_v4l2_subdev(sensor_me); +} + +static struct v4l2_mbus_framefmt * +rkisp1_isp_get_pad_fmt(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(&isp->sd, cfg, pad); + else + return v4l2_subdev_get_try_format(&isp->sd, isp->pad_cfg, pad); +} + +static struct v4l2_rect * +rkisp1_isp_get_pad_crop(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_crop(&isp->sd, cfg, pad); + else + return v4l2_subdev_get_try_crop(&isp->sd, isp->pad_cfg, pad); +} + +/* ---------------------------------------------------------------------------- + * Camera Interface registers configurations + */ + +/* + * Image Stabilization. + * This should only be called when configuring CIF + * or at the frame end interrupt + */ +static void rkisp1_config_ism(struct rkisp1_device *rkisp1) +{ + struct v4l2_rect *src_crop = + rkisp1_isp_get_pad_crop(&rkisp1->isp, NULL, + RKISP1_ISP_PAD_SOURCE_VIDEO, + V4L2_SUBDEV_FORMAT_ACTIVE); + u32 val; + + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_RECENTER); + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_MAX_DX); + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_MAX_DY); + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_DISPLACE); + rkisp1_write(rkisp1, src_crop->left, RKISP1_CIF_ISP_IS_H_OFFS); + rkisp1_write(rkisp1, src_crop->top, RKISP1_CIF_ISP_IS_V_OFFS); + rkisp1_write(rkisp1, src_crop->width, RKISP1_CIF_ISP_IS_H_SIZE); + rkisp1_write(rkisp1, src_crop->height, RKISP1_CIF_ISP_IS_V_SIZE); + + /* IS(Image Stabilization) is always on, working as output crop */ + rkisp1_write(rkisp1, 1, RKISP1_CIF_ISP_IS_CTRL); + val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); + val |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD; + rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); +} + +/* + * configure ISP blocks with input format, size...... + */ +static int rkisp1_config_isp(struct rkisp1_device *rkisp1) +{ + u32 isp_ctrl = 0, irq_mask = 0, acq_mult = 0, signal = 0; + const struct rkisp1_isp_mbus_info *src_fmt, *sink_fmt; + struct rkisp1_sensor_async *sensor; + struct v4l2_mbus_framefmt *sink_frm; + struct v4l2_rect *sink_crop; + + sensor = rkisp1->active_sensor; + sink_fmt = rkisp1->isp.sink_fmt; + src_fmt = rkisp1->isp.src_fmt; + sink_frm = rkisp1_isp_get_pad_fmt(&rkisp1->isp, NULL, + RKISP1_ISP_PAD_SINK_VIDEO, + V4L2_SUBDEV_FORMAT_ACTIVE); + sink_crop = rkisp1_isp_get_pad_crop(&rkisp1->isp, NULL, + RKISP1_ISP_PAD_SINK_VIDEO, + V4L2_SUBDEV_FORMAT_ACTIVE); + + if (sink_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { + acq_mult = 1; + if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { + if (sensor->mbus_type == V4L2_MBUS_BT656) + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656; + else + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT; + } else { + rkisp1_write(rkisp1, RKISP1_CIF_ISP_DEMOSAIC_TH(0xc), + RKISP1_CIF_ISP_DEMOSAIC); + + if (sensor->mbus_type == V4L2_MBUS_BT656) + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656; + else + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601; + } + } else if (sink_fmt->pixel_enc == V4L2_PIXEL_ENC_YUV) { + acq_mult = 2; + if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601; + } else { + if (sensor->mbus_type == V4L2_MBUS_BT656) + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU656; + else + isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601; + } + + irq_mask |= RKISP1_CIF_ISP_DATA_LOSS; + } + + /* Set up input acquisition properties */ + if (sensor->mbus_type == V4L2_MBUS_BT656 || + sensor->mbus_type == V4L2_MBUS_PARALLEL) { + if (sensor->mbus_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + signal = RKISP1_CIF_ISP_ACQ_PROP_POS_EDGE; + } + + if (sensor->mbus_type == V4L2_MBUS_PARALLEL) { + if (sensor->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + signal |= RKISP1_CIF_ISP_ACQ_PROP_VSYNC_LOW; + + if (sensor->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + signal |= RKISP1_CIF_ISP_ACQ_PROP_HSYNC_LOW; + } + + rkisp1_write(rkisp1, isp_ctrl, RKISP1_CIF_ISP_CTRL); + rkisp1_write(rkisp1, signal | sink_fmt->yuv_seq | + RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT(sink_fmt->bayer_pat) | + RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, + RKISP1_CIF_ISP_ACQ_PROP); + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_NR_FRAMES); + + /* Acquisition Size */ + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_H_OFFS); + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_V_OFFS); + rkisp1_write(rkisp1, + acq_mult * sink_frm->width, RKISP1_CIF_ISP_ACQ_H_SIZE); + rkisp1_write(rkisp1, sink_frm->height, RKISP1_CIF_ISP_ACQ_V_SIZE); + + /* ISP Out Area */ + rkisp1_write(rkisp1, sink_crop->left, RKISP1_CIF_ISP_OUT_H_OFFS); + rkisp1_write(rkisp1, sink_crop->top, RKISP1_CIF_ISP_OUT_V_OFFS); + rkisp1_write(rkisp1, sink_crop->width, RKISP1_CIF_ISP_OUT_H_SIZE); + rkisp1_write(rkisp1, sink_crop->height, RKISP1_CIF_ISP_OUT_V_SIZE); + + irq_mask |= RKISP1_CIF_ISP_FRAME | RKISP1_CIF_ISP_V_START | + RKISP1_CIF_ISP_PIC_SIZE_ERROR; + rkisp1_write(rkisp1, irq_mask, RKISP1_CIF_ISP_IMSC); + + if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { + rkisp1_params_disable(&rkisp1->params); + } else { + struct v4l2_mbus_framefmt *src_frm; + + src_frm = rkisp1_isp_get_pad_fmt(&rkisp1->isp, NULL, + RKISP1_ISP_PAD_SINK_VIDEO, + V4L2_SUBDEV_FORMAT_ACTIVE); + rkisp1_params_configure(&rkisp1->params, sink_fmt->bayer_pat, + src_frm->quantization); + } + + return 0; +} + +static int rkisp1_config_dvp(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_isp_mbus_info *sink_fmt = rkisp1->isp.sink_fmt; + u32 val, input_sel; + + switch (sink_fmt->bus_width) { + case 8: + input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO; + break; + case 10: + input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO; + break; + case 12: + input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_12B; + break; + default: + dev_err(rkisp1->dev, "Invalid bus width\n"); + return -EINVAL; + } + + val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ACQ_PROP); + rkisp1_write(rkisp1, val | input_sel, RKISP1_CIF_ISP_ACQ_PROP); + + return 0; +} + +static int rkisp1_config_mipi(struct rkisp1_device *rkisp1) +{ + const struct rkisp1_isp_mbus_info *sink_fmt = rkisp1->isp.sink_fmt; + unsigned int lanes = rkisp1->active_sensor->lanes; + u32 mipi_ctrl; + + if (lanes < 1 || lanes > 4) + return -EINVAL; + + mipi_ctrl = RKISP1_CIF_MIPI_CTRL_NUM_LANES(lanes - 1) | + RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) | + RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP | + RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA; + + rkisp1_write(rkisp1, mipi_ctrl, RKISP1_CIF_MIPI_CTRL); + + /* Configure Data Type and Virtual Channel */ + rkisp1_write(rkisp1, + RKISP1_CIF_MIPI_DATA_SEL_DT(sink_fmt->mipi_dt) | + RKISP1_CIF_MIPI_DATA_SEL_VC(0), + RKISP1_CIF_MIPI_IMG_DATA_SEL); + + /* Clear MIPI interrupts */ + rkisp1_write(rkisp1, ~0, RKISP1_CIF_MIPI_ICR); + /* + * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for + * isp bus may be dead when switch isp. + */ + rkisp1_write(rkisp1, + RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI | + RKISP1_CIF_MIPI_ERR_DPHY | + RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | + RKISP1_CIF_MIPI_ADD_DATA_OVFLW, + RKISP1_CIF_MIPI_IMSC); + + dev_dbg(rkisp1->dev, "\n MIPI_CTRL 0x%08x\n" + " MIPI_IMG_DATA_SEL 0x%08x\n" + " MIPI_STATUS 0x%08x\n" + " MIPI_IMSC 0x%08x\n", + rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL), + rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL), + rkisp1_read(rkisp1, RKISP1_CIF_MIPI_STATUS), + rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC)); + + return 0; +} + +/* Configure MUX */ +static int rkisp1_config_path(struct rkisp1_device *rkisp1) +{ + struct rkisp1_sensor_async *sensor = rkisp1->active_sensor; + u32 dpcl = rkisp1_read(rkisp1, RKISP1_CIF_VI_DPCL); + int ret = 0; + + if (sensor->mbus_type == V4L2_MBUS_BT656 || + sensor->mbus_type == V4L2_MBUS_PARALLEL) { + ret = rkisp1_config_dvp(rkisp1); + dpcl |= RKISP1_CIF_VI_DPCL_IF_SEL_PARALLEL; + } else if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { + ret = rkisp1_config_mipi(rkisp1); + dpcl |= RKISP1_CIF_VI_DPCL_IF_SEL_MIPI; + } + + rkisp1_write(rkisp1, dpcl, RKISP1_CIF_VI_DPCL); + + return ret; +} + +/* Hardware configure Entry */ +static int rkisp1_config_cif(struct rkisp1_device *rkisp1) +{ + u32 cif_id; + int ret; + + cif_id = rkisp1_read(rkisp1, RKISP1_CIF_VI_ID); + dev_dbg(rkisp1->dev, "CIF_ID 0x%08x\n", cif_id); + + ret = rkisp1_config_isp(rkisp1); + if (ret) + return ret; + ret = rkisp1_config_path(rkisp1); + if (ret) + return ret; + rkisp1_config_ism(rkisp1); + + return 0; +} + +static void rkisp1_isp_stop(struct rkisp1_device *rkisp1) +{ + u32 val; + + /* + * ISP(mi) stop in mi frame end -> Stop ISP(mipi) -> + * Stop ISP(isp) ->wait for ISP isp off + */ + /* stop and clear MI, MIPI, and ISP interrupts */ + rkisp1_write(rkisp1, 0, RKISP1_CIF_MIPI_IMSC); + rkisp1_write(rkisp1, ~0, RKISP1_CIF_MIPI_ICR); + + rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IMSC); + rkisp1_write(rkisp1, ~0, RKISP1_CIF_ISP_ICR); + + rkisp1_write(rkisp1, 0, RKISP1_CIF_MI_IMSC); + rkisp1_write(rkisp1, ~0, RKISP1_CIF_MI_ICR); + val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); + rkisp1_write(rkisp1, val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA), + RKISP1_CIF_MIPI_CTRL); + /* stop ISP */ + val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); + val &= ~(RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE | + RKISP1_CIF_ISP_CTRL_ISP_ENABLE); + rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); + + val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); + rkisp1_write(rkisp1, val | RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD, + RKISP1_CIF_ISP_CTRL); + + readx_poll_timeout(readl, rkisp1->base_addr + RKISP1_CIF_ISP_RIS, + val, val & RKISP1_CIF_ISP_OFF, 20, 100); + rkisp1_write(rkisp1, + RKISP1_CIF_IRCL_MIPI_SW_RST | RKISP1_CIF_IRCL_ISP_SW_RST, + RKISP1_CIF_IRCL); + rkisp1_write(rkisp1, 0x0, RKISP1_CIF_IRCL); +} + +static void rkisp1_config_clk(struct rkisp1_device *rkisp1) +{ + u32 val = RKISP1_CIF_ICCL_ISP_CLK | RKISP1_CIF_ICCL_CP_CLK | + RKISP1_CIF_ICCL_MRSZ_CLK | RKISP1_CIF_ICCL_SRSZ_CLK | + RKISP1_CIF_ICCL_JPEG_CLK | RKISP1_CIF_ICCL_MI_CLK | + RKISP1_CIF_ICCL_IE_CLK | RKISP1_CIF_ICCL_MIPI_CLK | + RKISP1_CIF_ICCL_DCROP_CLK; + + rkisp1_write(rkisp1, val, RKISP1_CIF_ICCL); +} + +static void rkisp1_isp_start(struct rkisp1_device *rkisp1) +{ + struct rkisp1_sensor_async *sensor = rkisp1->active_sensor; + u32 val; + + rkisp1_config_clk(rkisp1); + + /* Activate MIPI */ + if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { + val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); + rkisp1_write(rkisp1, val | RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA, + RKISP1_CIF_MIPI_CTRL); + } + /* Activate ISP */ + val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); + val |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD | + RKISP1_CIF_ISP_CTRL_ISP_ENABLE | + RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE; + rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); + + /* + * CIF spec says to wait for sufficient time after enabling + * the MIPI interface and before starting the sensor output. + */ + usleep_range(1000, 1200); +} + +/* ---------------------------------------------------------------------------- + * Subdev pad operations + */ + +static int rkisp1_isp_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + unsigned int i, dir; + int pos = 0; + + if (code->pad == RKISP1_ISP_PAD_SINK_VIDEO) { + dir = RKISP1_ISP_SD_SINK; + } else if (code->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) { + dir = RKISP1_ISP_SD_SRC; + } else { + if (code->index > 0) + return -EINVAL; + code->code = MEDIA_BUS_FMT_METADATA_FIXED; + return 0; + } + + if (code->index >= ARRAY_SIZE(rkisp1_isp_formats)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(rkisp1_isp_formats); i++) { + const struct rkisp1_isp_mbus_info *fmt = &rkisp1_isp_formats[i]; + + if (fmt->direction & dir) + pos++; + + if (code->index == pos - 1) { + code->code = fmt->mbus_code; + if (fmt->pixel_enc == V4L2_PIXEL_ENC_YUV && + dir == RKISP1_ISP_SD_SRC) + code->flags = + V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION; + return 0; + } + } + + return -EINVAL; +} + +static int rkisp1_isp_init_config(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg) +{ + struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; + struct v4l2_rect *sink_crop, *src_crop; + + sink_fmt = v4l2_subdev_get_try_format(sd, cfg, + RKISP1_ISP_PAD_SINK_VIDEO); + sink_fmt->width = RKISP1_DEFAULT_WIDTH; + sink_fmt->height = RKISP1_DEFAULT_HEIGHT; + sink_fmt->field = V4L2_FIELD_NONE; + sink_fmt->code = RKISP1_DEF_SINK_PAD_FMT; + + sink_crop = v4l2_subdev_get_try_crop(sd, cfg, + RKISP1_ISP_PAD_SINK_VIDEO); + sink_crop->width = RKISP1_DEFAULT_WIDTH; + sink_crop->height = RKISP1_DEFAULT_HEIGHT; + sink_crop->left = 0; + sink_crop->top = 0; + + src_fmt = v4l2_subdev_get_try_format(sd, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO); + *src_fmt = *sink_fmt; + src_fmt->code = RKISP1_DEF_SRC_PAD_FMT; + + src_crop = v4l2_subdev_get_try_crop(sd, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO); + *src_crop = *sink_crop; + + sink_fmt = v4l2_subdev_get_try_format(sd, cfg, + RKISP1_ISP_PAD_SINK_PARAMS); + src_fmt = v4l2_subdev_get_try_format(sd, cfg, + RKISP1_ISP_PAD_SOURCE_STATS); + sink_fmt->width = 0; + sink_fmt->height = 0; + sink_fmt->field = V4L2_FIELD_NONE; + sink_fmt->code = MEDIA_BUS_FMT_METADATA_FIXED; + *src_fmt = *sink_fmt; + + return 0; +} + +static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_mbus_framefmt *format, + unsigned int which) +{ + const struct rkisp1_isp_mbus_info *mbus_info; + struct v4l2_mbus_framefmt *src_fmt; + const struct v4l2_rect *src_crop; + + src_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO, which); + src_crop = rkisp1_isp_get_pad_crop(isp, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO, which); + + src_fmt->code = format->code; + mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); + if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) { + src_fmt->code = RKISP1_DEF_SRC_PAD_FMT; + mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); + } + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) + isp->src_fmt = mbus_info; + src_fmt->width = src_crop->width; + src_fmt->height = src_crop->height; + + /* + * The CSC API is used to allow userspace to force full + * quantization on YUV formats. + */ + if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC && + format->quantization == V4L2_QUANTIZATION_FULL_RANGE && + mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV) + src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; + else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV) + src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; + else + src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; + + *format = *src_fmt; +} + +static void rkisp1_isp_set_src_crop(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_rect *r, unsigned int which) +{ + struct v4l2_mbus_framefmt *src_fmt; + const struct v4l2_rect *sink_crop; + struct v4l2_rect *src_crop; + + src_crop = rkisp1_isp_get_pad_crop(isp, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO, + which); + sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, + RKISP1_ISP_PAD_SINK_VIDEO, + which); + + src_crop->left = ALIGN(r->left, 2); + src_crop->width = ALIGN(r->width, 2); + src_crop->top = r->top; + src_crop->height = r->height; + rkisp1_sd_adjust_crop_rect(src_crop, sink_crop); + + *r = *src_crop; + + /* Propagate to out format */ + src_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO, which); + rkisp1_isp_set_src_fmt(isp, cfg, src_fmt, which); +} + +static void rkisp1_isp_set_sink_crop(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_rect *r, unsigned int which) +{ + struct v4l2_rect *sink_crop, *src_crop; + struct v4l2_mbus_framefmt *sink_fmt; + + sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, + which); + sink_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, + which); + + sink_crop->left = ALIGN(r->left, 2); + sink_crop->width = ALIGN(r->width, 2); + sink_crop->top = r->top; + sink_crop->height = r->height; + rkisp1_sd_adjust_crop(sink_crop, sink_fmt); + + *r = *sink_crop; + + /* Propagate to out crop */ + src_crop = rkisp1_isp_get_pad_crop(isp, cfg, + RKISP1_ISP_PAD_SOURCE_VIDEO, which); + rkisp1_isp_set_src_crop(isp, cfg, src_crop, which); +} + +static void rkisp1_isp_set_sink_fmt(struct rkisp1_isp *isp, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_mbus_framefmt *format, + unsigned int which) +{ + const struct rkisp1_isp_mbus_info *mbus_info; + struct v4l2_mbus_framefmt *sink_fmt; + struct v4l2_rect *sink_crop; + + sink_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, + which); + sink_fmt->code = format->code; + mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); + if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SINK)) { + sink_fmt->code = RKISP1_DEF_SINK_PAD_FMT; + mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); + } + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) + isp->sink_fmt = mbus_info; + + sink_fmt->width = clamp_t(u32, format->width, + RKISP1_ISP_MIN_WIDTH, + RKISP1_ISP_MAX_WIDTH); + sink_fmt->height = clamp_t(u32, format->height, + RKISP1_ISP_MIN_HEIGHT, + RKISP1_ISP_MAX_HEIGHT); + + *format = *sink_fmt; + + /* Propagate to in crop */ + sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, + which); + rkisp1_isp_set_sink_crop(isp, cfg, sink_crop, which); +} + +static int rkisp1_isp_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); + + mutex_lock(&isp->ops_lock); + fmt->format = *rkisp1_isp_get_pad_fmt(isp, cfg, fmt->pad, fmt->which); + mutex_unlock(&isp->ops_lock); + return 0; +} + +static int rkisp1_isp_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); + + mutex_lock(&isp->ops_lock); + if (fmt->pad == RKISP1_ISP_PAD_SINK_VIDEO) + rkisp1_isp_set_sink_fmt(isp, cfg, &fmt->format, fmt->which); + else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) + rkisp1_isp_set_src_fmt(isp, cfg, &fmt->format, fmt->which); + else + fmt->format = *rkisp1_isp_get_pad_fmt(isp, cfg, fmt->pad, + fmt->which); + + mutex_unlock(&isp->ops_lock); + return 0; +} + +static int rkisp1_isp_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); + int ret = 0; + + if (sel->pad != RKISP1_ISP_PAD_SOURCE_VIDEO && + sel->pad != RKISP1_ISP_PAD_SINK_VIDEO) + return -EINVAL; + + mutex_lock(&isp->ops_lock); + switch (sel->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + if (sel->pad == RKISP1_ISP_PAD_SINK_VIDEO) { + struct v4l2_mbus_framefmt *fmt; + + fmt = rkisp1_isp_get_pad_fmt(isp, cfg, sel->pad, + sel->which); + sel->r.height = fmt->height; + sel->r.width = fmt->width; + sel->r.left = 0; + sel->r.top = 0; + } else { + sel->r = *rkisp1_isp_get_pad_crop(isp, cfg, + RKISP1_ISP_PAD_SINK_VIDEO, + sel->which); + } + break; + case V4L2_SEL_TGT_CROP: + sel->r = *rkisp1_isp_get_pad_crop(isp, cfg, sel->pad, + sel->which); + break; + default: + ret = -EINVAL; + } + mutex_unlock(&isp->ops_lock); + return ret; +} + +static int rkisp1_isp_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct rkisp1_device *rkisp1 = + container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev); + struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); + int ret = 0; + + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + dev_dbg(rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, + sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); + mutex_lock(&isp->ops_lock); + if (sel->pad == RKISP1_ISP_PAD_SINK_VIDEO) + rkisp1_isp_set_sink_crop(isp, cfg, &sel->r, sel->which); + else if (sel->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) + rkisp1_isp_set_src_crop(isp, cfg, &sel->r, sel->which); + else + ret = -EINVAL; + + mutex_unlock(&isp->ops_lock); + return ret; +} + +static int rkisp1_subdev_link_validate(struct media_link *link) +{ + if (link->sink->index == RKISP1_ISP_PAD_SINK_PARAMS) + return 0; + + return v4l2_subdev_link_validate(link); +} + +static const struct v4l2_subdev_pad_ops rkisp1_isp_pad_ops = { + .enum_mbus_code = rkisp1_isp_enum_mbus_code, + .get_selection = rkisp1_isp_get_selection, + .set_selection = rkisp1_isp_set_selection, + .init_cfg = rkisp1_isp_init_config, + .get_fmt = rkisp1_isp_get_fmt, + .set_fmt = rkisp1_isp_set_fmt, + .link_validate = v4l2_subdev_link_validate_default, +}; + +/* ---------------------------------------------------------------------------- + * Stream operations + */ + +static int rkisp1_mipi_csi2_start(struct rkisp1_isp *isp, + struct rkisp1_sensor_async *sensor) +{ + struct rkisp1_device *rkisp1 = + container_of(isp->sd.v4l2_dev, struct rkisp1_device, v4l2_dev); + union phy_configure_opts opts; + struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; + s64 pixel_clock; + + if (!sensor->pixel_rate_ctrl) { + dev_warn(rkisp1->dev, "No pixel rate control in sensor subdev\n"); + return -EPIPE; + } + + pixel_clock = v4l2_ctrl_g_ctrl_int64(sensor->pixel_rate_ctrl); + if (!pixel_clock) { + dev_err(rkisp1->dev, "Invalid pixel rate value\n"); + return -EINVAL; + } + + phy_mipi_dphy_get_default_config(pixel_clock, isp->sink_fmt->bus_width, + sensor->lanes, cfg); + phy_set_mode(sensor->dphy, PHY_MODE_MIPI_DPHY); + phy_configure(sensor->dphy, &opts); + phy_power_on(sensor->dphy); + + return 0; +} + +static void rkisp1_mipi_csi2_stop(struct rkisp1_sensor_async *sensor) +{ + phy_power_off(sensor->dphy); +} + +static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct rkisp1_device *rkisp1 = + container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev); + struct rkisp1_isp *isp = &rkisp1->isp; + struct v4l2_subdev *sensor_sd; + int ret = 0; + + if (!enable) { + rkisp1_isp_stop(rkisp1); + rkisp1_mipi_csi2_stop(rkisp1->active_sensor); + return 0; + } + + sensor_sd = rkisp1_get_remote_sensor(sd); + if (!sensor_sd) { + dev_warn(rkisp1->dev, "No link between isp and sensor\n"); + return -ENODEV; + } + + rkisp1->active_sensor = container_of(sensor_sd->asd, + struct rkisp1_sensor_async, asd); + + if (rkisp1->active_sensor->mbus_type != V4L2_MBUS_CSI2_DPHY) + return -EINVAL; + + rkisp1->isp.frame_sequence = -1; + mutex_lock(&isp->ops_lock); + ret = rkisp1_config_cif(rkisp1); + if (ret) + goto mutex_unlock; + + ret = rkisp1_mipi_csi2_start(&rkisp1->isp, rkisp1->active_sensor); + if (ret) + goto mutex_unlock; + + rkisp1_isp_start(rkisp1); + +mutex_unlock: + mutex_unlock(&isp->ops_lock); + return ret; +} + +static int rkisp1_isp_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +{ + if (sub->type != V4L2_EVENT_FRAME_SYNC) + return -EINVAL; + + /* V4L2_EVENT_FRAME_SYNC doesn't require an id, so zero should be set */ + if (sub->id != 0) + return -EINVAL; + + return v4l2_event_subscribe(fh, sub, 0, NULL); +} + +static const struct media_entity_operations rkisp1_isp_media_ops = { + .link_validate = rkisp1_subdev_link_validate, +}; + +static const struct v4l2_subdev_video_ops rkisp1_isp_video_ops = { + .s_stream = rkisp1_isp_s_stream, +}; + +static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = { + .subscribe_event = rkisp1_isp_subs_evt, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_ops rkisp1_isp_ops = { + .core = &rkisp1_isp_core_ops, + .video = &rkisp1_isp_video_ops, + .pad = &rkisp1_isp_pad_ops, +}; + +int rkisp1_isp_register(struct rkisp1_device *rkisp1) +{ + struct rkisp1_isp *isp = &rkisp1->isp; + struct media_pad *pads = isp->pads; + struct v4l2_subdev *sd = &isp->sd; + int ret; + + v4l2_subdev_init(sd, &rkisp1_isp_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + sd->entity.ops = &rkisp1_isp_media_ops; + sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; + sd->owner = THIS_MODULE; + strscpy(sd->name, RKISP1_ISP_DEV_NAME, sizeof(sd->name)); + + pads[RKISP1_ISP_PAD_SINK_VIDEO].flags = MEDIA_PAD_FL_SINK | + MEDIA_PAD_FL_MUST_CONNECT; + pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK; + pads[RKISP1_ISP_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; + pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE; + + isp->sink_fmt = rkisp1_isp_mbus_info_get(RKISP1_DEF_SINK_PAD_FMT); + isp->src_fmt = rkisp1_isp_mbus_info_get(RKISP1_DEF_SRC_PAD_FMT); + + mutex_init(&isp->ops_lock); + ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX, pads); + if (ret) + return ret; + + ret = v4l2_device_register_subdev(&rkisp1->v4l2_dev, sd); + if (ret) { + dev_err(rkisp1->dev, "Failed to register isp subdev\n"); + goto err_cleanup_media_entity; + } + + rkisp1_isp_init_config(sd, rkisp1->isp.pad_cfg); + return 0; + +err_cleanup_media_entity: + media_entity_cleanup(&sd->entity); + + return ret; +} + +void rkisp1_isp_unregister(struct rkisp1_device *rkisp1) +{ + struct v4l2_subdev *sd = &rkisp1->isp.sd; + + v4l2_device_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); +} + +/* ---------------------------------------------------------------------------- + * Interrupt handlers + */ + +void rkisp1_mipi_isr(struct rkisp1_device *rkisp1) +{ + u32 val, status; + + status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS); + if (!status) + return; + + rkisp1_write(rkisp1, status, RKISP1_CIF_MIPI_ICR); + + /* + * Disable DPHY errctrl interrupt, because this dphy + * erctrl signal is asserted until the next changes + * of line state. This time is may be too long and cpu + * is hold in this interrupt. + */ + if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) { + val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); + rkisp1_write(rkisp1, val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f), + RKISP1_CIF_MIPI_IMSC); + rkisp1->isp.is_dphy_errctrl_disabled = true; + } + + /* + * Enable DPHY errctrl interrupt again, if mipi have receive + * the whole frame without any error. + */ + if (status == RKISP1_CIF_MIPI_FRAME_END) { + /* + * Enable DPHY errctrl interrupt again, if mipi have receive + * the whole frame without any error. + */ + if (rkisp1->isp.is_dphy_errctrl_disabled) { + val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); + val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f); + rkisp1_write(rkisp1, val, RKISP1_CIF_MIPI_IMSC); + rkisp1->isp.is_dphy_errctrl_disabled = false; + } + } else { + rkisp1->debug.mipi_error++; + } +} + +static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp) +{ + struct v4l2_event event = { + .type = V4L2_EVENT_FRAME_SYNC, + }; + event.u.frame_sync.frame_sequence = isp->frame_sequence; + + v4l2_event_queue(isp->sd.devnode, &event); +} + +void rkisp1_isp_isr(struct rkisp1_device *rkisp1) +{ + u32 status, isp_err; + + status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); + if (!status) + return; + + rkisp1_write(rkisp1, status, RKISP1_CIF_ISP_ICR); + + /* Vertical sync signal, starting generating new frame */ + if (status & RKISP1_CIF_ISP_V_START) { + rkisp1->isp.frame_sequence++; + rkisp1_isp_queue_event_sof(&rkisp1->isp); + if (status & RKISP1_CIF_ISP_FRAME) { + WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n"); + rkisp1->debug.irq_delay++; + } + } + if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) { + /* Clear pic_size_error */ + isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR); + if (isp_err & RKISP1_CIF_ISP_ERR_INFORM_SIZE) + rkisp1->debug.inform_size_error++; + if (isp_err & RKISP1_CIF_ISP_ERR_IS_SIZE) + rkisp1->debug.img_stabilization_size_error++; + if (isp_err & RKISP1_CIF_ISP_ERR_OUTFORM_SIZE) + rkisp1->debug.outform_size_error++; + rkisp1_write(rkisp1, isp_err, RKISP1_CIF_ISP_ERR_CLR); + } else if (status & RKISP1_CIF_ISP_DATA_LOSS) { + /* keep track of data_loss in debugfs */ + rkisp1->debug.data_loss++; + } + + if (status & RKISP1_CIF_ISP_FRAME) { + u32 isp_ris; + + /* New frame from the sensor received */ + isp_ris = rkisp1_read(rkisp1, RKISP1_CIF_ISP_RIS); + if (isp_ris & RKISP1_STATS_MEAS_MASK) + rkisp1_stats_isr(&rkisp1->stats, isp_ris); + /* + * Then update changed configs. Some of them involve + * lot of register writes. Do those only one per frame. + * Do the updates in the order of the processing flow. + */ + rkisp1_params_isr(rkisp1); + } +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c new file mode 100644 index 000000000000..03f9a81df440 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c @@ -0,0 +1,1572 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - Params subdevice + * + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include /* for ISP params */ + +#include "rkisp1-common.h" + +#define RKISP1_PARAMS_DEV_NAME RKISP1_DRIVER_NAME "_params" + +#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2 +#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8 + +#define RKISP1_ISP_DPCC_LINE_THRESH(n) \ + (RKISP1_CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n)) +#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) \ + (RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n)) +#define RKISP1_ISP_DPCC_PG_FAC(n) \ + (RKISP1_CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n)) +#define RKISP1_ISP_DPCC_RND_THRESH(n) \ + (RKISP1_CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n)) +#define RKISP1_ISP_DPCC_RG_FAC(n) \ + (RKISP1_CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n)) +#define RKISP1_ISP_CC_COEFF(n) \ + (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4) + +static inline void +rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) +{ + u32 val; + + val = rkisp1_read(params->rkisp1, reg); + rkisp1_write(params->rkisp1, val | bit_mask, reg); +} + +static inline void +rkisp1_param_clear_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) +{ + u32 val; + + val = rkisp1_read(params->rkisp1, reg); + rkisp1_write(params->rkisp1, val & ~bit_mask, reg); +} + +/* ISP BP interface function */ +static void rkisp1_dpcc_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_dpcc_config *arg) +{ + unsigned int i; + u32 mode; + + /* avoid to override the old enable value */ + mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DPCC_MODE); + mode &= RKISP1_CIF_ISP_DPCC_ENA; + mode |= arg->mode & ~RKISP1_CIF_ISP_DPCC_ENA; + rkisp1_write(params->rkisp1, mode, RKISP1_CIF_ISP_DPCC_MODE); + rkisp1_write(params->rkisp1, arg->output_mode, + RKISP1_CIF_ISP_DPCC_OUTPUT_MODE); + rkisp1_write(params->rkisp1, arg->set_use, + RKISP1_CIF_ISP_DPCC_SET_USE); + + rkisp1_write(params->rkisp1, arg->methods[0].method, + RKISP1_CIF_ISP_DPCC_METHODS_SET_1); + rkisp1_write(params->rkisp1, arg->methods[1].method, + RKISP1_CIF_ISP_DPCC_METHODS_SET_2); + rkisp1_write(params->rkisp1, arg->methods[2].method, + RKISP1_CIF_ISP_DPCC_METHODS_SET_3); + for (i = 0; i < RKISP1_CIF_ISP_DPCC_METHODS_MAX; i++) { + rkisp1_write(params->rkisp1, arg->methods[i].line_thresh, + RKISP1_ISP_DPCC_LINE_THRESH(i)); + rkisp1_write(params->rkisp1, arg->methods[i].line_mad_fac, + RKISP1_ISP_DPCC_LINE_MAD_FAC(i)); + rkisp1_write(params->rkisp1, arg->methods[i].pg_fac, + RKISP1_ISP_DPCC_PG_FAC(i)); + rkisp1_write(params->rkisp1, arg->methods[i].rnd_thresh, + RKISP1_ISP_DPCC_RND_THRESH(i)); + rkisp1_write(params->rkisp1, arg->methods[i].rg_fac, + RKISP1_ISP_DPCC_RG_FAC(i)); + } + + rkisp1_write(params->rkisp1, arg->rnd_offs, + RKISP1_CIF_ISP_DPCC_RND_OFFS); + rkisp1_write(params->rkisp1, arg->ro_limits, + RKISP1_CIF_ISP_DPCC_RO_LIMITS); +} + +/* ISP black level subtraction interface function */ +static void rkisp1_bls_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_bls_config *arg) +{ + /* avoid to override the old enable value */ + u32 new_control; + + new_control = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_BLS_CTRL); + new_control &= RKISP1_CIF_ISP_BLS_ENA; + /* fixed subtraction values */ + if (!arg->enable_auto) { + const struct rkisp1_cif_isp_bls_fixed_val *pval = + &arg->fixed_val; + + switch (params->raw_type) { + case RKISP1_RAW_BGGR: + rkisp1_write(params->rkisp1, + pval->r, RKISP1_CIF_ISP_BLS_D_FIXED); + rkisp1_write(params->rkisp1, + pval->gr, RKISP1_CIF_ISP_BLS_C_FIXED); + rkisp1_write(params->rkisp1, + pval->gb, RKISP1_CIF_ISP_BLS_B_FIXED); + rkisp1_write(params->rkisp1, + pval->b, RKISP1_CIF_ISP_BLS_A_FIXED); + break; + case RKISP1_RAW_GBRG: + rkisp1_write(params->rkisp1, + pval->r, RKISP1_CIF_ISP_BLS_C_FIXED); + rkisp1_write(params->rkisp1, + pval->gr, RKISP1_CIF_ISP_BLS_D_FIXED); + rkisp1_write(params->rkisp1, + pval->gb, RKISP1_CIF_ISP_BLS_A_FIXED); + rkisp1_write(params->rkisp1, + pval->b, RKISP1_CIF_ISP_BLS_B_FIXED); + break; + case RKISP1_RAW_GRBG: + rkisp1_write(params->rkisp1, + pval->r, RKISP1_CIF_ISP_BLS_B_FIXED); + rkisp1_write(params->rkisp1, + pval->gr, RKISP1_CIF_ISP_BLS_A_FIXED); + rkisp1_write(params->rkisp1, + pval->gb, RKISP1_CIF_ISP_BLS_D_FIXED); + rkisp1_write(params->rkisp1, + pval->b, RKISP1_CIF_ISP_BLS_C_FIXED); + break; + case RKISP1_RAW_RGGB: + rkisp1_write(params->rkisp1, + pval->r, RKISP1_CIF_ISP_BLS_A_FIXED); + rkisp1_write(params->rkisp1, + pval->gr, RKISP1_CIF_ISP_BLS_B_FIXED); + rkisp1_write(params->rkisp1, + pval->gb, RKISP1_CIF_ISP_BLS_C_FIXED); + rkisp1_write(params->rkisp1, + pval->b, RKISP1_CIF_ISP_BLS_D_FIXED); + break; + default: + break; + } + + } else { + if (arg->en_windows & BIT(1)) { + rkisp1_write(params->rkisp1, arg->bls_window2.h_offs, + RKISP1_CIF_ISP_BLS_H2_START); + rkisp1_write(params->rkisp1, arg->bls_window2.h_size, + RKISP1_CIF_ISP_BLS_H2_STOP); + rkisp1_write(params->rkisp1, arg->bls_window2.v_offs, + RKISP1_CIF_ISP_BLS_V2_START); + rkisp1_write(params->rkisp1, arg->bls_window2.v_size, + RKISP1_CIF_ISP_BLS_V2_STOP); + new_control |= RKISP1_CIF_ISP_BLS_WINDOW_2; + } + + if (arg->en_windows & BIT(0)) { + rkisp1_write(params->rkisp1, arg->bls_window1.h_offs, + RKISP1_CIF_ISP_BLS_H1_START); + rkisp1_write(params->rkisp1, arg->bls_window1.h_size, + RKISP1_CIF_ISP_BLS_H1_STOP); + rkisp1_write(params->rkisp1, arg->bls_window1.v_offs, + RKISP1_CIF_ISP_BLS_V1_START); + rkisp1_write(params->rkisp1, arg->bls_window1.v_size, + RKISP1_CIF_ISP_BLS_V1_STOP); + new_control |= RKISP1_CIF_ISP_BLS_WINDOW_1; + } + + rkisp1_write(params->rkisp1, arg->bls_samples, + RKISP1_CIF_ISP_BLS_SAMPLES); + + new_control |= RKISP1_CIF_ISP_BLS_MODE_MEASURED; + } + rkisp1_write(params->rkisp1, new_control, RKISP1_CIF_ISP_BLS_CTRL); +} + +/* ISP LS correction interface function */ +static void +rkisp1_lsc_correct_matrix_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_lsc_config *pconfig) +{ + unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel, i, j, data; + + isp_lsc_status = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_LSC_STATUS); + + /* RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */ + sram_addr = (isp_lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE) ? + RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 : + RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153; + rkisp1_write(params->rkisp1, sram_addr, + RKISP1_CIF_ISP_LSC_R_TABLE_ADDR); + rkisp1_write(params->rkisp1, sram_addr, + RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR); + rkisp1_write(params->rkisp1, sram_addr, + RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR); + rkisp1_write(params->rkisp1, sram_addr, + RKISP1_CIF_ISP_LSC_B_TABLE_ADDR); + + /* program data tables (table size is 9 * 17 = 153) */ + for (i = 0; i < RKISP1_CIF_ISP_LSC_SAMPLES_MAX; i++) { + /* + * 17 sectors with 2 values in one DWORD = 9 + * DWORDs (2nd value of last DWORD unused) + */ + for (j = 0; j < RKISP1_CIF_ISP_LSC_SAMPLES_MAX - 1; j += 2) { + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j], + pconfig->r_data_tbl[i][j + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_R_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j], + pconfig->gr_data_tbl[i][j + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_GR_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j], + pconfig->gb_data_tbl[i][j + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_GB_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j], + pconfig->b_data_tbl[i][j + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_B_TABLE_DATA); + } + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j], 0); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_R_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j], 0); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_GR_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j], 0); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_GB_TABLE_DATA); + + data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j], 0); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_B_TABLE_DATA); + } + isp_lsc_table_sel = (isp_lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE) ? + RKISP1_CIF_ISP_LSC_TABLE_0 : + RKISP1_CIF_ISP_LSC_TABLE_1; + rkisp1_write(params->rkisp1, isp_lsc_table_sel, + RKISP1_CIF_ISP_LSC_TABLE_SEL); +} + +static void rkisp1_lsc_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_lsc_config *arg) +{ + unsigned int i, data; + u32 lsc_ctrl; + + /* To config must be off , store the current status firstly */ + lsc_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_LSC_CTRL); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + rkisp1_lsc_correct_matrix_config(params, arg); + + for (i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE / 2; i++) { + /* program x size tables */ + data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2], + arg->x_size_tbl[i * 2 + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_XSIZE_01 + i * 4); + + /* program x grad tables */ + data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2], + arg->x_grad_tbl[i * 2 + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_XGRAD_01 + i * 4); + + /* program y size tables */ + data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2], + arg->y_size_tbl[i * 2 + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_YSIZE_01 + i * 4); + + /* program y grad tables */ + data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2], + arg->y_grad_tbl[i * 2 + 1]); + rkisp1_write(params->rkisp1, data, + RKISP1_CIF_ISP_LSC_YGRAD_01 + i * 4); + } + + /* restore the lsc ctrl status */ + if (lsc_ctrl & RKISP1_CIF_ISP_LSC_CTRL_ENA) { + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + } else { + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + } +} + +/* ISP Filtering function */ +static void rkisp1_flt_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_flt_config *arg) +{ + u32 filt_mode; + + rkisp1_write(params->rkisp1, + arg->thresh_bl0, RKISP1_CIF_ISP_FILT_THRESH_BL0); + rkisp1_write(params->rkisp1, + arg->thresh_bl1, RKISP1_CIF_ISP_FILT_THRESH_BL1); + rkisp1_write(params->rkisp1, + arg->thresh_sh0, RKISP1_CIF_ISP_FILT_THRESH_SH0); + rkisp1_write(params->rkisp1, + arg->thresh_sh1, RKISP1_CIF_ISP_FILT_THRESH_SH1); + rkisp1_write(params->rkisp1, arg->fac_bl0, RKISP1_CIF_ISP_FILT_FAC_BL0); + rkisp1_write(params->rkisp1, arg->fac_bl1, RKISP1_CIF_ISP_FILT_FAC_BL1); + rkisp1_write(params->rkisp1, arg->fac_mid, RKISP1_CIF_ISP_FILT_FAC_MID); + rkisp1_write(params->rkisp1, arg->fac_sh0, RKISP1_CIF_ISP_FILT_FAC_SH0); + rkisp1_write(params->rkisp1, arg->fac_sh1, RKISP1_CIF_ISP_FILT_FAC_SH1); + rkisp1_write(params->rkisp1, + arg->lum_weight, RKISP1_CIF_ISP_FILT_LUM_WEIGHT); + + rkisp1_write(params->rkisp1, + (arg->mode ? RKISP1_CIF_ISP_FLT_MODE_DNR : 0) | + RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | + RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | + RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1), + RKISP1_CIF_ISP_FILT_MODE); + + /* avoid to override the old enable value */ + filt_mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE); + filt_mode &= RKISP1_CIF_ISP_FLT_ENA; + if (arg->mode) + filt_mode |= RKISP1_CIF_ISP_FLT_MODE_DNR; + filt_mode |= RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | + RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | + RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1); + rkisp1_write(params->rkisp1, filt_mode, RKISP1_CIF_ISP_FILT_MODE); +} + +/* ISP demosaic interface function */ +static int rkisp1_bdm_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_bdm_config *arg) +{ + u32 bdm_th; + + /* avoid to override the old enable value */ + bdm_th = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DEMOSAIC); + bdm_th &= RKISP1_CIF_ISP_DEMOSAIC_BYPASS; + bdm_th |= arg->demosaic_th & ~RKISP1_CIF_ISP_DEMOSAIC_BYPASS; + /* set demosaic threshold */ + rkisp1_write(params->rkisp1, bdm_th, RKISP1_CIF_ISP_DEMOSAIC); + return 0; +} + +/* ISP GAMMA correction interface function */ +static void rkisp1_sdg_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_sdg_config *arg) +{ + unsigned int i; + + rkisp1_write(params->rkisp1, + arg->xa_pnts.gamma_dx0, RKISP1_CIF_ISP_GAMMA_DX_LO); + rkisp1_write(params->rkisp1, + arg->xa_pnts.gamma_dx1, RKISP1_CIF_ISP_GAMMA_DX_HI); + + for (i = 0; i < RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE; i++) { + rkisp1_write(params->rkisp1, arg->curve_r.gamma_y[i], + RKISP1_CIF_ISP_GAMMA_R_Y0 + i * 4); + rkisp1_write(params->rkisp1, arg->curve_g.gamma_y[i], + RKISP1_CIF_ISP_GAMMA_G_Y0 + i * 4); + rkisp1_write(params->rkisp1, arg->curve_b.gamma_y[i], + RKISP1_CIF_ISP_GAMMA_B_Y0 + i * 4); + } +} + +/* ISP GAMMA correction interface function */ +static void rkisp1_goc_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_goc_config *arg) +{ + unsigned int i; + + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); + rkisp1_write(params->rkisp1, arg->mode, RKISP1_CIF_ISP_GAMMA_OUT_MODE); + + for (i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES; i++) + rkisp1_write(params->rkisp1, arg->gamma_y[i], + RKISP1_CIF_ISP_GAMMA_OUT_Y_0 + i * 4); +} + +/* ISP Cross Talk */ +static void rkisp1_ctk_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_ctk_config *arg) +{ + unsigned int i, j, k = 0; + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + rkisp1_write(params->rkisp1, arg->coeff[i][j], + RKISP1_CIF_ISP_CT_COEFF_0 + 4 * k++); + for (i = 0; i < 3; i++) + rkisp1_write(params->rkisp1, arg->ct_offset[i], + RKISP1_CIF_ISP_CT_OFFSET_R + i * 4); +} + +static void rkisp1_ctk_enable(struct rkisp1_params *params, bool en) +{ + if (en) + return; + + /* Write back the default values. */ + rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_0); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_1); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_2); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_3); + rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_4); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_5); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_6); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_7); + rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_8); + + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_R); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_G); + rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_B); +} + +/* ISP White Balance Mode */ +static void rkisp1_awb_meas_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_awb_meas_config *arg) +{ + u32 reg_val = 0; + /* based on the mode,configure the awb module */ + if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_YCBCR) { + /* Reference Cb and Cr */ + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) | + arg->awb_ref_cb, RKISP1_CIF_ISP_AWB_REF); + /* Yc Threshold */ + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AWB_MAX_Y_SET(arg->max_y) | + RKISP1_CIF_ISP_AWB_MIN_Y_SET(arg->min_y) | + RKISP1_CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) | + arg->min_c, RKISP1_CIF_ISP_AWB_THRESH); + } + + reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP); + if (arg->enable_ymax_cmp) + reg_val |= RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; + else + reg_val &= ~RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; + rkisp1_write(params->rkisp1, reg_val, RKISP1_CIF_ISP_AWB_PROP); + + /* window offset */ + rkisp1_write(params->rkisp1, + arg->awb_wnd.v_offs, RKISP1_CIF_ISP_AWB_WND_V_OFFS); + rkisp1_write(params->rkisp1, + arg->awb_wnd.h_offs, RKISP1_CIF_ISP_AWB_WND_H_OFFS); + /* AWB window size */ + rkisp1_write(params->rkisp1, + arg->awb_wnd.v_size, RKISP1_CIF_ISP_AWB_WND_V_SIZE); + rkisp1_write(params->rkisp1, + arg->awb_wnd.h_size, RKISP1_CIF_ISP_AWB_WND_H_SIZE); + /* Number of frames */ + rkisp1_write(params->rkisp1, + arg->frames, RKISP1_CIF_ISP_AWB_FRAMES); +} + +static void +rkisp1_awb_meas_enable(struct rkisp1_params *params, + const struct rkisp1_cif_isp_awb_meas_config *arg, + bool en) +{ + u32 reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP); + + /* switch off */ + reg_val &= RKISP1_CIF_ISP_AWB_MODE_MASK_NONE; + + if (en) { + if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_RGB) + reg_val |= RKISP1_CIF_ISP_AWB_MODE_RGB_EN; + else + reg_val |= RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN; + + rkisp1_write(params->rkisp1, reg_val, RKISP1_CIF_ISP_AWB_PROP); + + /* Measurements require AWB block be active. */ + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + } else { + rkisp1_write(params->rkisp1, + reg_val, RKISP1_CIF_ISP_AWB_PROP); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + } +} + +static void +rkisp1_awb_gain_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_awb_gain_config *arg) +{ + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) | + arg->gain_green_b, RKISP1_CIF_ISP_AWB_GAIN_G); + + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) | + arg->gain_blue, RKISP1_CIF_ISP_AWB_GAIN_RB); +} + +static void rkisp1_aec_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_aec_config *arg) +{ + unsigned int block_hsize, block_vsize; + u32 exp_ctrl; + + /* avoid to override the old enable value */ + exp_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL); + exp_ctrl &= RKISP1_CIF_ISP_EXP_ENA; + if (arg->autostop) + exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP; + if (arg->mode == RKISP1_CIF_ISP_EXP_MEASURING_MODE_1) + exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1; + rkisp1_write(params->rkisp1, exp_ctrl, RKISP1_CIF_ISP_EXP_CTRL); + + rkisp1_write(params->rkisp1, + arg->meas_window.h_offs, RKISP1_CIF_ISP_EXP_H_OFFSET); + rkisp1_write(params->rkisp1, + arg->meas_window.v_offs, RKISP1_CIF_ISP_EXP_V_OFFSET); + + block_hsize = arg->meas_window.h_size / + RKISP1_CIF_ISP_EXP_COLUMN_NUM - 1; + block_vsize = arg->meas_window.v_size / + RKISP1_CIF_ISP_EXP_ROW_NUM - 1; + + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_EXP_H_SIZE_SET(block_hsize), + RKISP1_CIF_ISP_EXP_H_SIZE); + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_EXP_V_SIZE_SET(block_vsize), + RKISP1_CIF_ISP_EXP_V_SIZE); +} + +static void rkisp1_cproc_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_cproc_config *arg) +{ + struct rkisp1_cif_isp_isp_other_cfg *cur_other_cfg = + container_of(arg, struct rkisp1_cif_isp_isp_other_cfg, cproc_config); + struct rkisp1_cif_isp_ie_config *cur_ie_config = + &cur_other_cfg->ie_config; + u32 effect = cur_ie_config->effect; + u32 quantization = params->quantization; + + rkisp1_write(params->rkisp1, arg->contrast, RKISP1_CIF_C_PROC_CONTRAST); + rkisp1_write(params->rkisp1, arg->hue, RKISP1_CIF_C_PROC_HUE); + rkisp1_write(params->rkisp1, arg->sat, RKISP1_CIF_C_PROC_SATURATION); + rkisp1_write(params->rkisp1, arg->brightness, + RKISP1_CIF_C_PROC_BRIGHTNESS); + + if (quantization != V4L2_QUANTIZATION_FULL_RANGE || + effect != V4L2_COLORFX_NONE) { + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_YOUT_FULL | + RKISP1_CIF_C_PROC_YIN_FULL | + RKISP1_CIF_C_PROC_COUT_FULL); + } else { + rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_YOUT_FULL | + RKISP1_CIF_C_PROC_YIN_FULL | + RKISP1_CIF_C_PROC_COUT_FULL); + } +} + +static void rkisp1_hst_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_hst_config *arg) +{ + unsigned int block_hsize, block_vsize; + static const u32 hist_weight_regs[] = { + RKISP1_CIF_ISP_HIST_WEIGHT_00TO30, + RKISP1_CIF_ISP_HIST_WEIGHT_40TO21, + RKISP1_CIF_ISP_HIST_WEIGHT_31TO12, + RKISP1_CIF_ISP_HIST_WEIGHT_22TO03, + RKISP1_CIF_ISP_HIST_WEIGHT_13TO43, + RKISP1_CIF_ISP_HIST_WEIGHT_04TO34, + RKISP1_CIF_ISP_HIST_WEIGHT_44, + }; + const u8 *weight; + unsigned int i; + u32 hist_prop; + + /* avoid to override the old enable value */ + hist_prop = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_HIST_PROP); + hist_prop &= RKISP1_CIF_ISP_HIST_PROP_MODE_MASK; + hist_prop |= RKISP1_CIF_ISP_HIST_PREDIV_SET(arg->histogram_predivider); + rkisp1_write(params->rkisp1, hist_prop, RKISP1_CIF_ISP_HIST_PROP); + rkisp1_write(params->rkisp1, + arg->meas_window.h_offs, + RKISP1_CIF_ISP_HIST_H_OFFS); + rkisp1_write(params->rkisp1, + arg->meas_window.v_offs, + RKISP1_CIF_ISP_HIST_V_OFFS); + + block_hsize = arg->meas_window.h_size / + RKISP1_CIF_ISP_HIST_COLUMN_NUM - 1; + block_vsize = arg->meas_window.v_size / RKISP1_CIF_ISP_HIST_ROW_NUM - 1; + + rkisp1_write(params->rkisp1, block_hsize, RKISP1_CIF_ISP_HIST_H_SIZE); + rkisp1_write(params->rkisp1, block_vsize, RKISP1_CIF_ISP_HIST_V_SIZE); + + weight = arg->hist_weight; + for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4) + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_HIST_WEIGHT_SET(weight[0], + weight[1], + weight[2], + weight[3]), + hist_weight_regs[i]); +} + +static void +rkisp1_hst_enable(struct rkisp1_params *params, + const struct rkisp1_cif_isp_hst_config *arg, bool en) +{ + if (en) { + u32 hist_prop = rkisp1_read(params->rkisp1, + RKISP1_CIF_ISP_HIST_PROP); + + hist_prop &= ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK; + hist_prop |= arg->mode; + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP, + hist_prop); + } else { + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_HIST_PROP, + RKISP1_CIF_ISP_HIST_PROP_MODE_MASK); + } +} + +static void rkisp1_afm_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_afc_config *arg) +{ + size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win), + arg->num_afm_win); + u32 afm_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL); + unsigned int i; + + /* Switch off to configure. */ + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + + for (i = 0; i < num_of_win; i++) { + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) | + RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs), + RKISP1_CIF_ISP_AFM_LT_A + i * 8); + rkisp1_write(params->rkisp1, + RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size + + arg->afm_win[i].h_offs) | + RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size + + arg->afm_win[i].v_offs), + RKISP1_CIF_ISP_AFM_RB_A + i * 8); + } + rkisp1_write(params->rkisp1, arg->thres, RKISP1_CIF_ISP_AFM_THRES); + rkisp1_write(params->rkisp1, arg->var_shift, + RKISP1_CIF_ISP_AFM_VAR_SHIFT); + /* restore afm status */ + rkisp1_write(params->rkisp1, afm_ctrl, RKISP1_CIF_ISP_AFM_CTRL); +} + +static void rkisp1_ie_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_ie_config *arg) +{ + u32 eff_ctrl; + + eff_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL); + eff_ctrl &= ~RKISP1_CIF_IMG_EFF_CTRL_MODE_MASK; + + if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_YCBCR_FULL; + + switch (arg->effect) { + case V4L2_COLORFX_SEPIA: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; + break; + case V4L2_COLORFX_SET_CBCR: + rkisp1_write(params->rkisp1, arg->eff_tint, + RKISP1_CIF_IMG_EFF_TINT); + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; + break; + /* + * Color selection is similar to water color(AQUA): + * grayscale + selected color w threshold + */ + case V4L2_COLORFX_AQUA: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL; + rkisp1_write(params->rkisp1, arg->color_sel, + RKISP1_CIF_IMG_EFF_COLOR_SEL); + break; + case V4L2_COLORFX_EMBOSS: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS; + rkisp1_write(params->rkisp1, arg->eff_mat_1, + RKISP1_CIF_IMG_EFF_MAT_1); + rkisp1_write(params->rkisp1, arg->eff_mat_2, + RKISP1_CIF_IMG_EFF_MAT_2); + rkisp1_write(params->rkisp1, arg->eff_mat_3, + RKISP1_CIF_IMG_EFF_MAT_3); + break; + case V4L2_COLORFX_SKETCH: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH; + rkisp1_write(params->rkisp1, arg->eff_mat_3, + RKISP1_CIF_IMG_EFF_MAT_3); + rkisp1_write(params->rkisp1, arg->eff_mat_4, + RKISP1_CIF_IMG_EFF_MAT_4); + rkisp1_write(params->rkisp1, arg->eff_mat_5, + RKISP1_CIF_IMG_EFF_MAT_5); + break; + case V4L2_COLORFX_BW: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE; + break; + case V4L2_COLORFX_NEGATIVE: + eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE; + break; + default: + break; + } + + rkisp1_write(params->rkisp1, eff_ctrl, RKISP1_CIF_IMG_EFF_CTRL); +} + +static void rkisp1_ie_enable(struct rkisp1_params *params, bool en) +{ + if (en) { + rkisp1_param_set_bits(params, RKISP1_CIF_ICCL, + RKISP1_CIF_ICCL_IE_CLK); + rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL_ENABLE, + RKISP1_CIF_IMG_EFF_CTRL); + rkisp1_param_set_bits(params, RKISP1_CIF_IMG_EFF_CTRL, + RKISP1_CIF_IMG_EFF_CTRL_CFG_UPD); + } else { + rkisp1_param_clear_bits(params, RKISP1_CIF_IMG_EFF_CTRL, + RKISP1_CIF_IMG_EFF_CTRL_ENABLE); + rkisp1_param_clear_bits(params, RKISP1_CIF_ICCL, + RKISP1_CIF_ICCL_IE_CLK); + } +} + +static void rkisp1_csm_config(struct rkisp1_params *params, bool full_range) +{ + static const u16 full_range_coeff[] = { + 0x0026, 0x004b, 0x000f, + 0x01ea, 0x01d6, 0x0040, + 0x0040, 0x01ca, 0x01f6 + }; + static const u16 limited_range_coeff[] = { + 0x0021, 0x0040, 0x000d, + 0x01ed, 0x01db, 0x0038, + 0x0038, 0x01d1, 0x01f7, + }; + unsigned int i; + + if (full_range) { + for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++) + rkisp1_write(params->rkisp1, full_range_coeff[i], + RKISP1_CIF_ISP_CC_COEFF_0 + i * 4); + + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); + } else { + for (i = 0; i < ARRAY_SIZE(limited_range_coeff); i++) + rkisp1_write(params->rkisp1, limited_range_coeff[i], + RKISP1_CIF_ISP_CC_COEFF_0 + i * 4); + + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | + RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); + } +} + +/* ISP De-noise Pre-Filter(DPF) function */ +static void rkisp1_dpf_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_dpf_config *arg) +{ + unsigned int isp_dpf_mode, spatial_coeff, i; + + switch (arg->gain.mode) { + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS: + isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | + RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; + break; + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS: + isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; + break; + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS: + isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | + RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP | + RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; + break; + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS: + isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; + break; + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS: + isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP | + RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; + break; + case RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED: + default: + isp_dpf_mode = 0; + break; + } + + if (arg->nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_NLL_SEGMENTATION; + if (arg->rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9; + if (!arg->rb_flt.r_enable) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_R_FLT_DIS; + if (!arg->rb_flt.b_enable) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_B_FLT_DIS; + if (!arg->g_flt.gb_enable) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GB_FLT_DIS; + if (!arg->g_flt.gr_enable) + isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GR_FLT_DIS; + + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE, + isp_dpf_mode); + rkisp1_write(params->rkisp1, arg->gain.nf_b_gain, + RKISP1_CIF_ISP_DPF_NF_GAIN_B); + rkisp1_write(params->rkisp1, arg->gain.nf_r_gain, + RKISP1_CIF_ISP_DPF_NF_GAIN_R); + rkisp1_write(params->rkisp1, arg->gain.nf_gb_gain, + RKISP1_CIF_ISP_DPF_NF_GAIN_GB); + rkisp1_write(params->rkisp1, arg->gain.nf_gr_gain, + RKISP1_CIF_ISP_DPF_NF_GAIN_GR); + + for (i = 0; i < RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS; i++) { + rkisp1_write(params->rkisp1, arg->nll.coeff[i], + RKISP1_CIF_ISP_DPF_NULL_COEFF_0 + i * 4); + } + + spatial_coeff = arg->g_flt.spatial_coeff[0] | + (arg->g_flt.spatial_coeff[1] << 8) | + (arg->g_flt.spatial_coeff[2] << 16) | + (arg->g_flt.spatial_coeff[3] << 24); + rkisp1_write(params->rkisp1, spatial_coeff, + RKISP1_CIF_ISP_DPF_S_WEIGHT_G_1_4); + + spatial_coeff = arg->g_flt.spatial_coeff[4] | + (arg->g_flt.spatial_coeff[5] << 8); + rkisp1_write(params->rkisp1, spatial_coeff, + RKISP1_CIF_ISP_DPF_S_WEIGHT_G_5_6); + + spatial_coeff = arg->rb_flt.spatial_coeff[0] | + (arg->rb_flt.spatial_coeff[1] << 8) | + (arg->rb_flt.spatial_coeff[2] << 16) | + (arg->rb_flt.spatial_coeff[3] << 24); + rkisp1_write(params->rkisp1, spatial_coeff, + RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_1_4); + + spatial_coeff = arg->rb_flt.spatial_coeff[4] | + (arg->rb_flt.spatial_coeff[5] << 8); + rkisp1_write(params->rkisp1, spatial_coeff, + RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_5_6); +} + +static void +rkisp1_dpf_strength_config(struct rkisp1_params *params, + const struct rkisp1_cif_isp_dpf_strength_config *arg) +{ + rkisp1_write(params->rkisp1, arg->b, RKISP1_CIF_ISP_DPF_STRENGTH_B); + rkisp1_write(params->rkisp1, arg->g, RKISP1_CIF_ISP_DPF_STRENGTH_G); + rkisp1_write(params->rkisp1, arg->r, RKISP1_CIF_ISP_DPF_STRENGTH_R); +} + +static void +rkisp1_isp_isr_other_config(struct rkisp1_params *params, + const struct rkisp1_params_cfg *new_params) +{ + unsigned int module_en_update, module_cfg_update, module_ens; + + module_en_update = new_params->module_en_update; + module_cfg_update = new_params->module_cfg_update; + module_ens = new_params->module_ens; + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPCC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC)) { + /*update dpc config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC) + rkisp1_dpcc_config(params, + &new_params->others.dpcc_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_DPCC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_DPCC) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_DPCC_MODE, + RKISP1_CIF_ISP_DPCC_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_DPCC_MODE, + RKISP1_CIF_ISP_DPCC_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_BLS) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_BLS)) { + /* update bls config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BLS) + rkisp1_bls_config(params, + &new_params->others.bls_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_BLS) { + if (module_ens & RKISP1_CIF_ISP_MODULE_BLS) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_BLS_CTRL, + RKISP1_CIF_ISP_BLS_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_BLS_CTRL, + RKISP1_CIF_ISP_BLS_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_SDG) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_SDG)) { + /* update sdg config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_SDG) + rkisp1_sdg_config(params, + &new_params->others.sdg_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_SDG) { + if (module_ens & RKISP1_CIF_ISP_MODULE_SDG) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_LSC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_LSC)) { + /* update lsc config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_LSC) + rkisp1_lsc_config(params, + &new_params->others.lsc_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_LSC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_LSC) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN)) { + /* update awb gains */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) + rkisp1_awb_gain_config(params, + &new_params->others.awb_gain_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) { + if (module_ens & RKISP1_CIF_ISP_MODULE_AWB_GAIN) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_BDM) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_BDM)) { + /* update bdm config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BDM) + rkisp1_bdm_config(params, + &new_params->others.bdm_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_BDM) { + if (module_ens & RKISP1_CIF_ISP_MODULE_BDM) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_DEMOSAIC, + RKISP1_CIF_ISP_DEMOSAIC_BYPASS); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_DEMOSAIC, + RKISP1_CIF_ISP_DEMOSAIC_BYPASS); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_FLT) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_FLT)) { + /* update filter config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_FLT) + rkisp1_flt_config(params, + &new_params->others.flt_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_FLT) { + if (module_ens & RKISP1_CIF_ISP_MODULE_FLT) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_FILT_MODE, + RKISP1_CIF_ISP_FLT_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_FILT_MODE, + RKISP1_CIF_ISP_FLT_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_CTK) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_CTK)) { + /* update ctk config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CTK) + rkisp1_ctk_config(params, + &new_params->others.ctk_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_CTK) + rkisp1_ctk_enable(params, + !!(module_ens & RKISP1_CIF_ISP_MODULE_CTK)); + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_GOC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_GOC)) { + /* update goc config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_GOC) + rkisp1_goc_config(params, + &new_params->others.goc_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_GOC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_GOC) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_CPROC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_CPROC)) { + /* update cproc config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CPROC) { + rkisp1_cproc_config(params, + &new_params->others.cproc_config); + } + + if (module_en_update & RKISP1_CIF_ISP_MODULE_CPROC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_CPROC) + rkisp1_param_set_bits(params, + RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_CTR_ENABLE); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_CTR_ENABLE); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_IE) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_IE)) { + /* update ie config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_IE) + rkisp1_ie_config(params, + &new_params->others.ie_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_IE) + rkisp1_ie_enable(params, + !!(module_ens & RKISP1_CIF_ISP_MODULE_IE)); + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPF) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF)) { + /* update dpf config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF) + rkisp1_dpf_config(params, + &new_params->others.dpf_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_DPF) { + if (module_ens & RKISP1_CIF_ISP_MODULE_DPF) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_DPF_MODE, + RKISP1_CIF_ISP_DPF_MODE_EN); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_DPF_MODE, + RKISP1_CIF_ISP_DPF_MODE_EN); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH)) { + /* update dpf strength config */ + rkisp1_dpf_strength_config(params, + &new_params->others.dpf_strength_config); + } +} + +static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params, + struct rkisp1_params_cfg *new_params) +{ + unsigned int module_en_update, module_cfg_update, module_ens; + + module_en_update = new_params->module_en_update; + module_cfg_update = new_params->module_cfg_update; + module_ens = new_params->module_ens; + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_AWB) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB)) { + /* update awb config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB) + rkisp1_awb_meas_config(params, + &new_params->meas.awb_meas_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB) + rkisp1_awb_meas_enable(params, + &new_params->meas.awb_meas_config, + !!(module_ens & RKISP1_CIF_ISP_MODULE_AWB)); + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_AFC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_AFC)) { + /* update afc config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AFC) + rkisp1_afm_config(params, + &new_params->meas.afc_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_AFC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_AFC) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + } + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_HST) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_HST)) { + /* update hst config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_HST) + rkisp1_hst_config(params, + &new_params->meas.hst_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_HST) + rkisp1_hst_enable(params, + &new_params->meas.hst_config, + !!(module_ens & RKISP1_CIF_ISP_MODULE_HST)); + } + + if ((module_en_update & RKISP1_CIF_ISP_MODULE_AEC) || + (module_cfg_update & RKISP1_CIF_ISP_MODULE_AEC)) { + /* update aec config */ + if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AEC) + rkisp1_aec_config(params, + &new_params->meas.aec_config); + + if (module_en_update & RKISP1_CIF_ISP_MODULE_AEC) { + if (module_ens & RKISP1_CIF_ISP_MODULE_AEC) + rkisp1_param_set_bits(params, + RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); + else + rkisp1_param_clear_bits(params, + RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); + } + } +} + +static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params, + unsigned int frame_sequence) +{ + struct rkisp1_params_cfg *new_params; + struct rkisp1_buffer *cur_buf = NULL; + + if (list_empty(¶ms->params)) + return; + + cur_buf = list_first_entry(¶ms->params, + struct rkisp1_buffer, queue); + + new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr); + + rkisp1_isp_isr_other_config(params, new_params); + rkisp1_isp_isr_meas_config(params, new_params); + + /* update shadow register immediately */ + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD); + + list_del(&cur_buf->queue); + + cur_buf->vb.sequence = frame_sequence; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); +} + +void rkisp1_params_isr(struct rkisp1_device *rkisp1) +{ + /* + * This isr is called when the ISR finishes processing a frame (RKISP1_CIF_ISP_FRAME). + * Configurations performed here will be applied on the next frame. + * Since frame_sequence is updated on the vertical sync signal, we should use + * frame_sequence + 1 here to indicate to userspace on which frame these parameters + * are being applied. + */ + unsigned int frame_sequence = rkisp1->isp.frame_sequence + 1; + struct rkisp1_params *params = &rkisp1->params; + + spin_lock(¶ms->config_lock); + rkisp1_params_apply_params_cfg(params, frame_sequence); + + spin_unlock(¶ms->config_lock); +} + +static const struct rkisp1_cif_isp_awb_meas_config rkisp1_awb_params_default_config = { + { + 0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT + }, + RKISP1_CIF_ISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128 +}; + +static const struct rkisp1_cif_isp_aec_config rkisp1_aec_params_default_config = { + RKISP1_CIF_ISP_EXP_MEASURING_MODE_0, + RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0, + { + RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, + RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 + } +}; + +static const struct rkisp1_cif_isp_hst_config rkisp1_hst_params_default_config = { + RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED, + 3, + { + RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, + RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 + }, + { + 0, /* To be filled in with 0x01 at runtime. */ + } +}; + +static const struct rkisp1_cif_isp_afc_config rkisp1_afc_params_default_config = { + 1, + { + { + 300, 225, 200, 150 + } + }, + 4, + 14 +}; + +static void rkisp1_params_config_parameter(struct rkisp1_params *params) +{ + struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config; + + rkisp1_awb_meas_config(params, &rkisp1_awb_params_default_config); + rkisp1_awb_meas_enable(params, &rkisp1_awb_params_default_config, + true); + + rkisp1_aec_config(params, &rkisp1_aec_params_default_config); + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); + + rkisp1_afm_config(params, &rkisp1_afc_params_default_config); + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + + memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight)); + rkisp1_hst_config(params, &hst); + rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP, + ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK | + rkisp1_hst_params_default_config.mode); + + /* set the range */ + if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) + rkisp1_csm_config(params, true); + else + rkisp1_csm_config(params, false); + + spin_lock_irq(¶ms->config_lock); + + /* apply the first buffer if there is one already */ + rkisp1_params_apply_params_cfg(params, 0); + + spin_unlock_irq(¶ms->config_lock); +} + +void rkisp1_params_configure(struct rkisp1_params *params, + enum rkisp1_fmt_raw_pat_type bayer_pat, + enum v4l2_quantization quantization) +{ + params->quantization = quantization; + params->raw_type = bayer_pat; + rkisp1_params_config_parameter(params); +} + +/* Not called when the camera active, thus not isr protection. */ +void rkisp1_params_disable(struct rkisp1_params *params) +{ + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE, + RKISP1_CIF_ISP_DPCC_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, + RKISP1_CIF_ISP_LSC_CTRL_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL, + RKISP1_CIF_ISP_BLS_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC, + RKISP1_CIF_ISP_DEMOSAIC_BYPASS); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE, + RKISP1_CIF_ISP_FLT_ENA); + rkisp1_awb_meas_enable(params, NULL, false); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, + RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL, + RKISP1_CIF_ISP_EXP_ENA); + rkisp1_ctk_enable(params, false); + rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, + RKISP1_CIF_C_PROC_CTR_ENABLE); + rkisp1_hst_enable(params, NULL, false); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, + RKISP1_CIF_ISP_AFM_ENA); + rkisp1_ie_enable(params, false); + rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE, + RKISP1_CIF_ISP_DPF_MODE_EN); +} + +static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct video_device *video = video_devdata(file); + struct rkisp1_params *params = video_get_drvdata(video); + + if (f->index > 0 || f->type != video->queue->type) + return -EINVAL; + + f->pixelformat = params->vdev_fmt.fmt.meta.dataformat; + + return 0; +} + +static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct video_device *video = video_devdata(file); + struct rkisp1_params *params = video_get_drvdata(video); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != video->queue->type) + return -EINVAL; + + memset(meta, 0, sizeof(*meta)); + meta->dataformat = params->vdev_fmt.fmt.meta.dataformat; + meta->buffersize = params->vdev_fmt.fmt.meta.buffersize; + + return 0; +} + +static int rkisp1_params_querycap(struct file *file, + void *priv, struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, vdev->name, sizeof(cap->card)); + strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); + + return 0; +} + +/* ISP params video device IOCTLs */ +static const struct v4l2_ioctl_ops rkisp1_params_ioctl = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out, + .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out, + .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out, + .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out, + .vidioc_querycap = rkisp1_params_querycap, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + *num_buffers = clamp_t(u32, *num_buffers, + RKISP1_ISP_PARAMS_REQ_BUFS_MIN, + RKISP1_ISP_PARAMS_REQ_BUFS_MAX); + + *num_planes = 1; + + sizes[0] = sizeof(struct rkisp1_params_cfg); + + return 0; +} + +static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_buffer *params_buf = + container_of(vbuf, struct rkisp1_buffer, vb); + struct vb2_queue *vq = vb->vb2_queue; + struct rkisp1_params *params = vq->drv_priv; + + params_buf->vaddr = vb2_plane_vaddr(vb, 0); + spin_lock_irq(¶ms->config_lock); + list_add_tail(¶ms_buf->queue, ¶ms->params); + spin_unlock_irq(¶ms->config_lock); +} + +static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb) +{ + if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg)) + return -EINVAL; + + vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg)); + + return 0; +} + +static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct rkisp1_params *params = vq->drv_priv; + struct rkisp1_buffer *buf; + LIST_HEAD(tmp_list); + + /* + * we first move the buffers into a local list 'tmp_list' + * and then we can iterate it and call vb2_buffer_done + * without holding the lock + */ + spin_lock_irq(¶ms->config_lock); + list_splice_init(¶ms->params, &tmp_list); + spin_unlock_irq(¶ms->config_lock); + + list_for_each_entry(buf, &tmp_list, queue) + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); +} + +static struct vb2_ops rkisp1_params_vb2_ops = { + .queue_setup = rkisp1_params_vb2_queue_setup, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .buf_queue = rkisp1_params_vb2_buf_queue, + .buf_prepare = rkisp1_params_vb2_buf_prepare, + .stop_streaming = rkisp1_params_vb2_stop_streaming, + +}; + +static struct v4l2_file_operations rkisp1_params_fops = { + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .open = v4l2_fh_open, + .release = vb2_fop_release +}; + +static int rkisp1_params_init_vb2_queue(struct vb2_queue *q, + struct rkisp1_params *params) +{ + struct rkisp1_vdev_node *node; + + node = container_of(q, struct rkisp1_vdev_node, buf_queue); + + q->type = V4L2_BUF_TYPE_META_OUTPUT; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->drv_priv = params; + q->ops = &rkisp1_params_vb2_ops; + q->mem_ops = &vb2_vmalloc_memops; + q->buf_struct_size = sizeof(struct rkisp1_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &node->vlock; + + return vb2_queue_init(q); +} + +static void rkisp1_init_params(struct rkisp1_params *params) +{ + params->vdev_fmt.fmt.meta.dataformat = + V4L2_META_FMT_RK_ISP1_PARAMS; + params->vdev_fmt.fmt.meta.buffersize = + sizeof(struct rkisp1_params_cfg); +} + +int rkisp1_params_register(struct rkisp1_device *rkisp1) +{ + struct rkisp1_params *params = &rkisp1->params; + struct rkisp1_vdev_node *node = ¶ms->vnode; + struct video_device *vdev = &node->vdev; + int ret; + + params->rkisp1 = rkisp1; + mutex_init(&node->vlock); + INIT_LIST_HEAD(¶ms->params); + spin_lock_init(¶ms->config_lock); + + strscpy(vdev->name, RKISP1_PARAMS_DEV_NAME, sizeof(vdev->name)); + + video_set_drvdata(vdev, params); + vdev->ioctl_ops = &rkisp1_params_ioctl; + vdev->fops = &rkisp1_params_fops; + vdev->release = video_device_release_empty; + /* + * Provide a mutex to v4l2 core. It will be used + * to protect all fops and v4l2 ioctls. + */ + vdev->lock = &node->vlock; + vdev->v4l2_dev = &rkisp1->v4l2_dev; + vdev->queue = &node->buf_queue; + vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; + vdev->vfl_dir = VFL_DIR_TX; + rkisp1_params_init_vb2_queue(vdev->queue, params); + rkisp1_init_params(params); + video_set_drvdata(vdev, params); + + node->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); + if (ret) + return ret; + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(rkisp1->dev, + "failed to register %s, ret=%d\n", vdev->name, ret); + goto err_cleanup_media_entity; + } + return 0; +err_cleanup_media_entity: + media_entity_cleanup(&vdev->entity); + return ret; +} + +void rkisp1_params_unregister(struct rkisp1_device *rkisp1) +{ + struct rkisp1_params *params = &rkisp1->params; + struct rkisp1_vdev_node *node = ¶ms->vnode; + struct video_device *vdev = &node->vdev; + + vb2_video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h new file mode 100644 index 000000000000..049f6c3a11df --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h @@ -0,0 +1,1262 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Rockchip ISP1 Driver - Registers header + * + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef _RKISP1_REGS_H +#define _RKISP1_REGS_H + +/* ISP_CTRL */ +#define RKISP1_CIF_ISP_CTRL_ISP_ENABLE BIT(0) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT (0 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU656 BIT(1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601 (2 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601 (3 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_DATA_MODE (4 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656 (5 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656 (6 << 1) +#define RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE BIT(4) +#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA BIT(6) +#define RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA BIT(7) +#define RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT BIT(8) +#define RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD BIT(9) +#define RKISP1_CIF_ISP_CTRL_ISP_GEN_CFG_UPD BIT(10) +#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA BIT(11) +#define RKISP1_CIF_ISP_CTRL_ISP_FLASH_MODE_ENA BIT(12) +#define RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA BIT(13) +#define RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA BIT(14) + +/* ISP_ACQ_PROP */ +#define RKISP1_CIF_ISP_ACQ_PROP_POS_EDGE BIT(0) +#define RKISP1_CIF_ISP_ACQ_PROP_HSYNC_LOW BIT(1) +#define RKISP1_CIF_ISP_ACQ_PROP_VSYNC_LOW BIT(2) +#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB (0 << 3) +#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG BIT(3) +#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG (2 << 3) +#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR (3 << 3) +#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT(pat) ((pat) << 3) +#define RKISP1_CIF_ISP_ACQ_PROP_YCBYCR (0 << 7) +#define RKISP1_CIF_ISP_ACQ_PROP_YCRYCB BIT(7) +#define RKISP1_CIF_ISP_ACQ_PROP_CBYCRY (2 << 7) +#define RKISP1_CIF_ISP_ACQ_PROP_CRYCBY (3 << 7) +#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ALL (0 << 9) +#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN BIT(9) +#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ODD (2 << 9) +#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_12B (0 << 12) +#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO BIT(12) +#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB (2 << 12) +#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO (3 << 12) +#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB (4 << 12) + +/* VI_DPCL */ +#define RKISP1_CIF_VI_DPCL_DMA_JPEG (0 << 0) +#define RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI BIT(0) +#define RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_JPEG (2 << 0) +#define RKISP1_CIF_VI_DPCL_CHAN_MODE_MP BIT(2) +#define RKISP1_CIF_VI_DPCL_CHAN_MODE_SP (2 << 2) +#define RKISP1_CIF_VI_DPCL_CHAN_MODE_MPSP (3 << 2) +#define RKISP1_CIF_VI_DPCL_DMA_SW_SPMUX (0 << 4) +#define RKISP1_CIF_VI_DPCL_DMA_SW_SI BIT(4) +#define RKISP1_CIF_VI_DPCL_DMA_SW_IE (2 << 4) +#define RKISP1_CIF_VI_DPCL_DMA_SW_JPEG (3 << 4) +#define RKISP1_CIF_VI_DPCL_DMA_SW_ISP (4 << 4) +#define RKISP1_CIF_VI_DPCL_IF_SEL_PARALLEL (0 << 8) +#define RKISP1_CIF_VI_DPCL_IF_SEL_SMIA BIT(8) +#define RKISP1_CIF_VI_DPCL_IF_SEL_MIPI (2 << 8) +#define RKISP1_CIF_VI_DPCL_DMA_IE_MUX_DMA BIT(10) +#define RKISP1_CIF_VI_DPCL_DMA_SP_MUX_DMA BIT(11) + +/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */ +#define RKISP1_CIF_ISP_OFF BIT(0) +#define RKISP1_CIF_ISP_FRAME BIT(1) +#define RKISP1_CIF_ISP_DATA_LOSS BIT(2) +#define RKISP1_CIF_ISP_PIC_SIZE_ERROR BIT(3) +#define RKISP1_CIF_ISP_AWB_DONE BIT(4) +#define RKISP1_CIF_ISP_FRAME_IN BIT(5) +#define RKISP1_CIF_ISP_V_START BIT(6) +#define RKISP1_CIF_ISP_H_START BIT(7) +#define RKISP1_CIF_ISP_FLASH_ON BIT(8) +#define RKISP1_CIF_ISP_FLASH_OFF BIT(9) +#define RKISP1_CIF_ISP_SHUTTER_ON BIT(10) +#define RKISP1_CIF_ISP_SHUTTER_OFF BIT(11) +#define RKISP1_CIF_ISP_AFM_SUM_OF BIT(12) +#define RKISP1_CIF_ISP_AFM_LUM_OF BIT(13) +#define RKISP1_CIF_ISP_AFM_FIN BIT(14) +#define RKISP1_CIF_ISP_HIST_MEASURE_RDY BIT(15) +#define RKISP1_CIF_ISP_FLASH_CAP BIT(17) +#define RKISP1_CIF_ISP_EXP_END BIT(18) +#define RKISP1_CIF_ISP_VSM_END BIT(19) + +/* ISP_ERR */ +#define RKISP1_CIF_ISP_ERR_INFORM_SIZE BIT(0) +#define RKISP1_CIF_ISP_ERR_IS_SIZE BIT(1) +#define RKISP1_CIF_ISP_ERR_OUTFORM_SIZE BIT(2) + +/* MI_CTRL */ +#define RKISP1_CIF_MI_CTRL_MP_ENABLE BIT(0) +#define RKISP1_CIF_MI_CTRL_SP_ENABLE (2 << 0) +#define RKISP1_CIF_MI_CTRL_JPEG_ENABLE (4 << 0) +#define RKISP1_CIF_MI_CTRL_RAW_ENABLE (8 << 0) +#define RKISP1_CIF_MI_CTRL_HFLIP BIT(4) +#define RKISP1_CIF_MI_CTRL_VFLIP BIT(5) +#define RKISP1_CIF_MI_CTRL_ROT BIT(6) +#define RKISP1_CIF_MI_BYTE_SWAP BIT(7) +#define RKISP1_CIF_MI_SP_Y_FULL_YUV2RGB BIT(8) +#define RKISP1_CIF_MI_SP_CBCR_FULL_YUV2RGB BIT(9) +#define RKISP1_CIF_MI_SP_422NONCOSITEED BIT(10) +#define RKISP1_CIF_MI_MP_PINGPONG_ENABEL BIT(11) +#define RKISP1_CIF_MI_SP_PINGPONG_ENABEL BIT(12) +#define RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE BIT(13) +#define RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE BIT(14) +#define RKISP1_CIF_MI_LAST_PIXEL_SIG_ENABLE BIT(15) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_16 (0 << 16) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_32 BIT(16) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64 (2 << 16) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_16 (0 << 18) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_32 BIT(18) +#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64 (2 << 18) +#define RKISP1_CIF_MI_CTRL_INIT_BASE_EN BIT(20) +#define RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN BIT(21) +#define RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8 (0 << 22) +#define RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA BIT(22) +#define RKISP1_MI_CTRL_MP_WRITE_YUVINT (2 << 22) +#define RKISP1_MI_CTRL_MP_WRITE_RAW12 (2 << 22) +#define RKISP1_MI_CTRL_SP_WRITE_PLA (0 << 24) +#define RKISP1_MI_CTRL_SP_WRITE_SPLA BIT(24) +#define RKISP1_MI_CTRL_SP_WRITE_INT (2 << 24) +#define RKISP1_MI_CTRL_SP_INPUT_YUV400 (0 << 26) +#define RKISP1_MI_CTRL_SP_INPUT_YUV420 BIT(26) +#define RKISP1_MI_CTRL_SP_INPUT_YUV422 (2 << 26) +#define RKISP1_MI_CTRL_SP_INPUT_YUV444 (3 << 26) +#define RKISP1_MI_CTRL_SP_OUTPUT_YUV400 (0 << 28) +#define RKISP1_MI_CTRL_SP_OUTPUT_YUV420 BIT(28) +#define RKISP1_MI_CTRL_SP_OUTPUT_YUV422 (2 << 28) +#define RKISP1_MI_CTRL_SP_OUTPUT_YUV444 (3 << 28) +#define RKISP1_MI_CTRL_SP_OUTPUT_RGB565 (4 << 28) +#define RKISP1_MI_CTRL_SP_OUTPUT_RGB666 (5 << 28) +#define RKISP1_MI_CTRL_SP_OUTPUT_RGB888 (6 << 28) + +#define RKISP1_MI_CTRL_MP_FMT_MASK GENMASK(23, 22) +#define RKISP1_MI_CTRL_SP_FMT_MASK GENMASK(30, 24) + +/* MI_INIT */ +#define RKISP1_CIF_MI_INIT_SKIP BIT(2) +#define RKISP1_CIF_MI_INIT_SOFT_UPD BIT(4) + +/* MI_CTRL_SHD */ +#define RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED BIT(0) +#define RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED BIT(1) +#define RKISP1_CIF_MI_CTRL_SHD_JPEG_IN_ENABLED BIT(2) +#define RKISP1_CIF_MI_CTRL_SHD_RAW_IN_ENABLED BIT(3) +#define RKISP1_CIF_MI_CTRL_SHD_MP_OUT_ENABLED BIT(16) +#define RKISP1_CIF_MI_CTRL_SHD_SP_OUT_ENABLED BIT(17) +#define RKISP1_CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED BIT(18) +#define RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED BIT(19) + +/* RSZ_CTRL */ +#define RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE BIT(0) +#define RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE BIT(1) +#define RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE BIT(2) +#define RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE BIT(3) +#define RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP BIT(4) +#define RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP BIT(5) +#define RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP BIT(6) +#define RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP BIT(7) +#define RKISP1_CIF_RSZ_CTRL_CFG_UPD BIT(8) +#define RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO BIT(9) +#define RKISP1_CIF_RSZ_SCALER_FACTOR BIT(16) + +/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */ +#define RKISP1_CIF_MI_FRAME(stream) BIT((stream)->id) +#define RKISP1_CIF_MI_MBLK_LINE BIT(2) +#define RKISP1_CIF_MI_FILL_MP_Y BIT(3) +#define RKISP1_CIF_MI_WRAP_MP_Y BIT(4) +#define RKISP1_CIF_MI_WRAP_MP_CB BIT(5) +#define RKISP1_CIF_MI_WRAP_MP_CR BIT(6) +#define RKISP1_CIF_MI_WRAP_SP_Y BIT(7) +#define RKISP1_CIF_MI_WRAP_SP_CB BIT(8) +#define RKISP1_CIF_MI_WRAP_SP_CR BIT(9) +#define RKISP1_CIF_MI_DMA_READY BIT(11) + +/* MI_STATUS */ +#define RKISP1_CIF_MI_STATUS_MP_Y_FIFO_FULL BIT(0) +#define RKISP1_CIF_MI_STATUS_SP_Y_FIFO_FULL BIT(4) + +/* MI_DMA_CTRL */ +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_16 (0 << 0) +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_32 BIT(0) +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_64 (2 << 0) +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16 (0 << 2) +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32 BIT(2) +#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64 (2 << 2) +#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_PLANAR (0 << 4) +#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_SPLANAR BIT(4) +#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV400 (0 << 6) +#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV420 BIT(6) +#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_PACKED (2 << 4) +#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV422 (2 << 6) +#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV444 (3 << 6) +#define RKISP1_CIF_MI_DMA_CTRL_BYTE_SWAP BIT(8) +#define RKISP1_CIF_MI_DMA_CTRL_CONTINUOUS_ENA BIT(9) +#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_NO (0 << 12) +#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_8BIT BIT(12) +#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_16BIT (2 << 12) +/* MI_DMA_START */ +#define RKISP1_CIF_MI_DMA_START_ENABLE BIT(0) +/* MI_XTD_FORMAT_CTRL */ +#define RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP BIT(0) +#define RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP BIT(1) +#define RKISP1_CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP BIT(2) + +/* CCL */ +#define RKISP1_CIF_CCL_CIF_CLK_DIS BIT(2) +/* ICCL */ +#define RKISP1_CIF_ICCL_ISP_CLK BIT(0) +#define RKISP1_CIF_ICCL_CP_CLK BIT(1) +#define RKISP1_CIF_ICCL_RES_2 BIT(2) +#define RKISP1_CIF_ICCL_MRSZ_CLK BIT(3) +#define RKISP1_CIF_ICCL_SRSZ_CLK BIT(4) +#define RKISP1_CIF_ICCL_JPEG_CLK BIT(5) +#define RKISP1_CIF_ICCL_MI_CLK BIT(6) +#define RKISP1_CIF_ICCL_RES_7 BIT(7) +#define RKISP1_CIF_ICCL_IE_CLK BIT(8) +#define RKISP1_CIF_ICCL_SIMP_CLK BIT(9) +#define RKISP1_CIF_ICCL_SMIA_CLK BIT(10) +#define RKISP1_CIF_ICCL_MIPI_CLK BIT(11) +#define RKISP1_CIF_ICCL_DCROP_CLK BIT(12) +/* IRCL */ +#define RKISP1_CIF_IRCL_ISP_SW_RST BIT(0) +#define RKISP1_CIF_IRCL_CP_SW_RST BIT(1) +#define RKISP1_CIF_IRCL_YCS_SW_RST BIT(2) +#define RKISP1_CIF_IRCL_MRSZ_SW_RST BIT(3) +#define RKISP1_CIF_IRCL_SRSZ_SW_RST BIT(4) +#define RKISP1_CIF_IRCL_JPEG_SW_RST BIT(5) +#define RKISP1_CIF_IRCL_MI_SW_RST BIT(6) +#define RKISP1_CIF_IRCL_CIF_SW_RST BIT(7) +#define RKISP1_CIF_IRCL_IE_SW_RST BIT(8) +#define RKISP1_CIF_IRCL_SI_SW_RST BIT(9) +#define RKISP1_CIF_IRCL_MIPI_SW_RST BIT(11) + +/* C_PROC_CTR */ +#define RKISP1_CIF_C_PROC_CTR_ENABLE BIT(0) +#define RKISP1_CIF_C_PROC_YOUT_FULL BIT(1) +#define RKISP1_CIF_C_PROC_YIN_FULL BIT(2) +#define RKISP1_CIF_C_PROC_COUT_FULL BIT(3) +#define RKISP1_CIF_C_PROC_CTRL_RESERVED 0xFFFFFFFE +#define RKISP1_CIF_C_PROC_CONTRAST_RESERVED 0xFFFFFF00 +#define RKISP1_CIF_C_PROC_BRIGHTNESS_RESERVED 0xFFFFFF00 +#define RKISP1_CIF_C_PROC_HUE_RESERVED 0xFFFFFF00 +#define RKISP1_CIF_C_PROC_SATURATION_RESERVED 0xFFFFFF00 +#define RKISP1_CIF_C_PROC_MACC_RESERVED 0xE000E000 +#define RKISP1_CIF_C_PROC_TONE_RESERVED 0xF000 +/* DUAL_CROP_CTRL */ +#define RKISP1_CIF_DUAL_CROP_MP_MODE_BYPASS (0 << 0) +#define RKISP1_CIF_DUAL_CROP_MP_MODE_YUV BIT(0) +#define RKISP1_CIF_DUAL_CROP_MP_MODE_RAW (2 << 0) +#define RKISP1_CIF_DUAL_CROP_SP_MODE_BYPASS (0 << 2) +#define RKISP1_CIF_DUAL_CROP_SP_MODE_YUV BIT(2) +#define RKISP1_CIF_DUAL_CROP_SP_MODE_RAW (2 << 2) +#define RKISP1_CIF_DUAL_CROP_CFG_UPD_PERMANENT BIT(4) +#define RKISP1_CIF_DUAL_CROP_CFG_UPD BIT(5) +#define RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD BIT(6) + +/* IMG_EFF_CTRL */ +#define RKISP1_CIF_IMG_EFF_CTRL_ENABLE BIT(0) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE (0 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE BIT(1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA (2 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL (3 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS (4 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH (5 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SHARPEN (6 << 1) +#define RKISP1_CIF_IMG_EFF_CTRL_CFG_UPD BIT(4) +#define RKISP1_CIF_IMG_EFF_CTRL_YCBCR_FULL BIT(5) + +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT 0 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT 1 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT 2 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT 3 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT 4 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT 5 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT 6 +#define RKISP1_CIF_IMG_EFF_CTRL_MODE_MASK 0xE + +/* IMG_EFF_COLOR_SEL */ +#define RKISP1_CIF_IMG_EFF_COLOR_RGB 0 +#define RKISP1_CIF_IMG_EFF_COLOR_B BIT(0) +#define RKISP1_CIF_IMG_EFF_COLOR_G (2 << 0) +#define RKISP1_CIF_IMG_EFF_COLOR_GB (3 << 0) +#define RKISP1_CIF_IMG_EFF_COLOR_R (4 << 0) +#define RKISP1_CIF_IMG_EFF_COLOR_RB (5 << 0) +#define RKISP1_CIF_IMG_EFF_COLOR_RG (6 << 0) +#define RKISP1_CIF_IMG_EFF_COLOR_RGB2 (7 << 0) + +/* MIPI_CTRL */ +#define RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA BIT(0) +#define RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(a) (((a) & 0xF) << 8) +#define RKISP1_CIF_MIPI_CTRL_NUM_LANES(a) (((a) & 0x3) << 12) +#define RKISP1_CIF_MIPI_CTRL_ERR_SOT_HS_SKIP BIT(16) +#define RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP BIT(17) +#define RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA BIT(18) + +/* MIPI_DATA_SEL */ +#define RKISP1_CIF_MIPI_DATA_SEL_VC(a) (((a) & 0x3) << 6) +#define RKISP1_CIF_MIPI_DATA_SEL_DT(a) (((a) & 0x3F) << 0) +/* MIPI DATA_TYPE */ +#define RKISP1_CIF_CSI2_DT_YUV420_8b 0x18 +#define RKISP1_CIF_CSI2_DT_YUV420_10b 0x19 +#define RKISP1_CIF_CSI2_DT_YUV422_8b 0x1E +#define RKISP1_CIF_CSI2_DT_YUV422_10b 0x1F +#define RKISP1_CIF_CSI2_DT_RGB565 0x22 +#define RKISP1_CIF_CSI2_DT_RGB666 0x23 +#define RKISP1_CIF_CSI2_DT_RGB888 0x24 +#define RKISP1_CIF_CSI2_DT_RAW8 0x2A +#define RKISP1_CIF_CSI2_DT_RAW10 0x2B +#define RKISP1_CIF_CSI2_DT_RAW12 0x2C + +/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */ +#define RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(a) (((a) & 0xF) << 0) +#define RKISP1_CIF_MIPI_ERR_SOT(a) (((a) & 0xF) << 4) +#define RKISP1_CIF_MIPI_ERR_SOT_SYNC(a) (((a) & 0xF) << 8) +#define RKISP1_CIF_MIPI_ERR_EOT_SYNC(a) (((a) & 0xF) << 12) +#define RKISP1_CIF_MIPI_ERR_CTRL(a) (((a) & 0xF) << 16) +#define RKISP1_CIF_MIPI_ERR_PROTOCOL BIT(20) +#define RKISP1_CIF_MIPI_ERR_ECC1 BIT(21) +#define RKISP1_CIF_MIPI_ERR_ECC2 BIT(22) +#define RKISP1_CIF_MIPI_ERR_CS BIT(23) +#define RKISP1_CIF_MIPI_FRAME_END BIT(24) +#define RKISP1_CIF_MIPI_ADD_DATA_OVFLW BIT(25) +#define RKISP1_CIF_MIPI_ADD_DATA_WATER_MARK BIT(26) + +#define RKISP1_CIF_MIPI_ERR_CSI (RKISP1_CIF_MIPI_ERR_PROTOCOL | \ + RKISP1_CIF_MIPI_ERR_ECC1 | \ + RKISP1_CIF_MIPI_ERR_ECC2 | \ + RKISP1_CIF_MIPI_ERR_CS) + +#define RKISP1_CIF_MIPI_ERR_DPHY (RKISP1_CIF_MIPI_ERR_SOT(3) | \ + RKISP1_CIF_MIPI_ERR_SOT_SYNC(3) | \ + RKISP1_CIF_MIPI_ERR_EOT_SYNC(3) | \ + RKISP1_CIF_MIPI_ERR_CTRL(3)) + +/* SUPER_IMPOSE */ +#define RKISP1_CIF_SUPER_IMP_CTRL_NORMAL_MODE BIT(0) +#define RKISP1_CIF_SUPER_IMP_CTRL_REF_IMG_MEM BIT(1) +#define RKISP1_CIF_SUPER_IMP_CTRL_TRANSP_DIS BIT(2) + +/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */ +#define RKISP1_CIF_ISP_HIST_PROP_MODE_DIS (0 << 0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_RGB BIT(0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_RED (2 << 0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_GREEN (3 << 0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_BLUE (4 << 0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_LUM (5 << 0) +#define RKISP1_CIF_ISP_HIST_PROP_MODE_MASK 0x7 +#define RKISP1_CIF_ISP_HIST_PREDIV_SET(x) (((x) & 0x7F) << 3) +#define RKISP1_CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3) \ + (((v0) & 0x1F) | (((v1) & 0x1F) << 8) |\ + (((v2) & 0x1F) << 16) | \ + (((v3) & 0x1F) << 24)) + +#define RKISP1_CIF_ISP_HIST_WINDOW_OFFSET_RESERVED 0xFFFFF000 +#define RKISP1_CIF_ISP_HIST_WINDOW_SIZE_RESERVED 0xFFFFF800 +#define RKISP1_CIF_ISP_HIST_WEIGHT_RESERVED 0xE0E0E0E0 +#define RKISP1_CIF_ISP_MAX_HIST_PREDIVIDER 0x0000007F +#define RKISP1_CIF_ISP_HIST_ROW_NUM 5 +#define RKISP1_CIF_ISP_HIST_COLUMN_NUM 5 + +/* AUTO FOCUS MEASUREMENT: ISP_AFM_CTRL */ +#define RKISP1_ISP_AFM_CTRL_ENABLE BIT(0) + +/* SHUTTER CONTROL */ +#define RKISP1_CIF_ISP_SH_CTRL_SH_ENA BIT(0) +#define RKISP1_CIF_ISP_SH_CTRL_REP_EN BIT(1) +#define RKISP1_CIF_ISP_SH_CTRL_SRC_SH_TRIG BIT(2) +#define RKISP1_CIF_ISP_SH_CTRL_EDGE_POS BIT(3) +#define RKISP1_CIF_ISP_SH_CTRL_POL_LOW BIT(4) + +/* FLASH MODULE */ +/* ISP_FLASH_CMD */ +#define RKISP1_CIFFLASH_CMD_PRELIGHT_ON BIT(0) +#define RKISP1_CIFFLASH_CMD_FLASH_ON BIT(1) +#define RKISP1_CIFFLASH_CMD_PRE_FLASH_ON BIT(2) +/* ISP_FLASH_CONFIG */ +#define RKISP1_CIFFLASH_CONFIG_PRELIGHT_END BIT(0) +#define RKISP1_CIFFLASH_CONFIG_VSYNC_POS BIT(1) +#define RKISP1_CIFFLASH_CONFIG_PRELIGHT_LOW BIT(2) +#define RKISP1_CIFFLASH_CONFIG_SRC_FL_TRIG BIT(3) +#define RKISP1_CIFFLASH_CONFIG_DELAY(a) (((a) & 0xF) << 4) + +/* Demosaic: ISP_DEMOSAIC */ +#define RKISP1_CIF_ISP_DEMOSAIC_BYPASS BIT(10) +#define RKISP1_CIF_ISP_DEMOSAIC_TH(x) ((x) & 0xFF) + +/* AWB */ +/* ISP_AWB_PROP */ +#define RKISP1_CIF_ISP_AWB_YMAX_CMP_EN BIT(2) +#define RKISP1_CIF_ISP_AWB_YMAX_READ(x) (((x) >> 2) & 1) +#define RKISP1_CIF_ISP_AWB_MODE_RGB_EN ((1 << 31) | (0x2 << 0)) +#define RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN ((0 << 31) | (0x2 << 0)) +#define RKISP1_CIF_ISP_AWB_MODE_MASK_NONE 0xFFFFFFFC +#define RKISP1_CIF_ISP_AWB_MODE_READ(x) ((x) & 3) +/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G */ +#define RKISP1_CIF_ISP_AWB_GAIN_R_SET(x) (((x) & 0x3FF) << 16) +#define RKISP1_CIF_ISP_AWB_GAIN_R_READ(x) (((x) >> 16) & 0x3FF) +#define RKISP1_CIF_ISP_AWB_GAIN_B_SET(x) ((x) & 0x3FFF) +#define RKISP1_CIF_ISP_AWB_GAIN_B_READ(x) ((x) & 0x3FFF) +/* ISP_AWB_REF */ +#define RKISP1_CIF_ISP_AWB_REF_CR_SET(x) (((x) & 0xFF) << 8) +#define RKISP1_CIF_ISP_AWB_REF_CR_READ(x) (((x) >> 8) & 0xFF) +#define RKISP1_CIF_ISP_AWB_REF_CB_READ(x) ((x) & 0xFF) +/* ISP_AWB_THRESH */ +#define RKISP1_CIF_ISP_AWB_MAX_CS_SET(x) (((x) & 0xFF) << 8) +#define RKISP1_CIF_ISP_AWB_MAX_CS_READ(x) (((x) >> 8) & 0xFF) +#define RKISP1_CIF_ISP_AWB_MIN_C_READ(x) ((x) & 0xFF) +#define RKISP1_CIF_ISP_AWB_MIN_Y_SET(x) (((x) & 0xFF) << 16) +#define RKISP1_CIF_ISP_AWB_MIN_Y_READ(x) (((x) >> 16) & 0xFF) +#define RKISP1_CIF_ISP_AWB_MAX_Y_SET(x) (((x) & 0xFF) << 24) +#define RKISP1_CIF_ISP_AWB_MAX_Y_READ(x) (((x) >> 24) & 0xFF) +/* ISP_AWB_MEAN */ +#define RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(x) ((x) & 0xFF) +#define RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(x) (((x) >> 8) & 0xFF) +#define RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(x) (((x) >> 16) & 0xFF) +/* ISP_AWB_WHITE_CNT */ +#define RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(x) ((x) & 0x3FFFFFF) + +#define RKISP1_CIF_ISP_AWB_GAINS_MAX_VAL 0x000003FF +#define RKISP1_CIF_ISP_AWB_WINDOW_OFFSET_MAX 0x00000FFF +#define RKISP1_CIF_ISP_AWB_WINDOW_MAX_SIZE 0x00001FFF +#define RKISP1_CIF_ISP_AWB_CBCR_MAX_REF 0x000000FF +#define RKISP1_CIF_ISP_AWB_THRES_MAX_YC 0x000000FF + +/* AE */ +/* ISP_EXP_CTRL */ +#define RKISP1_CIF_ISP_EXP_ENA BIT(0) +#define RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP BIT(1) +/* + *'1' luminance calculation according to Y=(R+G+B) x 0.332 (85/256) + *'0' luminance calculation according to Y=16+0.25R+0.5G+0.1094B + */ +#define RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1 BIT(31) + +/* ISP_EXP_H_SIZE */ +#define RKISP1_CIF_ISP_EXP_H_SIZE_SET(x) ((x) & 0x7FF) +#define RKISP1_CIF_ISP_EXP_HEIGHT_MASK 0x000007FF +/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */ +#define RKISP1_CIF_ISP_EXP_V_SIZE_SET(x) ((x) & 0x7FE) + +/* ISP_EXP_H_OFFSET */ +#define RKISP1_CIF_ISP_EXP_H_OFFSET_SET(x) ((x) & 0x1FFF) +#define RKISP1_CIF_ISP_EXP_MAX_HOFFS 2424 +/* ISP_EXP_V_OFFSET */ +#define RKISP1_CIF_ISP_EXP_V_OFFSET_SET(x) ((x) & 0x1FFF) +#define RKISP1_CIF_ISP_EXP_MAX_VOFFS 1806 + +#define RKISP1_CIF_ISP_EXP_ROW_NUM 5 +#define RKISP1_CIF_ISP_EXP_COLUMN_NUM 5 +#define RKISP1_CIF_ISP_EXP_NUM_LUMA_REGS \ + (RKISP1_CIF_ISP_EXP_ROW_NUM * RKISP1_CIF_ISP_EXP_COLUMN_NUM) +#define RKISP1_CIF_ISP_EXP_BLOCK_MAX_HSIZE 516 +#define RKISP1_CIF_ISP_EXP_BLOCK_MIN_HSIZE 35 +#define RKISP1_CIF_ISP_EXP_BLOCK_MAX_VSIZE 390 +#define RKISP1_CIF_ISP_EXP_BLOCK_MIN_VSIZE 28 +#define RKISP1_CIF_ISP_EXP_MAX_HSIZE \ + (RKISP1_CIF_ISP_EXP_BLOCK_MAX_HSIZE * RKISP1_CIF_ISP_EXP_COLUMN_NUM + 1) +#define RKISP1_CIF_ISP_EXP_MIN_HSIZE \ + (RKISP1_CIF_ISP_EXP_BLOCK_MIN_HSIZE * RKISP1_CIF_ISP_EXP_COLUMN_NUM + 1) +#define RKISP1_CIF_ISP_EXP_MAX_VSIZE \ + (RKISP1_CIF_ISP_EXP_BLOCK_MAX_VSIZE * RKISP1_CIF_ISP_EXP_ROW_NUM + 1) +#define RKISP1_CIF_ISP_EXP_MIN_VSIZE \ + (RKISP1_CIF_ISP_EXP_BLOCK_MIN_VSIZE * RKISP1_CIF_ISP_EXP_ROW_NUM + 1) + +/* LSC: ISP_LSC_CTRL */ +#define RKISP1_CIF_ISP_LSC_CTRL_ENA BIT(0) +#define RKISP1_CIF_ISP_LSC_SECT_SIZE_RESERVED 0xFC00FC00 +#define RKISP1_CIF_ISP_LSC_GRAD_RESERVED 0xF000F000 +#define RKISP1_CIF_ISP_LSC_SAMPLE_RESERVED 0xF000F000 +#define RKISP1_CIF_ISP_LSC_TABLE_DATA(v0, v1) \ + (((v0) & 0xFFF) | (((v1) & 0xFFF) << 12)) +#define RKISP1_CIF_ISP_LSC_SECT_SIZE(v0, v1) \ + (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16)) +#define RKISP1_CIF_ISP_LSC_GRAD_SIZE(v0, v1) \ + (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16)) + +/* LSC: ISP_LSC_TABLE_SEL */ +#define RKISP1_CIF_ISP_LSC_TABLE_0 0 +#define RKISP1_CIF_ISP_LSC_TABLE_1 1 + +/* LSC: ISP_LSC_STATUS */ +#define RKISP1_CIF_ISP_LSC_ACTIVE_TABLE BIT(1) +#define RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 0 +#define RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 153 + +/* FLT */ +/* ISP_FILT_MODE */ +#define RKISP1_CIF_ISP_FLT_ENA BIT(0) + +/* + * 0: green filter static mode (active filter factor = FILT_FAC_MID) + * 1: dynamic noise reduction/sharpen Default + */ +#define RKISP1_CIF_ISP_FLT_MODE_DNR BIT(1) +#define RKISP1_CIF_ISP_FLT_MODE_MAX 1 +#define RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(x) (((x) & 0x3) << 4) +#define RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(x) (((x) & 0x3) << 6) +#define RKISP1_CIF_ISP_FLT_CHROMA_MODE_MAX 3 +#define RKISP1_CIF_ISP_FLT_GREEN_STAGE1(x) (((x) & 0xF) << 8) +#define RKISP1_CIF_ISP_FLT_GREEN_STAGE1_MAX 8 +#define RKISP1_CIF_ISP_FLT_THREAD_RESERVED 0xFFFFFC00 +#define RKISP1_CIF_ISP_FLT_FAC_RESERVED 0xFFFFFFC0 +#define RKISP1_CIF_ISP_FLT_LUM_WEIGHT_RESERVED 0xFFF80000 + +#define RKISP1_CIF_ISP_CTK_COEFF_RESERVED 0xFFFFF800 +#define RKISP1_CIF_ISP_XTALK_OFFSET_RESERVED 0xFFFFF000 + +/* GOC */ +#define RKISP1_CIF_ISP_GAMMA_OUT_MODE_EQU BIT(0) +#define RKISP1_CIF_ISP_GOC_MODE_MAX 1 +#define RKISP1_CIF_ISP_GOC_RESERVED 0xFFFFF800 +/* ISP_CTRL BIT 11*/ +#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x) (((x) >> 11) & 1) + +/* DPCC */ +/* ISP_DPCC_MODE */ +#define RKISP1_CIF_ISP_DPCC_ENA BIT(0) +#define RKISP1_CIF_ISP_DPCC_MODE_MAX 0x07 +#define RKISP1_CIF_ISP_DPCC_OUTPUTMODE_MAX 0x0F +#define RKISP1_CIF_ISP_DPCC_SETUSE_MAX 0x0F +#define RKISP1_CIF_ISP_DPCC_METHODS_SET_RESERVED 0xFFFFE000 +#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_RESERVED 0xFFFF0000 +#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED 0xFFFFC0C0 +#define RKISP1_CIF_ISP_DPCC_PG_FAC_RESERVED 0xFFFFC0C0 +#define RKISP1_CIF_ISP_DPCC_RND_THRESH_RESERVED 0xFFFF0000 +#define RKISP1_CIF_ISP_DPCC_RG_FAC_RESERVED 0xFFFFC0C0 +#define RKISP1_CIF_ISP_DPCC_RO_LIMIT_RESERVED 0xFFFFF000 +#define RKISP1_CIF_ISP_DPCC_RND_OFFS_RESERVED 0xFFFFF000 + +/* BLS */ +/* ISP_BLS_CTRL */ +#define RKISP1_CIF_ISP_BLS_ENA BIT(0) +#define RKISP1_CIF_ISP_BLS_MODE_MEASURED BIT(1) +#define RKISP1_CIF_ISP_BLS_MODE_FIXED 0 +#define RKISP1_CIF_ISP_BLS_WINDOW_1 BIT(2) +#define RKISP1_CIF_ISP_BLS_WINDOW_2 (2 << 2) + +/* GAMMA-IN */ +#define RKISP1_CIFISP_DEGAMMA_X_RESERVED \ + ((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\ + (1 << 15) | (1 << 11) | (1 << 7) | (1 << 3)) +#define RKISP1_CIFISP_DEGAMMA_Y_RESERVED 0xFFFFF000 + +/* AFM */ +#define RKISP1_CIF_ISP_AFM_ENA BIT(0) +#define RKISP1_CIF_ISP_AFM_THRES_RESERVED 0xFFFF0000 +#define RKISP1_CIF_ISP_AFM_VAR_SHIFT_RESERVED 0xFFF8FFF8 +#define RKISP1_CIF_ISP_AFM_WINDOW_X_RESERVED 0xE000 +#define RKISP1_CIF_ISP_AFM_WINDOW_Y_RESERVED 0xF000 +#define RKISP1_CIF_ISP_AFM_WINDOW_X_MIN 0x5 +#define RKISP1_CIF_ISP_AFM_WINDOW_Y_MIN 0x2 +#define RKISP1_CIF_ISP_AFM_WINDOW_X(x) (((x) & 0x1FFF) << 16) +#define RKISP1_CIF_ISP_AFM_WINDOW_Y(x) ((x) & 0x1FFF) + +/* DPF */ +#define RKISP1_CIF_ISP_DPF_MODE_EN BIT(0) +#define RKISP1_CIF_ISP_DPF_MODE_B_FLT_DIS BIT(1) +#define RKISP1_CIF_ISP_DPF_MODE_GB_FLT_DIS BIT(2) +#define RKISP1_CIF_ISP_DPF_MODE_GR_FLT_DIS BIT(3) +#define RKISP1_CIF_ISP_DPF_MODE_R_FLT_DIS BIT(4) +#define RKISP1_CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9 BIT(5) +#define RKISP1_CIF_ISP_DPF_MODE_NLL_SEGMENTATION BIT(6) +#define RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP BIT(7) +#define RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP BIT(8) +#define RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN BIT(9) +#define RKISP1_CIF_ISP_DPF_NF_GAIN_RESERVED 0xFFFFF000 +#define RKISP1_CIF_ISP_DPF_SPATIAL_COEFF_MAX 0x1F +#define RKISP1_CIF_ISP_DPF_NLL_COEFF_N_MAX 0x3FF + +/* =================================================================== */ +/* CIF Registers */ +/* =================================================================== */ +#define RKISP1_CIF_CTRL_BASE 0x00000000 +#define RKISP1_CIF_CCL (RKISP1_CIF_CTRL_BASE + 0x00000000) +#define RKISP1_CIF_VI_ID (RKISP1_CIF_CTRL_BASE + 0x00000008) +#define RKISP1_CIF_ICCL (RKISP1_CIF_CTRL_BASE + 0x00000010) +#define RKISP1_CIF_IRCL (RKISP1_CIF_CTRL_BASE + 0x00000014) +#define RKISP1_CIF_VI_DPCL (RKISP1_CIF_CTRL_BASE + 0x00000018) + +#define RKISP1_CIF_IMG_EFF_BASE 0x00000200 +#define RKISP1_CIF_IMG_EFF_CTRL (RKISP1_CIF_IMG_EFF_BASE + 0x00000000) +#define RKISP1_CIF_IMG_EFF_COLOR_SEL (RKISP1_CIF_IMG_EFF_BASE + 0x00000004) +#define RKISP1_CIF_IMG_EFF_MAT_1 (RKISP1_CIF_IMG_EFF_BASE + 0x00000008) +#define RKISP1_CIF_IMG_EFF_MAT_2 (RKISP1_CIF_IMG_EFF_BASE + 0x0000000C) +#define RKISP1_CIF_IMG_EFF_MAT_3 (RKISP1_CIF_IMG_EFF_BASE + 0x00000010) +#define RKISP1_CIF_IMG_EFF_MAT_4 (RKISP1_CIF_IMG_EFF_BASE + 0x00000014) +#define RKISP1_CIF_IMG_EFF_MAT_5 (RKISP1_CIF_IMG_EFF_BASE + 0x00000018) +#define RKISP1_CIF_IMG_EFF_TINT (RKISP1_CIF_IMG_EFF_BASE + 0x0000001C) +#define RKISP1_CIF_IMG_EFF_CTRL_SHD (RKISP1_CIF_IMG_EFF_BASE + 0x00000020) +#define RKISP1_CIF_IMG_EFF_SHARPEN (RKISP1_CIF_IMG_EFF_BASE + 0x00000024) + +#define RKISP1_CIF_SUPER_IMP_BASE 0x00000300 +#define RKISP1_CIF_SUPER_IMP_CTRL (RKISP1_CIF_SUPER_IMP_BASE + 0x00000000) +#define RKISP1_CIF_SUPER_IMP_OFFSET_X (RKISP1_CIF_SUPER_IMP_BASE + 0x00000004) +#define RKISP1_CIF_SUPER_IMP_OFFSET_Y (RKISP1_CIF_SUPER_IMP_BASE + 0x00000008) +#define RKISP1_CIF_SUPER_IMP_COLOR_Y (RKISP1_CIF_SUPER_IMP_BASE + 0x0000000C) +#define RKISP1_CIF_SUPER_IMP_COLOR_CB (RKISP1_CIF_SUPER_IMP_BASE + 0x00000010) +#define RKISP1_CIF_SUPER_IMP_COLOR_CR (RKISP1_CIF_SUPER_IMP_BASE + 0x00000014) + +#define RKISP1_CIF_ISP_BASE 0x00000400 +#define RKISP1_CIF_ISP_CTRL (RKISP1_CIF_ISP_BASE + 0x00000000) +#define RKISP1_CIF_ISP_ACQ_PROP (RKISP1_CIF_ISP_BASE + 0x00000004) +#define RKISP1_CIF_ISP_ACQ_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000008) +#define RKISP1_CIF_ISP_ACQ_V_OFFS (RKISP1_CIF_ISP_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_ACQ_H_SIZE (RKISP1_CIF_ISP_BASE + 0x00000010) +#define RKISP1_CIF_ISP_ACQ_V_SIZE (RKISP1_CIF_ISP_BASE + 0x00000014) +#define RKISP1_CIF_ISP_ACQ_NR_FRAMES (RKISP1_CIF_ISP_BASE + 0x00000018) +#define RKISP1_CIF_ISP_GAMMA_DX_LO (RKISP1_CIF_ISP_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_GAMMA_DX_HI (RKISP1_CIF_ISP_BASE + 0x00000020) +#define RKISP1_CIF_ISP_GAMMA_R_Y0 (RKISP1_CIF_ISP_BASE + 0x00000024) +#define RKISP1_CIF_ISP_GAMMA_R_Y1 (RKISP1_CIF_ISP_BASE + 0x00000028) +#define RKISP1_CIF_ISP_GAMMA_R_Y2 (RKISP1_CIF_ISP_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_GAMMA_R_Y3 (RKISP1_CIF_ISP_BASE + 0x00000030) +#define RKISP1_CIF_ISP_GAMMA_R_Y4 (RKISP1_CIF_ISP_BASE + 0x00000034) +#define RKISP1_CIF_ISP_GAMMA_R_Y5 (RKISP1_CIF_ISP_BASE + 0x00000038) +#define RKISP1_CIF_ISP_GAMMA_R_Y6 (RKISP1_CIF_ISP_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_GAMMA_R_Y7 (RKISP1_CIF_ISP_BASE + 0x00000040) +#define RKISP1_CIF_ISP_GAMMA_R_Y8 (RKISP1_CIF_ISP_BASE + 0x00000044) +#define RKISP1_CIF_ISP_GAMMA_R_Y9 (RKISP1_CIF_ISP_BASE + 0x00000048) +#define RKISP1_CIF_ISP_GAMMA_R_Y10 (RKISP1_CIF_ISP_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_GAMMA_R_Y11 (RKISP1_CIF_ISP_BASE + 0x00000050) +#define RKISP1_CIF_ISP_GAMMA_R_Y12 (RKISP1_CIF_ISP_BASE + 0x00000054) +#define RKISP1_CIF_ISP_GAMMA_R_Y13 (RKISP1_CIF_ISP_BASE + 0x00000058) +#define RKISP1_CIF_ISP_GAMMA_R_Y14 (RKISP1_CIF_ISP_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_GAMMA_R_Y15 (RKISP1_CIF_ISP_BASE + 0x00000060) +#define RKISP1_CIF_ISP_GAMMA_R_Y16 (RKISP1_CIF_ISP_BASE + 0x00000064) +#define RKISP1_CIF_ISP_GAMMA_G_Y0 (RKISP1_CIF_ISP_BASE + 0x00000068) +#define RKISP1_CIF_ISP_GAMMA_G_Y1 (RKISP1_CIF_ISP_BASE + 0x0000006C) +#define RKISP1_CIF_ISP_GAMMA_G_Y2 (RKISP1_CIF_ISP_BASE + 0x00000070) +#define RKISP1_CIF_ISP_GAMMA_G_Y3 (RKISP1_CIF_ISP_BASE + 0x00000074) +#define RKISP1_CIF_ISP_GAMMA_G_Y4 (RKISP1_CIF_ISP_BASE + 0x00000078) +#define RKISP1_CIF_ISP_GAMMA_G_Y5 (RKISP1_CIF_ISP_BASE + 0x0000007C) +#define RKISP1_CIF_ISP_GAMMA_G_Y6 (RKISP1_CIF_ISP_BASE + 0x00000080) +#define RKISP1_CIF_ISP_GAMMA_G_Y7 (RKISP1_CIF_ISP_BASE + 0x00000084) +#define RKISP1_CIF_ISP_GAMMA_G_Y8 (RKISP1_CIF_ISP_BASE + 0x00000088) +#define RKISP1_CIF_ISP_GAMMA_G_Y9 (RKISP1_CIF_ISP_BASE + 0x0000008C) +#define RKISP1_CIF_ISP_GAMMA_G_Y10 (RKISP1_CIF_ISP_BASE + 0x00000090) +#define RKISP1_CIF_ISP_GAMMA_G_Y11 (RKISP1_CIF_ISP_BASE + 0x00000094) +#define RKISP1_CIF_ISP_GAMMA_G_Y12 (RKISP1_CIF_ISP_BASE + 0x00000098) +#define RKISP1_CIF_ISP_GAMMA_G_Y13 (RKISP1_CIF_ISP_BASE + 0x0000009C) +#define RKISP1_CIF_ISP_GAMMA_G_Y14 (RKISP1_CIF_ISP_BASE + 0x000000A0) +#define RKISP1_CIF_ISP_GAMMA_G_Y15 (RKISP1_CIF_ISP_BASE + 0x000000A4) +#define RKISP1_CIF_ISP_GAMMA_G_Y16 (RKISP1_CIF_ISP_BASE + 0x000000A8) +#define RKISP1_CIF_ISP_GAMMA_B_Y0 (RKISP1_CIF_ISP_BASE + 0x000000AC) +#define RKISP1_CIF_ISP_GAMMA_B_Y1 (RKISP1_CIF_ISP_BASE + 0x000000B0) +#define RKISP1_CIF_ISP_GAMMA_B_Y2 (RKISP1_CIF_ISP_BASE + 0x000000B4) +#define RKISP1_CIF_ISP_GAMMA_B_Y3 (RKISP1_CIF_ISP_BASE + 0x000000B8) +#define RKISP1_CIF_ISP_GAMMA_B_Y4 (RKISP1_CIF_ISP_BASE + 0x000000BC) +#define RKISP1_CIF_ISP_GAMMA_B_Y5 (RKISP1_CIF_ISP_BASE + 0x000000C0) +#define RKISP1_CIF_ISP_GAMMA_B_Y6 (RKISP1_CIF_ISP_BASE + 0x000000C4) +#define RKISP1_CIF_ISP_GAMMA_B_Y7 (RKISP1_CIF_ISP_BASE + 0x000000C8) +#define RKISP1_CIF_ISP_GAMMA_B_Y8 (RKISP1_CIF_ISP_BASE + 0x000000CC) +#define RKISP1_CIF_ISP_GAMMA_B_Y9 (RKISP1_CIF_ISP_BASE + 0x000000D0) +#define RKISP1_CIF_ISP_GAMMA_B_Y10 (RKISP1_CIF_ISP_BASE + 0x000000D4) +#define RKISP1_CIF_ISP_GAMMA_B_Y11 (RKISP1_CIF_ISP_BASE + 0x000000D8) +#define RKISP1_CIF_ISP_GAMMA_B_Y12 (RKISP1_CIF_ISP_BASE + 0x000000DC) +#define RKISP1_CIF_ISP_GAMMA_B_Y13 (RKISP1_CIF_ISP_BASE + 0x000000E0) +#define RKISP1_CIF_ISP_GAMMA_B_Y14 (RKISP1_CIF_ISP_BASE + 0x000000E4) +#define RKISP1_CIF_ISP_GAMMA_B_Y15 (RKISP1_CIF_ISP_BASE + 0x000000E8) +#define RKISP1_CIF_ISP_GAMMA_B_Y16 (RKISP1_CIF_ISP_BASE + 0x000000EC) +#define RKISP1_CIF_ISP_AWB_PROP (RKISP1_CIF_ISP_BASE + 0x00000110) +#define RKISP1_CIF_ISP_AWB_WND_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000114) +#define RKISP1_CIF_ISP_AWB_WND_V_OFFS (RKISP1_CIF_ISP_BASE + 0x00000118) +#define RKISP1_CIF_ISP_AWB_WND_H_SIZE (RKISP1_CIF_ISP_BASE + 0x0000011C) +#define RKISP1_CIF_ISP_AWB_WND_V_SIZE (RKISP1_CIF_ISP_BASE + 0x00000120) +#define RKISP1_CIF_ISP_AWB_FRAMES (RKISP1_CIF_ISP_BASE + 0x00000124) +#define RKISP1_CIF_ISP_AWB_REF (RKISP1_CIF_ISP_BASE + 0x00000128) +#define RKISP1_CIF_ISP_AWB_THRESH (RKISP1_CIF_ISP_BASE + 0x0000012C) +#define RKISP1_CIF_ISP_AWB_GAIN_G (RKISP1_CIF_ISP_BASE + 0x00000138) +#define RKISP1_CIF_ISP_AWB_GAIN_RB (RKISP1_CIF_ISP_BASE + 0x0000013C) +#define RKISP1_CIF_ISP_AWB_WHITE_CNT (RKISP1_CIF_ISP_BASE + 0x00000140) +#define RKISP1_CIF_ISP_AWB_MEAN (RKISP1_CIF_ISP_BASE + 0x00000144) +#define RKISP1_CIF_ISP_CC_COEFF_0 (RKISP1_CIF_ISP_BASE + 0x00000170) +#define RKISP1_CIF_ISP_CC_COEFF_1 (RKISP1_CIF_ISP_BASE + 0x00000174) +#define RKISP1_CIF_ISP_CC_COEFF_2 (RKISP1_CIF_ISP_BASE + 0x00000178) +#define RKISP1_CIF_ISP_CC_COEFF_3 (RKISP1_CIF_ISP_BASE + 0x0000017C) +#define RKISP1_CIF_ISP_CC_COEFF_4 (RKISP1_CIF_ISP_BASE + 0x00000180) +#define RKISP1_CIF_ISP_CC_COEFF_5 (RKISP1_CIF_ISP_BASE + 0x00000184) +#define RKISP1_CIF_ISP_CC_COEFF_6 (RKISP1_CIF_ISP_BASE + 0x00000188) +#define RKISP1_CIF_ISP_CC_COEFF_7 (RKISP1_CIF_ISP_BASE + 0x0000018C) +#define RKISP1_CIF_ISP_CC_COEFF_8 (RKISP1_CIF_ISP_BASE + 0x00000190) +#define RKISP1_CIF_ISP_OUT_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000194) +#define RKISP1_CIF_ISP_OUT_V_OFFS (RKISP1_CIF_ISP_BASE + 0x00000198) +#define RKISP1_CIF_ISP_OUT_H_SIZE (RKISP1_CIF_ISP_BASE + 0x0000019C) +#define RKISP1_CIF_ISP_OUT_V_SIZE (RKISP1_CIF_ISP_BASE + 0x000001A0) +#define RKISP1_CIF_ISP_DEMOSAIC (RKISP1_CIF_ISP_BASE + 0x000001A4) +#define RKISP1_CIF_ISP_FLAGS_SHD (RKISP1_CIF_ISP_BASE + 0x000001A8) +#define RKISP1_CIF_ISP_OUT_H_OFFS_SHD (RKISP1_CIF_ISP_BASE + 0x000001AC) +#define RKISP1_CIF_ISP_OUT_V_OFFS_SHD (RKISP1_CIF_ISP_BASE + 0x000001B0) +#define RKISP1_CIF_ISP_OUT_H_SIZE_SHD (RKISP1_CIF_ISP_BASE + 0x000001B4) +#define RKISP1_CIF_ISP_OUT_V_SIZE_SHD (RKISP1_CIF_ISP_BASE + 0x000001B8) +#define RKISP1_CIF_ISP_IMSC (RKISP1_CIF_ISP_BASE + 0x000001BC) +#define RKISP1_CIF_ISP_RIS (RKISP1_CIF_ISP_BASE + 0x000001C0) +#define RKISP1_CIF_ISP_MIS (RKISP1_CIF_ISP_BASE + 0x000001C4) +#define RKISP1_CIF_ISP_ICR (RKISP1_CIF_ISP_BASE + 0x000001C8) +#define RKISP1_CIF_ISP_ISR (RKISP1_CIF_ISP_BASE + 0x000001CC) +#define RKISP1_CIF_ISP_CT_COEFF_0 (RKISP1_CIF_ISP_BASE + 0x000001D0) +#define RKISP1_CIF_ISP_CT_COEFF_1 (RKISP1_CIF_ISP_BASE + 0x000001D4) +#define RKISP1_CIF_ISP_CT_COEFF_2 (RKISP1_CIF_ISP_BASE + 0x000001D8) +#define RKISP1_CIF_ISP_CT_COEFF_3 (RKISP1_CIF_ISP_BASE + 0x000001DC) +#define RKISP1_CIF_ISP_CT_COEFF_4 (RKISP1_CIF_ISP_BASE + 0x000001E0) +#define RKISP1_CIF_ISP_CT_COEFF_5 (RKISP1_CIF_ISP_BASE + 0x000001E4) +#define RKISP1_CIF_ISP_CT_COEFF_6 (RKISP1_CIF_ISP_BASE + 0x000001E8) +#define RKISP1_CIF_ISP_CT_COEFF_7 (RKISP1_CIF_ISP_BASE + 0x000001EC) +#define RKISP1_CIF_ISP_CT_COEFF_8 (RKISP1_CIF_ISP_BASE + 0x000001F0) +#define RKISP1_CIF_ISP_GAMMA_OUT_MODE (RKISP1_CIF_ISP_BASE + 0x000001F4) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_0 (RKISP1_CIF_ISP_BASE + 0x000001F8) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_1 (RKISP1_CIF_ISP_BASE + 0x000001FC) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_2 (RKISP1_CIF_ISP_BASE + 0x00000200) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_3 (RKISP1_CIF_ISP_BASE + 0x00000204) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_4 (RKISP1_CIF_ISP_BASE + 0x00000208) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_5 (RKISP1_CIF_ISP_BASE + 0x0000020C) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_6 (RKISP1_CIF_ISP_BASE + 0x00000210) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_7 (RKISP1_CIF_ISP_BASE + 0x00000214) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_8 (RKISP1_CIF_ISP_BASE + 0x00000218) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_9 (RKISP1_CIF_ISP_BASE + 0x0000021C) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_10 (RKISP1_CIF_ISP_BASE + 0x00000220) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_11 (RKISP1_CIF_ISP_BASE + 0x00000224) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_12 (RKISP1_CIF_ISP_BASE + 0x00000228) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_13 (RKISP1_CIF_ISP_BASE + 0x0000022C) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_14 (RKISP1_CIF_ISP_BASE + 0x00000230) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_15 (RKISP1_CIF_ISP_BASE + 0x00000234) +#define RKISP1_CIF_ISP_GAMMA_OUT_Y_16 (RKISP1_CIF_ISP_BASE + 0x00000238) +#define RKISP1_CIF_ISP_ERR (RKISP1_CIF_ISP_BASE + 0x0000023C) +#define RKISP1_CIF_ISP_ERR_CLR (RKISP1_CIF_ISP_BASE + 0x00000240) +#define RKISP1_CIF_ISP_FRAME_COUNT (RKISP1_CIF_ISP_BASE + 0x00000244) +#define RKISP1_CIF_ISP_CT_OFFSET_R (RKISP1_CIF_ISP_BASE + 0x00000248) +#define RKISP1_CIF_ISP_CT_OFFSET_G (RKISP1_CIF_ISP_BASE + 0x0000024C) +#define RKISP1_CIF_ISP_CT_OFFSET_B (RKISP1_CIF_ISP_BASE + 0x00000250) + +#define RKISP1_CIF_ISP_FLASH_BASE 0x00000660 +#define RKISP1_CIF_ISP_FLASH_CMD (RKISP1_CIF_ISP_FLASH_BASE + 0x00000000) +#define RKISP1_CIF_ISP_FLASH_CONFIG (RKISP1_CIF_ISP_FLASH_BASE + 0x00000004) +#define RKISP1_CIF_ISP_FLASH_PREDIV (RKISP1_CIF_ISP_FLASH_BASE + 0x00000008) +#define RKISP1_CIF_ISP_FLASH_DELAY (RKISP1_CIF_ISP_FLASH_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_FLASH_TIME (RKISP1_CIF_ISP_FLASH_BASE + 0x00000010) +#define RKISP1_CIF_ISP_FLASH_MAXP (RKISP1_CIF_ISP_FLASH_BASE + 0x00000014) + +#define RKISP1_CIF_ISP_SH_BASE 0x00000680 +#define RKISP1_CIF_ISP_SH_CTRL (RKISP1_CIF_ISP_SH_BASE + 0x00000000) +#define RKISP1_CIF_ISP_SH_PREDIV (RKISP1_CIF_ISP_SH_BASE + 0x00000004) +#define RKISP1_CIF_ISP_SH_DELAY (RKISP1_CIF_ISP_SH_BASE + 0x00000008) +#define RKISP1_CIF_ISP_SH_TIME (RKISP1_CIF_ISP_SH_BASE + 0x0000000C) + +#define RKISP1_CIF_C_PROC_BASE 0x00000800 +#define RKISP1_CIF_C_PROC_CTRL (RKISP1_CIF_C_PROC_BASE + 0x00000000) +#define RKISP1_CIF_C_PROC_CONTRAST (RKISP1_CIF_C_PROC_BASE + 0x00000004) +#define RKISP1_CIF_C_PROC_BRIGHTNESS (RKISP1_CIF_C_PROC_BASE + 0x00000008) +#define RKISP1_CIF_C_PROC_SATURATION (RKISP1_CIF_C_PROC_BASE + 0x0000000C) +#define RKISP1_CIF_C_PROC_HUE (RKISP1_CIF_C_PROC_BASE + 0x00000010) + +#define RKISP1_CIF_DUAL_CROP_BASE 0x00000880 +#define RKISP1_CIF_DUAL_CROP_CTRL (RKISP1_CIF_DUAL_CROP_BASE + 0x00000000) +#define RKISP1_CIF_DUAL_CROP_M_H_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000004) +#define RKISP1_CIF_DUAL_CROP_M_V_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000008) +#define RKISP1_CIF_DUAL_CROP_M_H_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x0000000C) +#define RKISP1_CIF_DUAL_CROP_M_V_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x00000010) +#define RKISP1_CIF_DUAL_CROP_S_H_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000014) +#define RKISP1_CIF_DUAL_CROP_S_V_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000018) +#define RKISP1_CIF_DUAL_CROP_S_H_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x0000001C) +#define RKISP1_CIF_DUAL_CROP_S_V_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x00000020) +#define RKISP1_CIF_DUAL_CROP_M_H_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000024) +#define RKISP1_CIF_DUAL_CROP_M_V_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000028) +#define RKISP1_CIF_DUAL_CROP_M_H_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x0000002C) +#define RKISP1_CIF_DUAL_CROP_M_V_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000030) +#define RKISP1_CIF_DUAL_CROP_S_H_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000034) +#define RKISP1_CIF_DUAL_CROP_S_V_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000038) +#define RKISP1_CIF_DUAL_CROP_S_H_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x0000003C) +#define RKISP1_CIF_DUAL_CROP_S_V_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000040) + +#define RKISP1_CIF_MRSZ_BASE 0x00000C00 +#define RKISP1_CIF_MRSZ_CTRL (RKISP1_CIF_MRSZ_BASE + 0x00000000) +#define RKISP1_CIF_MRSZ_SCALE_HY (RKISP1_CIF_MRSZ_BASE + 0x00000004) +#define RKISP1_CIF_MRSZ_SCALE_HCB (RKISP1_CIF_MRSZ_BASE + 0x00000008) +#define RKISP1_CIF_MRSZ_SCALE_HCR (RKISP1_CIF_MRSZ_BASE + 0x0000000C) +#define RKISP1_CIF_MRSZ_SCALE_VY (RKISP1_CIF_MRSZ_BASE + 0x00000010) +#define RKISP1_CIF_MRSZ_SCALE_VC (RKISP1_CIF_MRSZ_BASE + 0x00000014) +#define RKISP1_CIF_MRSZ_PHASE_HY (RKISP1_CIF_MRSZ_BASE + 0x00000018) +#define RKISP1_CIF_MRSZ_PHASE_HC (RKISP1_CIF_MRSZ_BASE + 0x0000001C) +#define RKISP1_CIF_MRSZ_PHASE_VY (RKISP1_CIF_MRSZ_BASE + 0x00000020) +#define RKISP1_CIF_MRSZ_PHASE_VC (RKISP1_CIF_MRSZ_BASE + 0x00000024) +#define RKISP1_CIF_MRSZ_SCALE_LUT_ADDR (RKISP1_CIF_MRSZ_BASE + 0x00000028) +#define RKISP1_CIF_MRSZ_SCALE_LUT (RKISP1_CIF_MRSZ_BASE + 0x0000002C) +#define RKISP1_CIF_MRSZ_CTRL_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000030) +#define RKISP1_CIF_MRSZ_SCALE_HY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000034) +#define RKISP1_CIF_MRSZ_SCALE_HCB_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000038) +#define RKISP1_CIF_MRSZ_SCALE_HCR_SHD (RKISP1_CIF_MRSZ_BASE + 0x0000003C) +#define RKISP1_CIF_MRSZ_SCALE_VY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000040) +#define RKISP1_CIF_MRSZ_SCALE_VC_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000044) +#define RKISP1_CIF_MRSZ_PHASE_HY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000048) +#define RKISP1_CIF_MRSZ_PHASE_HC_SHD (RKISP1_CIF_MRSZ_BASE + 0x0000004C) +#define RKISP1_CIF_MRSZ_PHASE_VY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000050) +#define RKISP1_CIF_MRSZ_PHASE_VC_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000054) + +#define RKISP1_CIF_SRSZ_BASE 0x00001000 +#define RKISP1_CIF_SRSZ_CTRL (RKISP1_CIF_SRSZ_BASE + 0x00000000) +#define RKISP1_CIF_SRSZ_SCALE_HY (RKISP1_CIF_SRSZ_BASE + 0x00000004) +#define RKISP1_CIF_SRSZ_SCALE_HCB (RKISP1_CIF_SRSZ_BASE + 0x00000008) +#define RKISP1_CIF_SRSZ_SCALE_HCR (RKISP1_CIF_SRSZ_BASE + 0x0000000C) +#define RKISP1_CIF_SRSZ_SCALE_VY (RKISP1_CIF_SRSZ_BASE + 0x00000010) +#define RKISP1_CIF_SRSZ_SCALE_VC (RKISP1_CIF_SRSZ_BASE + 0x00000014) +#define RKISP1_CIF_SRSZ_PHASE_HY (RKISP1_CIF_SRSZ_BASE + 0x00000018) +#define RKISP1_CIF_SRSZ_PHASE_HC (RKISP1_CIF_SRSZ_BASE + 0x0000001C) +#define RKISP1_CIF_SRSZ_PHASE_VY (RKISP1_CIF_SRSZ_BASE + 0x00000020) +#define RKISP1_CIF_SRSZ_PHASE_VC (RKISP1_CIF_SRSZ_BASE + 0x00000024) +#define RKISP1_CIF_SRSZ_SCALE_LUT_ADDR (RKISP1_CIF_SRSZ_BASE + 0x00000028) +#define RKISP1_CIF_SRSZ_SCALE_LUT (RKISP1_CIF_SRSZ_BASE + 0x0000002C) +#define RKISP1_CIF_SRSZ_CTRL_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000030) +#define RKISP1_CIF_SRSZ_SCALE_HY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000034) +#define RKISP1_CIF_SRSZ_SCALE_HCB_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000038) +#define RKISP1_CIF_SRSZ_SCALE_HCR_SHD (RKISP1_CIF_SRSZ_BASE + 0x0000003C) +#define RKISP1_CIF_SRSZ_SCALE_VY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000040) +#define RKISP1_CIF_SRSZ_SCALE_VC_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000044) +#define RKISP1_CIF_SRSZ_PHASE_HY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000048) +#define RKISP1_CIF_SRSZ_PHASE_HC_SHD (RKISP1_CIF_SRSZ_BASE + 0x0000004C) +#define RKISP1_CIF_SRSZ_PHASE_VY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000050) +#define RKISP1_CIF_SRSZ_PHASE_VC_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000054) + +#define RKISP1_CIF_MI_BASE 0x00001400 +#define RKISP1_CIF_MI_CTRL (RKISP1_CIF_MI_BASE + 0x00000000) +#define RKISP1_CIF_MI_INIT (RKISP1_CIF_MI_BASE + 0x00000004) +#define RKISP1_CIF_MI_MP_Y_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000008) +#define RKISP1_CIF_MI_MP_Y_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x0000000C) +#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000010) +#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000014) +#define RKISP1_CIF_MI_MP_Y_IRQ_OFFS_INIT (RKISP1_CIF_MI_BASE + 0x00000018) +#define RKISP1_CIF_MI_MP_CB_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000001C) +#define RKISP1_CIF_MI_MP_CB_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000020) +#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000024) +#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000028) +#define RKISP1_CIF_MI_MP_CR_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000002C) +#define RKISP1_CIF_MI_MP_CR_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000030) +#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000034) +#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000038) +#define RKISP1_CIF_MI_SP_Y_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000003C) +#define RKISP1_CIF_MI_SP_Y_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000040) +#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000044) +#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000048) +#define RKISP1_CIF_MI_SP_Y_LLENGTH (RKISP1_CIF_MI_BASE + 0x0000004C) +#define RKISP1_CIF_MI_SP_CB_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000050) +#define RKISP1_CIF_MI_SP_CB_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000054) +#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000058) +#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x0000005C) +#define RKISP1_CIF_MI_SP_CR_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000060) +#define RKISP1_CIF_MI_SP_CR_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000064) +#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000068) +#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x0000006C) +#define RKISP1_CIF_MI_BYTE_CNT (RKISP1_CIF_MI_BASE + 0x00000070) +#define RKISP1_CIF_MI_CTRL_SHD (RKISP1_CIF_MI_BASE + 0x00000074) +#define RKISP1_CIF_MI_MP_Y_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000078) +#define RKISP1_CIF_MI_MP_Y_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x0000007C) +#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x00000080) +#define RKISP1_CIF_MI_MP_Y_IRQ_OFFS_SHD (RKISP1_CIF_MI_BASE + 0x00000084) +#define RKISP1_CIF_MI_MP_CB_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000088) +#define RKISP1_CIF_MI_MP_CB_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x0000008C) +#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x00000090) +#define RKISP1_CIF_MI_MP_CR_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000094) +#define RKISP1_CIF_MI_MP_CR_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x00000098) +#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x0000009C) +#define RKISP1_CIF_MI_SP_Y_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000A0) +#define RKISP1_CIF_MI_SP_Y_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000A4) +#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000A8) +#define RKISP1_CIF_MI_SP_CB_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000B0) +#define RKISP1_CIF_MI_SP_CB_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000B4) +#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000B8) +#define RKISP1_CIF_MI_SP_CR_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000BC) +#define RKISP1_CIF_MI_SP_CR_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000C0) +#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000C4) +#define RKISP1_CIF_MI_DMA_Y_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000C8) +#define RKISP1_CIF_MI_DMA_Y_PIC_WIDTH (RKISP1_CIF_MI_BASE + 0x000000CC) +#define RKISP1_CIF_MI_DMA_Y_LLENGTH (RKISP1_CIF_MI_BASE + 0x000000D0) +#define RKISP1_CIF_MI_DMA_Y_PIC_SIZE (RKISP1_CIF_MI_BASE + 0x000000D4) +#define RKISP1_CIF_MI_DMA_CB_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000D8) +#define RKISP1_CIF_MI_DMA_CR_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000E8) +#define RKISP1_CIF_MI_IMSC (RKISP1_CIF_MI_BASE + 0x000000F8) +#define RKISP1_CIF_MI_RIS (RKISP1_CIF_MI_BASE + 0x000000FC) +#define RKISP1_CIF_MI_MIS (RKISP1_CIF_MI_BASE + 0x00000100) +#define RKISP1_CIF_MI_ICR (RKISP1_CIF_MI_BASE + 0x00000104) +#define RKISP1_CIF_MI_ISR (RKISP1_CIF_MI_BASE + 0x00000108) +#define RKISP1_CIF_MI_STATUS (RKISP1_CIF_MI_BASE + 0x0000010C) +#define RKISP1_CIF_MI_STATUS_CLR (RKISP1_CIF_MI_BASE + 0x00000110) +#define RKISP1_CIF_MI_SP_Y_PIC_WIDTH (RKISP1_CIF_MI_BASE + 0x00000114) +#define RKISP1_CIF_MI_SP_Y_PIC_HEIGHT (RKISP1_CIF_MI_BASE + 0x00000118) +#define RKISP1_CIF_MI_SP_Y_PIC_SIZE (RKISP1_CIF_MI_BASE + 0x0000011C) +#define RKISP1_CIF_MI_DMA_CTRL (RKISP1_CIF_MI_BASE + 0x00000120) +#define RKISP1_CIF_MI_DMA_START (RKISP1_CIF_MI_BASE + 0x00000124) +#define RKISP1_CIF_MI_DMA_STATUS (RKISP1_CIF_MI_BASE + 0x00000128) +#define RKISP1_CIF_MI_PIXEL_COUNT (RKISP1_CIF_MI_BASE + 0x0000012C) +#define RKISP1_CIF_MI_MP_Y_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000130) +#define RKISP1_CIF_MI_MP_CB_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000134) +#define RKISP1_CIF_MI_MP_CR_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000138) +#define RKISP1_CIF_MI_SP_Y_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x0000013C) +#define RKISP1_CIF_MI_SP_CB_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000140) +#define RKISP1_CIF_MI_SP_CR_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000144) +#define RKISP1_CIF_MI_XTD_FORMAT_CTRL (RKISP1_CIF_MI_BASE + 0x00000148) + +#define RKISP1_CIF_SMIA_BASE 0x00001A00 +#define RKISP1_CIF_SMIA_CTRL (RKISP1_CIF_SMIA_BASE + 0x00000000) +#define RKISP1_CIF_SMIA_STATUS (RKISP1_CIF_SMIA_BASE + 0x00000004) +#define RKISP1_CIF_SMIA_IMSC (RKISP1_CIF_SMIA_BASE + 0x00000008) +#define RKISP1_CIF_SMIA_RIS (RKISP1_CIF_SMIA_BASE + 0x0000000C) +#define RKISP1_CIF_SMIA_MIS (RKISP1_CIF_SMIA_BASE + 0x00000010) +#define RKISP1_CIF_SMIA_ICR (RKISP1_CIF_SMIA_BASE + 0x00000014) +#define RKISP1_CIF_SMIA_ISR (RKISP1_CIF_SMIA_BASE + 0x00000018) +#define RKISP1_CIF_SMIA_DATA_FORMAT_SEL (RKISP1_CIF_SMIA_BASE + 0x0000001C) +#define RKISP1_CIF_SMIA_SOF_EMB_DATA_LINES (RKISP1_CIF_SMIA_BASE + 0x00000020) +#define RKISP1_CIF_SMIA_EMB_HSTART (RKISP1_CIF_SMIA_BASE + 0x00000024) +#define RKISP1_CIF_SMIA_EMB_HSIZE (RKISP1_CIF_SMIA_BASE + 0x00000028) +#define RKISP1_CIF_SMIA_EMB_VSTART (RKISP1_CIF_SMIA_BASE + 0x0000002c) +#define RKISP1_CIF_SMIA_NUM_LINES (RKISP1_CIF_SMIA_BASE + 0x00000030) +#define RKISP1_CIF_SMIA_EMB_DATA_FIFO (RKISP1_CIF_SMIA_BASE + 0x00000034) +#define RKISP1_CIF_SMIA_EMB_DATA_WATERMARK (RKISP1_CIF_SMIA_BASE + 0x00000038) + +#define RKISP1_CIF_MIPI_BASE 0x00001C00 +#define RKISP1_CIF_MIPI_CTRL (RKISP1_CIF_MIPI_BASE + 0x00000000) +#define RKISP1_CIF_MIPI_STATUS (RKISP1_CIF_MIPI_BASE + 0x00000004) +#define RKISP1_CIF_MIPI_IMSC (RKISP1_CIF_MIPI_BASE + 0x00000008) +#define RKISP1_CIF_MIPI_RIS (RKISP1_CIF_MIPI_BASE + 0x0000000C) +#define RKISP1_CIF_MIPI_MIS (RKISP1_CIF_MIPI_BASE + 0x00000010) +#define RKISP1_CIF_MIPI_ICR (RKISP1_CIF_MIPI_BASE + 0x00000014) +#define RKISP1_CIF_MIPI_ISR (RKISP1_CIF_MIPI_BASE + 0x00000018) +#define RKISP1_CIF_MIPI_CUR_DATA_ID (RKISP1_CIF_MIPI_BASE + 0x0000001C) +#define RKISP1_CIF_MIPI_IMG_DATA_SEL (RKISP1_CIF_MIPI_BASE + 0x00000020) +#define RKISP1_CIF_MIPI_ADD_DATA_SEL_1 (RKISP1_CIF_MIPI_BASE + 0x00000024) +#define RKISP1_CIF_MIPI_ADD_DATA_SEL_2 (RKISP1_CIF_MIPI_BASE + 0x00000028) +#define RKISP1_CIF_MIPI_ADD_DATA_SEL_3 (RKISP1_CIF_MIPI_BASE + 0x0000002C) +#define RKISP1_CIF_MIPI_ADD_DATA_SEL_4 (RKISP1_CIF_MIPI_BASE + 0x00000030) +#define RKISP1_CIF_MIPI_ADD_DATA_FIFO (RKISP1_CIF_MIPI_BASE + 0x00000034) +#define RKISP1_CIF_MIPI_FIFO_FILL_LEVEL (RKISP1_CIF_MIPI_BASE + 0x00000038) +#define RKISP1_CIF_MIPI_COMPRESSED_MODE (RKISP1_CIF_MIPI_BASE + 0x0000003C) +#define RKISP1_CIF_MIPI_FRAME (RKISP1_CIF_MIPI_BASE + 0x00000040) +#define RKISP1_CIF_MIPI_GEN_SHORT_DT (RKISP1_CIF_MIPI_BASE + 0x00000044) +#define RKISP1_CIF_MIPI_GEN_SHORT_8_9 (RKISP1_CIF_MIPI_BASE + 0x00000048) +#define RKISP1_CIF_MIPI_GEN_SHORT_A_B (RKISP1_CIF_MIPI_BASE + 0x0000004C) +#define RKISP1_CIF_MIPI_GEN_SHORT_C_D (RKISP1_CIF_MIPI_BASE + 0x00000050) +#define RKISP1_CIF_MIPI_GEN_SHORT_E_F (RKISP1_CIF_MIPI_BASE + 0x00000054) + +#define RKISP1_CIF_ISP_AFM_BASE 0x00002000 +#define RKISP1_CIF_ISP_AFM_CTRL (RKISP1_CIF_ISP_AFM_BASE + 0x00000000) +#define RKISP1_CIF_ISP_AFM_LT_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000004) +#define RKISP1_CIF_ISP_AFM_RB_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000008) +#define RKISP1_CIF_ISP_AFM_LT_B (RKISP1_CIF_ISP_AFM_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_AFM_RB_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000010) +#define RKISP1_CIF_ISP_AFM_LT_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000014) +#define RKISP1_CIF_ISP_AFM_RB_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000018) +#define RKISP1_CIF_ISP_AFM_THRES (RKISP1_CIF_ISP_AFM_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_AFM_VAR_SHIFT (RKISP1_CIF_ISP_AFM_BASE + 0x00000020) +#define RKISP1_CIF_ISP_AFM_SUM_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000024) +#define RKISP1_CIF_ISP_AFM_SUM_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000028) +#define RKISP1_CIF_ISP_AFM_SUM_C (RKISP1_CIF_ISP_AFM_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_AFM_LUM_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000030) +#define RKISP1_CIF_ISP_AFM_LUM_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000034) +#define RKISP1_CIF_ISP_AFM_LUM_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000038) + +#define RKISP1_CIF_ISP_LSC_BASE 0x00002200 +#define RKISP1_CIF_ISP_LSC_CTRL (RKISP1_CIF_ISP_LSC_BASE + 0x00000000) +#define RKISP1_CIF_ISP_LSC_R_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000004) +#define RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000008) +#define RKISP1_CIF_ISP_LSC_B_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000010) +#define RKISP1_CIF_ISP_LSC_R_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000014) +#define RKISP1_CIF_ISP_LSC_GR_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000018) +#define RKISP1_CIF_ISP_LSC_B_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_LSC_GB_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000020) +#define RKISP1_CIF_ISP_LSC_XGRAD_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000024) +#define RKISP1_CIF_ISP_LSC_XGRAD_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000028) +#define RKISP1_CIF_ISP_LSC_XGRAD_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_LSC_XGRAD_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000030) +#define RKISP1_CIF_ISP_LSC_YGRAD_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000034) +#define RKISP1_CIF_ISP_LSC_YGRAD_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000038) +#define RKISP1_CIF_ISP_LSC_YGRAD_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_LSC_YGRAD_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000040) +#define RKISP1_CIF_ISP_LSC_XSIZE_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000044) +#define RKISP1_CIF_ISP_LSC_XSIZE_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000048) +#define RKISP1_CIF_ISP_LSC_XSIZE_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_LSC_XSIZE_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000050) +#define RKISP1_CIF_ISP_LSC_YSIZE_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000054) +#define RKISP1_CIF_ISP_LSC_YSIZE_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000058) +#define RKISP1_CIF_ISP_LSC_YSIZE_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_LSC_YSIZE_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000060) +#define RKISP1_CIF_ISP_LSC_TABLE_SEL (RKISP1_CIF_ISP_LSC_BASE + 0x00000064) +#define RKISP1_CIF_ISP_LSC_STATUS (RKISP1_CIF_ISP_LSC_BASE + 0x00000068) + +#define RKISP1_CIF_ISP_IS_BASE 0x00002300 +#define RKISP1_CIF_ISP_IS_CTRL (RKISP1_CIF_ISP_IS_BASE + 0x00000000) +#define RKISP1_CIF_ISP_IS_RECENTER (RKISP1_CIF_ISP_IS_BASE + 0x00000004) +#define RKISP1_CIF_ISP_IS_H_OFFS (RKISP1_CIF_ISP_IS_BASE + 0x00000008) +#define RKISP1_CIF_ISP_IS_V_OFFS (RKISP1_CIF_ISP_IS_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_IS_H_SIZE (RKISP1_CIF_ISP_IS_BASE + 0x00000010) +#define RKISP1_CIF_ISP_IS_V_SIZE (RKISP1_CIF_ISP_IS_BASE + 0x00000014) +#define RKISP1_CIF_ISP_IS_MAX_DX (RKISP1_CIF_ISP_IS_BASE + 0x00000018) +#define RKISP1_CIF_ISP_IS_MAX_DY (RKISP1_CIF_ISP_IS_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_IS_DISPLACE (RKISP1_CIF_ISP_IS_BASE + 0x00000020) +#define RKISP1_CIF_ISP_IS_H_OFFS_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000024) +#define RKISP1_CIF_ISP_IS_V_OFFS_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000028) +#define RKISP1_CIF_ISP_IS_H_SIZE_SHD (RKISP1_CIF_ISP_IS_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_IS_V_SIZE_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000030) + +#define RKISP1_CIF_ISP_HIST_BASE 0x00002400 + +#define RKISP1_CIF_ISP_HIST_PROP (RKISP1_CIF_ISP_HIST_BASE + 0x00000000) +#define RKISP1_CIF_ISP_HIST_H_OFFS (RKISP1_CIF_ISP_HIST_BASE + 0x00000004) +#define RKISP1_CIF_ISP_HIST_V_OFFS (RKISP1_CIF_ISP_HIST_BASE + 0x00000008) +#define RKISP1_CIF_ISP_HIST_H_SIZE (RKISP1_CIF_ISP_HIST_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_HIST_V_SIZE (RKISP1_CIF_ISP_HIST_BASE + 0x00000010) +#define RKISP1_CIF_ISP_HIST_BIN_0 (RKISP1_CIF_ISP_HIST_BASE + 0x00000014) +#define RKISP1_CIF_ISP_HIST_BIN_1 (RKISP1_CIF_ISP_HIST_BASE + 0x00000018) +#define RKISP1_CIF_ISP_HIST_BIN_2 (RKISP1_CIF_ISP_HIST_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_HIST_BIN_3 (RKISP1_CIF_ISP_HIST_BASE + 0x00000020) +#define RKISP1_CIF_ISP_HIST_BIN_4 (RKISP1_CIF_ISP_HIST_BASE + 0x00000024) +#define RKISP1_CIF_ISP_HIST_BIN_5 (RKISP1_CIF_ISP_HIST_BASE + 0x00000028) +#define RKISP1_CIF_ISP_HIST_BIN_6 (RKISP1_CIF_ISP_HIST_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_HIST_BIN_7 (RKISP1_CIF_ISP_HIST_BASE + 0x00000030) +#define RKISP1_CIF_ISP_HIST_BIN_8 (RKISP1_CIF_ISP_HIST_BASE + 0x00000034) +#define RKISP1_CIF_ISP_HIST_BIN_9 (RKISP1_CIF_ISP_HIST_BASE + 0x00000038) +#define RKISP1_CIF_ISP_HIST_BIN_10 (RKISP1_CIF_ISP_HIST_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_HIST_BIN_11 (RKISP1_CIF_ISP_HIST_BASE + 0x00000040) +#define RKISP1_CIF_ISP_HIST_BIN_12 (RKISP1_CIF_ISP_HIST_BASE + 0x00000044) +#define RKISP1_CIF_ISP_HIST_BIN_13 (RKISP1_CIF_ISP_HIST_BASE + 0x00000048) +#define RKISP1_CIF_ISP_HIST_BIN_14 (RKISP1_CIF_ISP_HIST_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_HIST_BIN_15 (RKISP1_CIF_ISP_HIST_BASE + 0x00000050) +#define RKISP1_CIF_ISP_HIST_WEIGHT_00TO30 (RKISP1_CIF_ISP_HIST_BASE + 0x00000054) +#define RKISP1_CIF_ISP_HIST_WEIGHT_40TO21 (RKISP1_CIF_ISP_HIST_BASE + 0x00000058) +#define RKISP1_CIF_ISP_HIST_WEIGHT_31TO12 (RKISP1_CIF_ISP_HIST_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_HIST_WEIGHT_22TO03 (RKISP1_CIF_ISP_HIST_BASE + 0x00000060) +#define RKISP1_CIF_ISP_HIST_WEIGHT_13TO43 (RKISP1_CIF_ISP_HIST_BASE + 0x00000064) +#define RKISP1_CIF_ISP_HIST_WEIGHT_04TO34 (RKISP1_CIF_ISP_HIST_BASE + 0x00000068) +#define RKISP1_CIF_ISP_HIST_WEIGHT_44 (RKISP1_CIF_ISP_HIST_BASE + 0x0000006C) + +#define RKISP1_CIF_ISP_FILT_BASE 0x00002500 +#define RKISP1_CIF_ISP_FILT_MODE (RKISP1_CIF_ISP_FILT_BASE + 0x00000000) +#define RKISP1_CIF_ISP_FILT_THRESH_BL0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000028) +#define RKISP1_CIF_ISP_FILT_THRESH_BL1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000002c) +#define RKISP1_CIF_ISP_FILT_THRESH_SH0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000030) +#define RKISP1_CIF_ISP_FILT_THRESH_SH1 (RKISP1_CIF_ISP_FILT_BASE + 0x00000034) +#define RKISP1_CIF_ISP_FILT_LUM_WEIGHT (RKISP1_CIF_ISP_FILT_BASE + 0x00000038) +#define RKISP1_CIF_ISP_FILT_FAC_SH1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000003c) +#define RKISP1_CIF_ISP_FILT_FAC_SH0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000040) +#define RKISP1_CIF_ISP_FILT_FAC_MID (RKISP1_CIF_ISP_FILT_BASE + 0x00000044) +#define RKISP1_CIF_ISP_FILT_FAC_BL0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000048) +#define RKISP1_CIF_ISP_FILT_FAC_BL1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000004C) + +#define RKISP1_CIF_ISP_CAC_BASE 0x00002580 +#define RKISP1_CIF_ISP_CAC_CTRL (RKISP1_CIF_ISP_CAC_BASE + 0x00000000) +#define RKISP1_CIF_ISP_CAC_COUNT_START (RKISP1_CIF_ISP_CAC_BASE + 0x00000004) +#define RKISP1_CIF_ISP_CAC_A (RKISP1_CIF_ISP_CAC_BASE + 0x00000008) +#define RKISP1_CIF_ISP_CAC_B (RKISP1_CIF_ISP_CAC_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_CAC_C (RKISP1_CIF_ISP_CAC_BASE + 0x00000010) +#define RKISP1_CIF_ISP_X_NORM (RKISP1_CIF_ISP_CAC_BASE + 0x00000014) +#define RKISP1_CIF_ISP_Y_NORM (RKISP1_CIF_ISP_CAC_BASE + 0x00000018) + +#define RKISP1_CIF_ISP_EXP_BASE 0x00002600 +#define RKISP1_CIF_ISP_EXP_CTRL (RKISP1_CIF_ISP_EXP_BASE + 0x00000000) +#define RKISP1_CIF_ISP_EXP_H_OFFSET (RKISP1_CIF_ISP_EXP_BASE + 0x00000004) +#define RKISP1_CIF_ISP_EXP_V_OFFSET (RKISP1_CIF_ISP_EXP_BASE + 0x00000008) +#define RKISP1_CIF_ISP_EXP_H_SIZE (RKISP1_CIF_ISP_EXP_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_EXP_V_SIZE (RKISP1_CIF_ISP_EXP_BASE + 0x00000010) +#define RKISP1_CIF_ISP_EXP_MEAN_00 (RKISP1_CIF_ISP_EXP_BASE + 0x00000014) +#define RKISP1_CIF_ISP_EXP_MEAN_10 (RKISP1_CIF_ISP_EXP_BASE + 0x00000018) +#define RKISP1_CIF_ISP_EXP_MEAN_20 (RKISP1_CIF_ISP_EXP_BASE + 0x0000001c) +#define RKISP1_CIF_ISP_EXP_MEAN_30 (RKISP1_CIF_ISP_EXP_BASE + 0x00000020) +#define RKISP1_CIF_ISP_EXP_MEAN_40 (RKISP1_CIF_ISP_EXP_BASE + 0x00000024) +#define RKISP1_CIF_ISP_EXP_MEAN_01 (RKISP1_CIF_ISP_EXP_BASE + 0x00000028) +#define RKISP1_CIF_ISP_EXP_MEAN_11 (RKISP1_CIF_ISP_EXP_BASE + 0x0000002c) +#define RKISP1_CIF_ISP_EXP_MEAN_21 (RKISP1_CIF_ISP_EXP_BASE + 0x00000030) +#define RKISP1_CIF_ISP_EXP_MEAN_31 (RKISP1_CIF_ISP_EXP_BASE + 0x00000034) +#define RKISP1_CIF_ISP_EXP_MEAN_41 (RKISP1_CIF_ISP_EXP_BASE + 0x00000038) +#define RKISP1_CIF_ISP_EXP_MEAN_02 (RKISP1_CIF_ISP_EXP_BASE + 0x0000003c) +#define RKISP1_CIF_ISP_EXP_MEAN_12 (RKISP1_CIF_ISP_EXP_BASE + 0x00000040) +#define RKISP1_CIF_ISP_EXP_MEAN_22 (RKISP1_CIF_ISP_EXP_BASE + 0x00000044) +#define RKISP1_CIF_ISP_EXP_MEAN_32 (RKISP1_CIF_ISP_EXP_BASE + 0x00000048) +#define RKISP1_CIF_ISP_EXP_MEAN_42 (RKISP1_CIF_ISP_EXP_BASE + 0x0000004c) +#define RKISP1_CIF_ISP_EXP_MEAN_03 (RKISP1_CIF_ISP_EXP_BASE + 0x00000050) +#define RKISP1_CIF_ISP_EXP_MEAN_13 (RKISP1_CIF_ISP_EXP_BASE + 0x00000054) +#define RKISP1_CIF_ISP_EXP_MEAN_23 (RKISP1_CIF_ISP_EXP_BASE + 0x00000058) +#define RKISP1_CIF_ISP_EXP_MEAN_33 (RKISP1_CIF_ISP_EXP_BASE + 0x0000005c) +#define RKISP1_CIF_ISP_EXP_MEAN_43 (RKISP1_CIF_ISP_EXP_BASE + 0x00000060) +#define RKISP1_CIF_ISP_EXP_MEAN_04 (RKISP1_CIF_ISP_EXP_BASE + 0x00000064) +#define RKISP1_CIF_ISP_EXP_MEAN_14 (RKISP1_CIF_ISP_EXP_BASE + 0x00000068) +#define RKISP1_CIF_ISP_EXP_MEAN_24 (RKISP1_CIF_ISP_EXP_BASE + 0x0000006c) +#define RKISP1_CIF_ISP_EXP_MEAN_34 (RKISP1_CIF_ISP_EXP_BASE + 0x00000070) +#define RKISP1_CIF_ISP_EXP_MEAN_44 (RKISP1_CIF_ISP_EXP_BASE + 0x00000074) + +#define RKISP1_CIF_ISP_BLS_BASE 0x00002700 +#define RKISP1_CIF_ISP_BLS_CTRL (RKISP1_CIF_ISP_BLS_BASE + 0x00000000) +#define RKISP1_CIF_ISP_BLS_SAMPLES (RKISP1_CIF_ISP_BLS_BASE + 0x00000004) +#define RKISP1_CIF_ISP_BLS_H1_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000008) +#define RKISP1_CIF_ISP_BLS_H1_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x0000000c) +#define RKISP1_CIF_ISP_BLS_V1_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000010) +#define RKISP1_CIF_ISP_BLS_V1_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x00000014) +#define RKISP1_CIF_ISP_BLS_H2_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000018) +#define RKISP1_CIF_ISP_BLS_H2_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x0000001c) +#define RKISP1_CIF_ISP_BLS_V2_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000020) +#define RKISP1_CIF_ISP_BLS_V2_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x00000024) +#define RKISP1_CIF_ISP_BLS_A_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000028) +#define RKISP1_CIF_ISP_BLS_B_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x0000002c) +#define RKISP1_CIF_ISP_BLS_C_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000030) +#define RKISP1_CIF_ISP_BLS_D_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000034) +#define RKISP1_CIF_ISP_BLS_A_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000038) +#define RKISP1_CIF_ISP_BLS_B_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x0000003c) +#define RKISP1_CIF_ISP_BLS_C_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000040) +#define RKISP1_CIF_ISP_BLS_D_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000044) + +#define RKISP1_CIF_ISP_DPF_BASE 0x00002800 +#define RKISP1_CIF_ISP_DPF_MODE (RKISP1_CIF_ISP_DPF_BASE + 0x00000000) +#define RKISP1_CIF_ISP_DPF_STRENGTH_R (RKISP1_CIF_ISP_DPF_BASE + 0x00000004) +#define RKISP1_CIF_ISP_DPF_STRENGTH_G (RKISP1_CIF_ISP_DPF_BASE + 0x00000008) +#define RKISP1_CIF_ISP_DPF_STRENGTH_B (RKISP1_CIF_ISP_DPF_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_DPF_S_WEIGHT_G_1_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000010) +#define RKISP1_CIF_ISP_DPF_S_WEIGHT_G_5_6 (RKISP1_CIF_ISP_DPF_BASE + 0x00000014) +#define RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_1_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000018) +#define RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_5_6 (RKISP1_CIF_ISP_DPF_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_0 (RKISP1_CIF_ISP_DPF_BASE + 0x00000020) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_1 (RKISP1_CIF_ISP_DPF_BASE + 0x00000024) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_2 (RKISP1_CIF_ISP_DPF_BASE + 0x00000028) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_3 (RKISP1_CIF_ISP_DPF_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000030) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_5 (RKISP1_CIF_ISP_DPF_BASE + 0x00000034) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_6 (RKISP1_CIF_ISP_DPF_BASE + 0x00000038) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_7 (RKISP1_CIF_ISP_DPF_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_8 (RKISP1_CIF_ISP_DPF_BASE + 0x00000040) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_9 (RKISP1_CIF_ISP_DPF_BASE + 0x00000044) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_10 (RKISP1_CIF_ISP_DPF_BASE + 0x00000048) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_11 (RKISP1_CIF_ISP_DPF_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_12 (RKISP1_CIF_ISP_DPF_BASE + 0x00000050) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_13 (RKISP1_CIF_ISP_DPF_BASE + 0x00000054) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_14 (RKISP1_CIF_ISP_DPF_BASE + 0x00000058) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_15 (RKISP1_CIF_ISP_DPF_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_DPF_NULL_COEFF_16 (RKISP1_CIF_ISP_DPF_BASE + 0x00000060) +#define RKISP1_CIF_ISP_DPF_NF_GAIN_R (RKISP1_CIF_ISP_DPF_BASE + 0x00000064) +#define RKISP1_CIF_ISP_DPF_NF_GAIN_GR (RKISP1_CIF_ISP_DPF_BASE + 0x00000068) +#define RKISP1_CIF_ISP_DPF_NF_GAIN_GB (RKISP1_CIF_ISP_DPF_BASE + 0x0000006C) +#define RKISP1_CIF_ISP_DPF_NF_GAIN_B (RKISP1_CIF_ISP_DPF_BASE + 0x00000070) + +#define RKISP1_CIF_ISP_DPCC_BASE 0x00002900 +#define RKISP1_CIF_ISP_DPCC_MODE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000000) +#define RKISP1_CIF_ISP_DPCC_OUTPUT_MODE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000004) +#define RKISP1_CIF_ISP_DPCC_SET_USE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000008) +#define RKISP1_CIF_ISP_DPCC_METHODS_SET_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_DPCC_METHODS_SET_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000010) +#define RKISP1_CIF_ISP_DPCC_METHODS_SET_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000014) +#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000018) +#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_DPCC_PG_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000020) +#define RKISP1_CIF_ISP_DPCC_RND_THRESH_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000024) +#define RKISP1_CIF_ISP_DPCC_RG_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000028) +#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000030) +#define RKISP1_CIF_ISP_DPCC_PG_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000034) +#define RKISP1_CIF_ISP_DPCC_RND_THRESH_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000038) +#define RKISP1_CIF_ISP_DPCC_RG_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000040) +#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000044) +#define RKISP1_CIF_ISP_DPCC_PG_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000048) +#define RKISP1_CIF_ISP_DPCC_RND_THRESH_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_DPCC_RG_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000050) +#define RKISP1_CIF_ISP_DPCC_RO_LIMITS (RKISP1_CIF_ISP_DPCC_BASE + 0x00000054) +#define RKISP1_CIF_ISP_DPCC_RND_OFFS (RKISP1_CIF_ISP_DPCC_BASE + 0x00000058) +#define RKISP1_CIF_ISP_DPCC_BPT_CTRL (RKISP1_CIF_ISP_DPCC_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_DPCC_BPT_NUMBER (RKISP1_CIF_ISP_DPCC_BASE + 0x00000060) +#define RKISP1_CIF_ISP_DPCC_BPT_ADDR (RKISP1_CIF_ISP_DPCC_BASE + 0x00000064) +#define RKISP1_CIF_ISP_DPCC_BPT_DATA (RKISP1_CIF_ISP_DPCC_BASE + 0x00000068) + +#define RKISP1_CIF_ISP_WDR_BASE 0x00002A00 +#define RKISP1_CIF_ISP_WDR_CTRL (RKISP1_CIF_ISP_WDR_BASE + 0x00000000) +#define RKISP1_CIF_ISP_WDR_TONECURVE_1 (RKISP1_CIF_ISP_WDR_BASE + 0x00000004) +#define RKISP1_CIF_ISP_WDR_TONECURVE_2 (RKISP1_CIF_ISP_WDR_BASE + 0x00000008) +#define RKISP1_CIF_ISP_WDR_TONECURVE_3 (RKISP1_CIF_ISP_WDR_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_4 (RKISP1_CIF_ISP_WDR_BASE + 0x00000010) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_0 (RKISP1_CIF_ISP_WDR_BASE + 0x00000014) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_1 (RKISP1_CIF_ISP_WDR_BASE + 0x00000018) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_2 (RKISP1_CIF_ISP_WDR_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_3 (RKISP1_CIF_ISP_WDR_BASE + 0x00000020) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_4 (RKISP1_CIF_ISP_WDR_BASE + 0x00000024) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_5 (RKISP1_CIF_ISP_WDR_BASE + 0x00000028) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_6 (RKISP1_CIF_ISP_WDR_BASE + 0x0000002C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_7 (RKISP1_CIF_ISP_WDR_BASE + 0x00000030) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_8 (RKISP1_CIF_ISP_WDR_BASE + 0x00000034) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_9 (RKISP1_CIF_ISP_WDR_BASE + 0x00000038) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_10 (RKISP1_CIF_ISP_WDR_BASE + 0x0000003C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_11 (RKISP1_CIF_ISP_WDR_BASE + 0x00000040) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_12 (RKISP1_CIF_ISP_WDR_BASE + 0x00000044) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_13 (RKISP1_CIF_ISP_WDR_BASE + 0x00000048) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_14 (RKISP1_CIF_ISP_WDR_BASE + 0x0000004C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_15 (RKISP1_CIF_ISP_WDR_BASE + 0x00000050) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_16 (RKISP1_CIF_ISP_WDR_BASE + 0x00000054) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_17 (RKISP1_CIF_ISP_WDR_BASE + 0x00000058) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_18 (RKISP1_CIF_ISP_WDR_BASE + 0x0000005C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_19 (RKISP1_CIF_ISP_WDR_BASE + 0x00000060) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_20 (RKISP1_CIF_ISP_WDR_BASE + 0x00000064) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_21 (RKISP1_CIF_ISP_WDR_BASE + 0x00000068) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_22 (RKISP1_CIF_ISP_WDR_BASE + 0x0000006C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_23 (RKISP1_CIF_ISP_WDR_BASE + 0x00000070) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_24 (RKISP1_CIF_ISP_WDR_BASE + 0x00000074) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_25 (RKISP1_CIF_ISP_WDR_BASE + 0x00000078) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_26 (RKISP1_CIF_ISP_WDR_BASE + 0x0000007C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_27 (RKISP1_CIF_ISP_WDR_BASE + 0x00000080) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_28 (RKISP1_CIF_ISP_WDR_BASE + 0x00000084) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_29 (RKISP1_CIF_ISP_WDR_BASE + 0x00000088) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_30 (RKISP1_CIF_ISP_WDR_BASE + 0x0000008C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_31 (RKISP1_CIF_ISP_WDR_BASE + 0x00000090) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_32 (RKISP1_CIF_ISP_WDR_BASE + 0x00000094) +#define RKISP1_CIF_ISP_WDR_OFFSET (RKISP1_CIF_ISP_WDR_BASE + 0x00000098) +#define RKISP1_CIF_ISP_WDR_DELTAMIN (RKISP1_CIF_ISP_WDR_BASE + 0x0000009C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_1_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_2_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_3_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_4_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000AC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_0_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_1_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_2_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_3_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000BC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_4_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_5_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_6_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_7_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000CC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_8_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_9_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_10_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_11_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000DC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_12_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_13_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_14_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_15_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000EC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_16_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F0) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_17_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F4) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_18_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F8) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_19_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000FC) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_20_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000100) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_21_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000104) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_22_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000108) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_23_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000010C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_24_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000110) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_25_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000114) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_26_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000118) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_27_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000011C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_28_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000120) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_29_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000124) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_30_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000128) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_31_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000012C) +#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_32_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000130) + +#define RKISP1_CIF_ISP_VSM_BASE 0x00002F00 +#define RKISP1_CIF_ISP_VSM_MODE (RKISP1_CIF_ISP_VSM_BASE + 0x00000000) +#define RKISP1_CIF_ISP_VSM_H_OFFS (RKISP1_CIF_ISP_VSM_BASE + 0x00000004) +#define RKISP1_CIF_ISP_VSM_V_OFFS (RKISP1_CIF_ISP_VSM_BASE + 0x00000008) +#define RKISP1_CIF_ISP_VSM_H_SIZE (RKISP1_CIF_ISP_VSM_BASE + 0x0000000C) +#define RKISP1_CIF_ISP_VSM_V_SIZE (RKISP1_CIF_ISP_VSM_BASE + 0x00000010) +#define RKISP1_CIF_ISP_VSM_H_SEGMENTS (RKISP1_CIF_ISP_VSM_BASE + 0x00000014) +#define RKISP1_CIF_ISP_VSM_V_SEGMENTS (RKISP1_CIF_ISP_VSM_BASE + 0x00000018) +#define RKISP1_CIF_ISP_VSM_DELTA_H (RKISP1_CIF_ISP_VSM_BASE + 0x0000001C) +#define RKISP1_CIF_ISP_VSM_DELTA_V (RKISP1_CIF_ISP_VSM_BASE + 0x00000020) + +#endif /* _RKISP1_REGS_H */ diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c new file mode 100644 index 000000000000..813670ed9577 --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - V4l resizer device + * + * Copyright (C) 2019 Collabora, Ltd. + * + * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include "rkisp1-common.h" + +#define RKISP1_RSZ_SP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_selfpath" +#define RKISP1_RSZ_MP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_mainpath" + +#define RKISP1_DEF_FMT MEDIA_BUS_FMT_YUYV8_2X8 +#define RKISP1_DEF_PIXEL_ENC V4L2_PIXEL_ENC_YUV + +struct rkisp1_rsz_yuv_mbus_info { + u32 mbus_code; + u32 hdiv; + u32 vdiv; +}; + +static const struct rkisp1_rsz_yuv_mbus_info rkisp1_rsz_yuv_src_formats[] = { + { + .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, /* YUV422 */ + .hdiv = 2, + .vdiv = 1, + }, + { + .mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8, /* YUV420 */ + .hdiv = 2, + .vdiv = 2, + }, +}; + +static const struct rkisp1_rsz_yuv_mbus_info *rkisp1_rsz_get_yuv_mbus_info(u32 mbus_code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(rkisp1_rsz_yuv_src_formats); i++) { + if (rkisp1_rsz_yuv_src_formats[i].mbus_code == mbus_code) + return &rkisp1_rsz_yuv_src_formats[i]; + } + + return NULL; +} + +enum rkisp1_shadow_regs_when { + RKISP1_SHADOW_REGS_SYNC, + RKISP1_SHADOW_REGS_ASYNC, +}; + +struct rkisp1_rsz_config { + /* constrains */ + const int max_rsz_width; + const int max_rsz_height; + const int min_rsz_width; + const int min_rsz_height; + /* registers */ + struct { + u32 ctrl; + u32 ctrl_shd; + u32 scale_hy; + u32 scale_hcr; + u32 scale_hcb; + u32 scale_vy; + u32 scale_vc; + u32 scale_lut; + u32 scale_lut_addr; + u32 scale_hy_shd; + u32 scale_hcr_shd; + u32 scale_hcb_shd; + u32 scale_vy_shd; + u32 scale_vc_shd; + u32 phase_hy; + u32 phase_hc; + u32 phase_vy; + u32 phase_vc; + u32 phase_hy_shd; + u32 phase_hc_shd; + u32 phase_vy_shd; + u32 phase_vc_shd; + } rsz; + struct { + u32 ctrl; + u32 yuvmode_mask; + u32 rawmode_mask; + u32 h_offset; + u32 v_offset; + u32 h_size; + u32 v_size; + } dual_crop; +}; + +static const struct rkisp1_rsz_config rkisp1_rsz_config_mp = { + /* constraints */ + .max_rsz_width = RKISP1_RSZ_MP_SRC_MAX_WIDTH, + .max_rsz_height = RKISP1_RSZ_MP_SRC_MAX_HEIGHT, + .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH, + .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT, + /* registers */ + .rsz = { + .ctrl = RKISP1_CIF_MRSZ_CTRL, + .scale_hy = RKISP1_CIF_MRSZ_SCALE_HY, + .scale_hcr = RKISP1_CIF_MRSZ_SCALE_HCR, + .scale_hcb = RKISP1_CIF_MRSZ_SCALE_HCB, + .scale_vy = RKISP1_CIF_MRSZ_SCALE_VY, + .scale_vc = RKISP1_CIF_MRSZ_SCALE_VC, + .scale_lut = RKISP1_CIF_MRSZ_SCALE_LUT, + .scale_lut_addr = RKISP1_CIF_MRSZ_SCALE_LUT_ADDR, + .scale_hy_shd = RKISP1_CIF_MRSZ_SCALE_HY_SHD, + .scale_hcr_shd = RKISP1_CIF_MRSZ_SCALE_HCR_SHD, + .scale_hcb_shd = RKISP1_CIF_MRSZ_SCALE_HCB_SHD, + .scale_vy_shd = RKISP1_CIF_MRSZ_SCALE_VY_SHD, + .scale_vc_shd = RKISP1_CIF_MRSZ_SCALE_VC_SHD, + .phase_hy = RKISP1_CIF_MRSZ_PHASE_HY, + .phase_hc = RKISP1_CIF_MRSZ_PHASE_HC, + .phase_vy = RKISP1_CIF_MRSZ_PHASE_VY, + .phase_vc = RKISP1_CIF_MRSZ_PHASE_VC, + .ctrl_shd = RKISP1_CIF_MRSZ_CTRL_SHD, + .phase_hy_shd = RKISP1_CIF_MRSZ_PHASE_HY_SHD, + .phase_hc_shd = RKISP1_CIF_MRSZ_PHASE_HC_SHD, + .phase_vy_shd = RKISP1_CIF_MRSZ_PHASE_VY_SHD, + .phase_vc_shd = RKISP1_CIF_MRSZ_PHASE_VC_SHD, + }, + .dual_crop = { + .ctrl = RKISP1_CIF_DUAL_CROP_CTRL, + .yuvmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_YUV, + .rawmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_RAW, + .h_offset = RKISP1_CIF_DUAL_CROP_M_H_OFFS, + .v_offset = RKISP1_CIF_DUAL_CROP_M_V_OFFS, + .h_size = RKISP1_CIF_DUAL_CROP_M_H_SIZE, + .v_size = RKISP1_CIF_DUAL_CROP_M_V_SIZE, + }, +}; + +static const struct rkisp1_rsz_config rkisp1_rsz_config_sp = { + /* constraints */ + .max_rsz_width = RKISP1_RSZ_SP_SRC_MAX_WIDTH, + .max_rsz_height = RKISP1_RSZ_SP_SRC_MAX_HEIGHT, + .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH, + .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT, + /* registers */ + .rsz = { + .ctrl = RKISP1_CIF_SRSZ_CTRL, + .scale_hy = RKISP1_CIF_SRSZ_SCALE_HY, + .scale_hcr = RKISP1_CIF_SRSZ_SCALE_HCR, + .scale_hcb = RKISP1_CIF_SRSZ_SCALE_HCB, + .scale_vy = RKISP1_CIF_SRSZ_SCALE_VY, + .scale_vc = RKISP1_CIF_SRSZ_SCALE_VC, + .scale_lut = RKISP1_CIF_SRSZ_SCALE_LUT, + .scale_lut_addr = RKISP1_CIF_SRSZ_SCALE_LUT_ADDR, + .scale_hy_shd = RKISP1_CIF_SRSZ_SCALE_HY_SHD, + .scale_hcr_shd = RKISP1_CIF_SRSZ_SCALE_HCR_SHD, + .scale_hcb_shd = RKISP1_CIF_SRSZ_SCALE_HCB_SHD, + .scale_vy_shd = RKISP1_CIF_SRSZ_SCALE_VY_SHD, + .scale_vc_shd = RKISP1_CIF_SRSZ_SCALE_VC_SHD, + .phase_hy = RKISP1_CIF_SRSZ_PHASE_HY, + .phase_hc = RKISP1_CIF_SRSZ_PHASE_HC, + .phase_vy = RKISP1_CIF_SRSZ_PHASE_VY, + .phase_vc = RKISP1_CIF_SRSZ_PHASE_VC, + .ctrl_shd = RKISP1_CIF_SRSZ_CTRL_SHD, + .phase_hy_shd = RKISP1_CIF_SRSZ_PHASE_HY_SHD, + .phase_hc_shd = RKISP1_CIF_SRSZ_PHASE_HC_SHD, + .phase_vy_shd = RKISP1_CIF_SRSZ_PHASE_VY_SHD, + .phase_vc_shd = RKISP1_CIF_SRSZ_PHASE_VC_SHD, + }, + .dual_crop = { + .ctrl = RKISP1_CIF_DUAL_CROP_CTRL, + .yuvmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_YUV, + .rawmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_RAW, + .h_offset = RKISP1_CIF_DUAL_CROP_S_H_OFFS, + .v_offset = RKISP1_CIF_DUAL_CROP_S_V_OFFS, + .h_size = RKISP1_CIF_DUAL_CROP_S_H_SIZE, + .v_size = RKISP1_CIF_DUAL_CROP_S_V_SIZE, + }, +}; + +static struct v4l2_mbus_framefmt * +rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer *rsz, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(&rsz->sd, cfg, pad); + else + return v4l2_subdev_get_try_format(&rsz->sd, rsz->pad_cfg, pad); +} + +static struct v4l2_rect * +rkisp1_rsz_get_pad_crop(struct rkisp1_resizer *rsz, + struct v4l2_subdev_pad_config *cfg, + unsigned int pad, u32 which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_crop(&rsz->sd, cfg, pad); + else + return v4l2_subdev_get_try_crop(&rsz->sd, rsz->pad_cfg, pad); +} + +/* ---------------------------------------------------------------------------- + * Dual crop hw configs + */ + +static void rkisp1_dcrop_disable(struct rkisp1_resizer *rsz, + enum rkisp1_shadow_regs_when when) +{ + u32 dc_ctrl = rkisp1_read(rsz->rkisp1, rsz->config->dual_crop.ctrl); + u32 mask = ~(rsz->config->dual_crop.yuvmode_mask | + rsz->config->dual_crop.rawmode_mask); + + dc_ctrl &= mask; + if (when == RKISP1_SHADOW_REGS_ASYNC) + dc_ctrl |= RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD; + else + dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; + rkisp1_write(rsz->rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); +} + +/* configure dual-crop unit */ +static void rkisp1_dcrop_config(struct rkisp1_resizer *rsz) +{ + struct rkisp1_device *rkisp1 = rsz->rkisp1; + struct v4l2_mbus_framefmt *sink_fmt; + struct v4l2_rect *sink_crop; + u32 dc_ctrl; + + sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, + V4L2_SUBDEV_FORMAT_ACTIVE); + sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, + V4L2_SUBDEV_FORMAT_ACTIVE); + + if (sink_crop->width == sink_fmt->width && + sink_crop->height == sink_fmt->height && + sink_crop->left == 0 && sink_crop->top == 0) { + rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_SYNC); + dev_dbg(rkisp1->dev, "capture %d crop disabled\n", rsz->id); + return; + } + + dc_ctrl = rkisp1_read(rkisp1, rsz->config->dual_crop.ctrl); + rkisp1_write(rkisp1, sink_crop->left, rsz->config->dual_crop.h_offset); + rkisp1_write(rkisp1, sink_crop->top, rsz->config->dual_crop.v_offset); + rkisp1_write(rkisp1, sink_crop->width, rsz->config->dual_crop.h_size); + rkisp1_write(rkisp1, sink_crop->height, rsz->config->dual_crop.v_size); + dc_ctrl |= rsz->config->dual_crop.yuvmode_mask; + dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; + rkisp1_write(rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); + + dev_dbg(rkisp1->dev, "stream %d crop: %dx%d -> %dx%d\n", rsz->id, + sink_fmt->width, sink_fmt->height, + sink_crop->width, sink_crop->height); +} + +/* ---------------------------------------------------------------------------- + * Resizer hw configs + */ + +static void rkisp1_rsz_dump_regs(struct rkisp1_resizer *rsz) +{ + dev_dbg(rsz->rkisp1->dev, + "RSZ_CTRL 0x%08x/0x%08x\n" + "RSZ_SCALE_HY %d/%d\n" + "RSZ_SCALE_HCB %d/%d\n" + "RSZ_SCALE_HCR %d/%d\n" + "RSZ_SCALE_VY %d/%d\n" + "RSZ_SCALE_VC %d/%d\n" + "RSZ_PHASE_HY %d/%d\n" + "RSZ_PHASE_HC %d/%d\n" + "RSZ_PHASE_VY %d/%d\n" + "RSZ_PHASE_VC %d/%d\n", + rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy_shd), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc), + rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc_shd)); +} + +static void rkisp1_rsz_update_shadow(struct rkisp1_resizer *rsz, + enum rkisp1_shadow_regs_when when) +{ + u32 ctrl_cfg = rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl); + + if (when == RKISP1_SHADOW_REGS_ASYNC) + ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO; + else + ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD; + + rkisp1_write(rsz->rkisp1, ctrl_cfg, rsz->config->rsz.ctrl); +} + +static u32 rkisp1_rsz_calc_ratio(u32 len_sink, u32 len_src) +{ + if (len_sink < len_src) + return ((len_sink - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / + (len_src - 1); + + return ((len_src - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / + (len_sink - 1) + 1; +} + +static void rkisp1_rsz_disable(struct rkisp1_resizer *rsz, + enum rkisp1_shadow_regs_when when) +{ + rkisp1_write(rsz->rkisp1, 0, rsz->config->rsz.ctrl); + + if (when == RKISP1_SHADOW_REGS_SYNC) + rkisp1_rsz_update_shadow(rsz, when); +} + +static void rkisp1_rsz_config_regs(struct rkisp1_resizer *rsz, + struct v4l2_rect *sink_y, + struct v4l2_rect *sink_c, + struct v4l2_rect *src_y, + struct v4l2_rect *src_c, + enum rkisp1_shadow_regs_when when) +{ + struct rkisp1_device *rkisp1 = rsz->rkisp1; + u32 ratio, rsz_ctrl = 0; + unsigned int i; + + /* No phase offset */ + rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hy); + rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hc); + rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vy); + rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vc); + + /* Linear interpolation */ + for (i = 0; i < 64; i++) { + rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut_addr); + rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut); + } + + if (sink_y->width != src_y->width) { + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE; + if (sink_y->width < src_y->width) + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP; + ratio = rkisp1_rsz_calc_ratio(sink_y->width, src_y->width); + rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hy); + } + + if (sink_c->width != src_c->width) { + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE; + if (sink_c->width < src_c->width) + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP; + ratio = rkisp1_rsz_calc_ratio(sink_c->width, src_c->width); + rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcb); + rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcr); + } + + if (sink_y->height != src_y->height) { + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE; + if (sink_y->height < src_y->height) + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP; + ratio = rkisp1_rsz_calc_ratio(sink_y->height, src_y->height); + rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vy); + } + + if (sink_c->height != src_c->height) { + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE; + if (sink_c->height < src_c->height) + rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP; + ratio = rkisp1_rsz_calc_ratio(sink_c->height, src_c->height); + rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vc); + } + + rkisp1_write(rkisp1, rsz_ctrl, rsz->config->rsz.ctrl); + + rkisp1_rsz_update_shadow(rsz, when); +} + +static void rkisp1_rsz_config(struct rkisp1_resizer *rsz, + enum rkisp1_shadow_regs_when when) +{ + const struct rkisp1_rsz_yuv_mbus_info *sink_yuv_info, *src_yuv_info; + struct v4l2_rect sink_y, sink_c, src_y, src_c; + struct v4l2_mbus_framefmt *src_fmt, *sink_fmt; + struct v4l2_rect *sink_crop; + + sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, + V4L2_SUBDEV_FORMAT_ACTIVE); + src_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SRC, + V4L2_SUBDEV_FORMAT_ACTIVE); + src_yuv_info = rkisp1_rsz_get_yuv_mbus_info(src_fmt->code); + sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, + V4L2_SUBDEV_FORMAT_ACTIVE); + sink_yuv_info = rkisp1_rsz_get_yuv_mbus_info(sink_fmt->code); + + /* + * The resizer only works on yuv formats, + * so return if it is bayer format. + */ + if (rsz->pixel_enc == V4L2_PIXEL_ENC_BAYER) { + rkisp1_rsz_disable(rsz, when); + return; + } + + sink_y.width = sink_crop->width; + sink_y.height = sink_crop->height; + src_y.width = src_fmt->width; + src_y.height = src_fmt->height; + + sink_c.width = sink_y.width / sink_yuv_info->hdiv; + sink_c.height = sink_y.height / sink_yuv_info->vdiv; + + /* + * The resizer is used not only to change the dimensions of the frame + * but also to change the scale for YUV formats, + * (4:2:2 -> 4:2:0 for example). So the width/height of the CbCr + * streams should be set according to the media bus format in the src pad. + */ + src_c.width = src_y.width / src_yuv_info->hdiv; + src_c.height = src_y.height / src_yuv_info->vdiv; + + if (sink_c.width == src_c.width && sink_c.height == src_c.height) { + rkisp1_rsz_disable(rsz, when); + return; + } + + dev_dbg(rsz->rkisp1->dev, "stream %d rsz/scale: %dx%d -> %dx%d\n", + rsz->id, sink_crop->width, sink_crop->height, + src_fmt->width, src_fmt->height); + dev_dbg(rsz->rkisp1->dev, "chroma scaling %dx%d -> %dx%d\n", + sink_c.width, sink_c.height, src_c.width, src_c.height); + + /* set values in the hw */ + rkisp1_rsz_config_regs(rsz, &sink_y, &sink_c, &src_y, &src_c, when); + + rkisp1_rsz_dump_regs(rsz); +} + +/* ---------------------------------------------------------------------------- + * Subdev pad operations + */ + +static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + struct v4l2_subdev_pad_config dummy_cfg; + u32 pad = code->pad; + int ret; + + if (code->pad == RKISP1_RSZ_PAD_SRC) { + /* supported mbus codes on the src are the same as in the capture */ + struct rkisp1_capture *cap = &rsz->rkisp1->capture_devs[rsz->id]; + + return rkisp1_cap_enum_mbus_codes(cap, code); + } + + /* + * The selfpath capture doesn't support bayer formats. Therefore the selfpath resizer + * should support only YUV422 on the sink pad + */ + if (rsz->id == RKISP1_SELFPATH) { + if (code->index > 0) + return -EINVAL; + code->code = MEDIA_BUS_FMT_YUYV8_2X8; + return 0; + } + + /* supported mbus codes on the sink pad are the same as isp src pad */ + code->pad = RKISP1_ISP_PAD_SOURCE_VIDEO; + ret = v4l2_subdev_call(&rsz->rkisp1->isp.sd, pad, enum_mbus_code, + &dummy_cfg, code); + + /* restore pad */ + code->pad = pad; + code->flags = 0; + return ret; +} + +static int rkisp1_rsz_init_config(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg) +{ + struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; + struct v4l2_rect *sink_crop; + + sink_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SRC); + sink_fmt->width = RKISP1_DEFAULT_WIDTH; + sink_fmt->height = RKISP1_DEFAULT_HEIGHT; + sink_fmt->field = V4L2_FIELD_NONE; + sink_fmt->code = RKISP1_DEF_FMT; + + sink_crop = v4l2_subdev_get_try_crop(sd, cfg, RKISP1_RSZ_PAD_SINK); + sink_crop->width = RKISP1_DEFAULT_WIDTH; + sink_crop->height = RKISP1_DEFAULT_HEIGHT; + sink_crop->left = 0; + sink_crop->top = 0; + + src_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SINK); + *src_fmt = *sink_fmt; + + /* NOTE: there is no crop in the source pad, only in the sink */ + + return 0; +} + +static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer *rsz, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_mbus_framefmt *format, + unsigned int which) +{ + const struct rkisp1_isp_mbus_info *mbus_info; + struct v4l2_mbus_framefmt *src_fmt; + + src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which); + mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); + + /* for YUV formats, userspace can change the mbus code on the src pad if it is supported */ + if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV && + rkisp1_rsz_get_yuv_mbus_info(format->code)) + src_fmt->code = format->code; + + src_fmt->width = clamp_t(u32, format->width, + rsz->config->min_rsz_width, + rsz->config->max_rsz_width); + src_fmt->height = clamp_t(u32, format->height, + rsz->config->min_rsz_height, + rsz->config->max_rsz_height); + + *format = *src_fmt; +} + +static void rkisp1_rsz_set_sink_crop(struct rkisp1_resizer *rsz, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_rect *r, + unsigned int which) +{ + const struct rkisp1_isp_mbus_info *mbus_info; + struct v4l2_mbus_framefmt *sink_fmt; + struct v4l2_rect *sink_crop; + + sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which); + sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, + which); + + /* Not crop for MP bayer raw data */ + mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); + + if (rsz->id == RKISP1_MAINPATH && + mbus_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { + sink_crop->left = 0; + sink_crop->top = 0; + sink_crop->width = sink_fmt->width; + sink_crop->height = sink_fmt->height; + + *r = *sink_crop; + return; + } + + sink_crop->left = ALIGN(r->left, 2); + sink_crop->width = ALIGN(r->width, 2); + sink_crop->top = r->top; + sink_crop->height = r->height; + rkisp1_sd_adjust_crop(sink_crop, sink_fmt); + + *r = *sink_crop; +} + +static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer *rsz, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_mbus_framefmt *format, + unsigned int which) +{ + const struct rkisp1_isp_mbus_info *mbus_info; + struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; + struct v4l2_rect *sink_crop; + + sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which); + src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which); + sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, + which); + if (rsz->id == RKISP1_SELFPATH) + sink_fmt->code = MEDIA_BUS_FMT_YUYV8_2X8; + else + sink_fmt->code = format->code; + + mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); + if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) { + sink_fmt->code = RKISP1_DEF_FMT; + mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); + } + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) + rsz->pixel_enc = mbus_info->pixel_enc; + + /* Propagete to source pad */ + src_fmt->code = sink_fmt->code; + + sink_fmt->width = clamp_t(u32, format->width, + RKISP1_ISP_MIN_WIDTH, + RKISP1_ISP_MAX_WIDTH); + sink_fmt->height = clamp_t(u32, format->height, + RKISP1_ISP_MIN_HEIGHT, + RKISP1_ISP_MAX_HEIGHT); + + *format = *sink_fmt; + + /* Update sink crop */ + rkisp1_rsz_set_sink_crop(rsz, cfg, sink_crop, which); +} + +static int rkisp1_rsz_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + + mutex_lock(&rsz->ops_lock); + fmt->format = *rkisp1_rsz_get_pad_fmt(rsz, cfg, fmt->pad, fmt->which); + mutex_unlock(&rsz->ops_lock); + return 0; +} + +static int rkisp1_rsz_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + + mutex_lock(&rsz->ops_lock); + if (fmt->pad == RKISP1_RSZ_PAD_SINK) + rkisp1_rsz_set_sink_fmt(rsz, cfg, &fmt->format, fmt->which); + else + rkisp1_rsz_set_src_fmt(rsz, cfg, &fmt->format, fmt->which); + + mutex_unlock(&rsz->ops_lock); + return 0; +} + +static int rkisp1_rsz_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + struct v4l2_mbus_framefmt *mf_sink; + int ret = 0; + + if (sel->pad == RKISP1_RSZ_PAD_SRC) + return -EINVAL; + + mutex_lock(&rsz->ops_lock); + switch (sel->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + mf_sink = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, + sel->which); + sel->r.height = mf_sink->height; + sel->r.width = mf_sink->width; + sel->r.left = 0; + sel->r.top = 0; + break; + case V4L2_SEL_TGT_CROP: + sel->r = *rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, + sel->which); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&rsz->ops_lock); + return ret; +} + +static int rkisp1_rsz_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + + if (sel->target != V4L2_SEL_TGT_CROP || sel->pad == RKISP1_RSZ_PAD_SRC) + return -EINVAL; + + dev_dbg(rsz->rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, + sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); + + mutex_lock(&rsz->ops_lock); + rkisp1_rsz_set_sink_crop(rsz, cfg, &sel->r, sel->which); + mutex_unlock(&rsz->ops_lock); + + return 0; +} + +static const struct media_entity_operations rkisp1_rsz_media_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_pad_ops rkisp1_rsz_pad_ops = { + .enum_mbus_code = rkisp1_rsz_enum_mbus_code, + .get_selection = rkisp1_rsz_get_selection, + .set_selection = rkisp1_rsz_set_selection, + .init_cfg = rkisp1_rsz_init_config, + .get_fmt = rkisp1_rsz_get_fmt, + .set_fmt = rkisp1_rsz_set_fmt, + .link_validate = v4l2_subdev_link_validate_default, +}; + +/* ---------------------------------------------------------------------------- + * Stream operations + */ + +static int rkisp1_rsz_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct rkisp1_resizer *rsz = + container_of(sd, struct rkisp1_resizer, sd); + struct rkisp1_device *rkisp1 = rsz->rkisp1; + struct rkisp1_capture *other = &rkisp1->capture_devs[rsz->id ^ 1]; + enum rkisp1_shadow_regs_when when = RKISP1_SHADOW_REGS_SYNC; + + if (!enable) { + rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); + rkisp1_rsz_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); + return 0; + } + + if (other->is_streaming) + when = RKISP1_SHADOW_REGS_ASYNC; + + mutex_lock(&rsz->ops_lock); + rkisp1_rsz_config(rsz, when); + rkisp1_dcrop_config(rsz); + + mutex_unlock(&rsz->ops_lock); + return 0; +} + +static const struct v4l2_subdev_video_ops rkisp1_rsz_video_ops = { + .s_stream = rkisp1_rsz_s_stream, +}; + +static const struct v4l2_subdev_ops rkisp1_rsz_ops = { + .video = &rkisp1_rsz_video_ops, + .pad = &rkisp1_rsz_pad_ops, +}; + +static void rkisp1_rsz_unregister(struct rkisp1_resizer *rsz) +{ + v4l2_device_unregister_subdev(&rsz->sd); + media_entity_cleanup(&rsz->sd.entity); +} + +static int rkisp1_rsz_register(struct rkisp1_resizer *rsz) +{ + static const char * const dev_names[] = { + RKISP1_RSZ_MP_DEV_NAME, + RKISP1_RSZ_SP_DEV_NAME + }; + struct media_pad *pads = rsz->pads; + struct v4l2_subdev *sd = &rsz->sd; + int ret; + + if (rsz->id == RKISP1_SELFPATH) + rsz->config = &rkisp1_rsz_config_sp; + else + rsz->config = &rkisp1_rsz_config_mp; + + v4l2_subdev_init(sd, &rkisp1_rsz_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->entity.ops = &rkisp1_rsz_media_ops; + sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; + sd->owner = THIS_MODULE; + strscpy(sd->name, dev_names[rsz->id], sizeof(sd->name)); + + pads[RKISP1_RSZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK | + MEDIA_PAD_FL_MUST_CONNECT; + pads[RKISP1_RSZ_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE | + MEDIA_PAD_FL_MUST_CONNECT; + + rsz->pixel_enc = RKISP1_DEF_PIXEL_ENC; + + mutex_init(&rsz->ops_lock); + ret = media_entity_pads_init(&sd->entity, RKISP1_RSZ_PAD_MAX, pads); + if (ret) + return ret; + + ret = v4l2_device_register_subdev(&rsz->rkisp1->v4l2_dev, sd); + if (ret) { + dev_err(sd->dev, "Failed to register resizer subdev\n"); + goto err_cleanup_media_entity; + } + + rkisp1_rsz_init_config(sd, rsz->pad_cfg); + return 0; + +err_cleanup_media_entity: + media_entity_cleanup(&sd->entity); + + return ret; +} + +int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1) +{ + struct rkisp1_resizer *rsz; + unsigned int i, j; + int ret; + + for (i = 0; i < ARRAY_SIZE(rkisp1->resizer_devs); i++) { + rsz = &rkisp1->resizer_devs[i]; + rsz->rkisp1 = rkisp1; + rsz->id = i; + ret = rkisp1_rsz_register(rsz); + if (ret) + goto err_unreg_resizer_devs; + } + + return 0; + +err_unreg_resizer_devs: + for (j = 0; j < i; j++) { + rsz = &rkisp1->resizer_devs[j]; + rkisp1_rsz_unregister(rsz); + } + + return ret; +} + +void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1) +{ + struct rkisp1_resizer *mp = &rkisp1->resizer_devs[RKISP1_MAINPATH]; + struct rkisp1_resizer *sp = &rkisp1->resizer_devs[RKISP1_SELFPATH]; + + rkisp1_rsz_unregister(mp); + rkisp1_rsz_unregister(sp); +} diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c new file mode 100644 index 000000000000..3ddab8fa8f2d --- /dev/null +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-stats.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Rockchip ISP1 Driver - Stats subdevice + * + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include /* for ISP statistics */ + +#include "rkisp1-common.h" + +#define RKISP1_STATS_DEV_NAME RKISP1_DRIVER_NAME "_stats" + +#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2 +#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8 + +static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct video_device *video = video_devdata(file); + struct rkisp1_stats *stats = video_get_drvdata(video); + + if (f->index > 0 || f->type != video->queue->type) + return -EINVAL; + + f->pixelformat = stats->vdev_fmt.fmt.meta.dataformat; + return 0; +} + +static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct video_device *video = video_devdata(file); + struct rkisp1_stats *stats = video_get_drvdata(video); + struct v4l2_meta_format *meta = &f->fmt.meta; + + if (f->type != video->queue->type) + return -EINVAL; + + memset(meta, 0, sizeof(*meta)); + meta->dataformat = stats->vdev_fmt.fmt.meta.dataformat; + meta->buffersize = stats->vdev_fmt.fmt.meta.buffersize; + + return 0; +} + +static int rkisp1_stats_querycap(struct file *file, + void *priv, struct v4l2_capability *cap) +{ + struct video_device *vdev = video_devdata(file); + + strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, vdev->name, sizeof(cap->card)); + strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); + + return 0; +} + +/* ISP video device IOCTLs */ +static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = { + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap, + .vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, + .vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, + .vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, + .vidioc_querycap = rkisp1_stats_querycap, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct v4l2_file_operations rkisp1_stats_fops = { + .mmap = vb2_fop_mmap, + .unlocked_ioctl = video_ioctl2, + .poll = vb2_fop_poll, + .open = v4l2_fh_open, + .release = vb2_fop_release +}; + +static int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq, + unsigned int *num_buffers, + unsigned int *num_planes, + unsigned int sizes[], + struct device *alloc_devs[]) +{ + *num_planes = 1; + + *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN, + RKISP1_ISP_STATS_REQ_BUFS_MAX); + + sizes[0] = sizeof(struct rkisp1_stat_buffer); + + return 0; +} + +static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct rkisp1_buffer *stats_buf = + container_of(vbuf, struct rkisp1_buffer, vb); + struct vb2_queue *vq = vb->vb2_queue; + struct rkisp1_stats *stats_dev = vq->drv_priv; + + stats_buf->vaddr = vb2_plane_vaddr(vb, 0); + + spin_lock_irq(&stats_dev->lock); + list_add_tail(&stats_buf->queue, &stats_dev->stat); + spin_unlock_irq(&stats_dev->lock); +} + +static int rkisp1_stats_vb2_buf_prepare(struct vb2_buffer *vb) +{ + if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_stat_buffer)) + return -EINVAL; + + vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_stat_buffer)); + + return 0; +} + +static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct rkisp1_stats *stats = vq->drv_priv; + struct rkisp1_buffer *buf; + unsigned int i; + + spin_lock_irq(&stats->lock); + for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) { + if (list_empty(&stats->stat)) + break; + buf = list_first_entry(&stats->stat, + struct rkisp1_buffer, queue); + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + spin_unlock_irq(&stats->lock); +} + +static const struct vb2_ops rkisp1_stats_vb2_ops = { + .queue_setup = rkisp1_stats_vb2_queue_setup, + .buf_queue = rkisp1_stats_vb2_buf_queue, + .buf_prepare = rkisp1_stats_vb2_buf_prepare, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = rkisp1_stats_vb2_stop_streaming, +}; + +static int +rkisp1_stats_init_vb2_queue(struct vb2_queue *q, struct rkisp1_stats *stats) +{ + struct rkisp1_vdev_node *node; + + node = container_of(q, struct rkisp1_vdev_node, buf_queue); + + q->type = V4L2_BUF_TYPE_META_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; + q->drv_priv = stats; + q->ops = &rkisp1_stats_vb2_ops; + q->mem_ops = &vb2_vmalloc_memops; + q->buf_struct_size = sizeof(struct rkisp1_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &node->vlock; + + return vb2_queue_init(q); +} + +static void rkisp1_stats_get_awb_meas(struct rkisp1_stats *stats, + struct rkisp1_stat_buffer *pbuf) +{ + /* Protect against concurrent access from ISR? */ + struct rkisp1_device *rkisp1 = stats->rkisp1; + u32 reg_val; + + pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AWB; + reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_WHITE_CNT); + pbuf->params.awb.awb_mean[0].cnt = + RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(reg_val); + reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_MEAN); + + pbuf->params.awb.awb_mean[0].mean_cr_or_r = + RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(reg_val); + pbuf->params.awb.awb_mean[0].mean_cb_or_b = + RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(reg_val); + pbuf->params.awb.awb_mean[0].mean_y_or_g = + RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(reg_val); +} + +static void rkisp1_stats_get_aec_meas(struct rkisp1_stats *stats, + struct rkisp1_stat_buffer *pbuf) +{ + struct rkisp1_device *rkisp1 = stats->rkisp1; + unsigned int i; + + pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AUTOEXP; + for (i = 0; i < RKISP1_CIF_ISP_AE_MEAN_MAX; i++) + pbuf->params.ae.exp_mean[i] = + (u8)rkisp1_read(rkisp1, + RKISP1_CIF_ISP_EXP_MEAN_00 + i * 4); +} + +static void rkisp1_stats_get_afc_meas(struct rkisp1_stats *stats, + struct rkisp1_stat_buffer *pbuf) +{ + struct rkisp1_device *rkisp1 = stats->rkisp1; + struct rkisp1_cif_isp_af_stat *af; + + pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AFM; + + af = &pbuf->params.af; + af->window[0].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_A); + af->window[0].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_A); + af->window[1].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_B); + af->window[1].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_B); + af->window[2].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_C); + af->window[2].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_C); +} + +static void rkisp1_stats_get_hst_meas(struct rkisp1_stats *stats, + struct rkisp1_stat_buffer *pbuf) +{ + struct rkisp1_device *rkisp1 = stats->rkisp1; + unsigned int i; + + pbuf->meas_type |= RKISP1_CIF_ISP_STAT_HIST; + for (i = 0; i < RKISP1_CIF_ISP_HIST_BIN_N_MAX; i++) + pbuf->params.hist.hist_bins[i] = + (u8)rkisp1_read(rkisp1, + RKISP1_CIF_ISP_HIST_BIN_0 + i * 4); +} + +static void rkisp1_stats_get_bls_meas(struct rkisp1_stats *stats, + struct rkisp1_stat_buffer *pbuf) +{ + struct rkisp1_device *rkisp1 = stats->rkisp1; + const struct rkisp1_isp_mbus_info *in_fmt = rkisp1->isp.sink_fmt; + struct rkisp1_cif_isp_bls_meas_val *bls_val; + + bls_val = &pbuf->params.ae.bls_val; + if (in_fmt->bayer_pat == RKISP1_RAW_BGGR) { + bls_val->meas_b = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); + bls_val->meas_gb = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); + bls_val->meas_gr = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); + bls_val->meas_r = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); + } else if (in_fmt->bayer_pat == RKISP1_RAW_GBRG) { + bls_val->meas_gb = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); + bls_val->meas_b = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); + bls_val->meas_r = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); + bls_val->meas_gr = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); + } else if (in_fmt->bayer_pat == RKISP1_RAW_GRBG) { + bls_val->meas_gr = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); + bls_val->meas_r = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); + bls_val->meas_b = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); + bls_val->meas_gb = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); + } else if (in_fmt->bayer_pat == RKISP1_RAW_RGGB) { + bls_val->meas_r = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); + bls_val->meas_gr = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); + bls_val->meas_gb = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); + bls_val->meas_b = + rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); + } +} + +static void +rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris) +{ + struct rkisp1_stat_buffer *cur_stat_buf; + struct rkisp1_buffer *cur_buf = NULL; + unsigned int frame_sequence = stats->rkisp1->isp.frame_sequence; + u64 timestamp = ktime_get_ns(); + + /* get one empty buffer */ + if (!list_empty(&stats->stat)) { + cur_buf = list_first_entry(&stats->stat, + struct rkisp1_buffer, queue); + list_del(&cur_buf->queue); + } + + if (!cur_buf) + return; + + cur_stat_buf = + (struct rkisp1_stat_buffer *)(cur_buf->vaddr); + + if (isp_ris & RKISP1_CIF_ISP_AWB_DONE) + rkisp1_stats_get_awb_meas(stats, cur_stat_buf); + + if (isp_ris & RKISP1_CIF_ISP_AFM_FIN) + rkisp1_stats_get_afc_meas(stats, cur_stat_buf); + + if (isp_ris & RKISP1_CIF_ISP_EXP_END) { + rkisp1_stats_get_aec_meas(stats, cur_stat_buf); + rkisp1_stats_get_bls_meas(stats, cur_stat_buf); + } + + if (isp_ris & RKISP1_CIF_ISP_HIST_MEASURE_RDY) + rkisp1_stats_get_hst_meas(stats, cur_stat_buf); + + vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0, + sizeof(struct rkisp1_stat_buffer)); + cur_buf->vb.sequence = frame_sequence; + cur_buf->vb.vb2_buf.timestamp = timestamp; + vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); +} + +void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris) +{ + struct rkisp1_device *rkisp1 = stats->rkisp1; + unsigned int isp_mis_tmp = 0; + + spin_lock(&stats->lock); + + rkisp1_write(rkisp1, RKISP1_STATS_MEAS_MASK, RKISP1_CIF_ISP_ICR); + + isp_mis_tmp = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); + if (isp_mis_tmp & RKISP1_STATS_MEAS_MASK) + rkisp1->debug.stats_error++; + + if (isp_ris & RKISP1_STATS_MEAS_MASK) + rkisp1_stats_send_measurement(stats, isp_ris); + + spin_unlock(&stats->lock); +} + +static void rkisp1_init_stats(struct rkisp1_stats *stats) +{ + stats->vdev_fmt.fmt.meta.dataformat = + V4L2_META_FMT_RK_ISP1_STAT_3A; + stats->vdev_fmt.fmt.meta.buffersize = + sizeof(struct rkisp1_stat_buffer); +} + +int rkisp1_stats_register(struct rkisp1_device *rkisp1) +{ + struct rkisp1_stats *stats = &rkisp1->stats; + struct rkisp1_vdev_node *node = &stats->vnode; + struct video_device *vdev = &node->vdev; + int ret; + + stats->rkisp1 = rkisp1; + mutex_init(&node->vlock); + INIT_LIST_HEAD(&stats->stat); + spin_lock_init(&stats->lock); + + strscpy(vdev->name, RKISP1_STATS_DEV_NAME, sizeof(vdev->name)); + + video_set_drvdata(vdev, stats); + vdev->ioctl_ops = &rkisp1_stats_ioctl; + vdev->fops = &rkisp1_stats_fops; + vdev->release = video_device_release_empty; + vdev->lock = &node->vlock; + vdev->v4l2_dev = &rkisp1->v4l2_dev; + vdev->queue = &node->buf_queue; + vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; + vdev->vfl_dir = VFL_DIR_RX; + rkisp1_stats_init_vb2_queue(vdev->queue, stats); + rkisp1_init_stats(stats); + video_set_drvdata(vdev, stats); + + node->pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); + if (ret) + goto err_mutex_destroy; + + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(&vdev->dev, + "failed to register %s, ret=%d\n", vdev->name, ret); + goto err_cleanup_media_entity; + } + + return 0; + +err_cleanup_media_entity: + media_entity_cleanup(&vdev->entity); +err_mutex_destroy: + mutex_destroy(&node->vlock); + return ret; +} + +void rkisp1_stats_unregister(struct rkisp1_device *rkisp1) +{ + struct rkisp1_stats *stats = &rkisp1->stats; + struct rkisp1_vdev_node *node = &stats->vnode; + struct video_device *vdev = &node->vdev; + + vb2_video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); + mutex_destroy(&node->vlock); +} diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 747c6cf1d795..e8996b1c3b35 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -44,6 +44,4 @@ source "drivers/staging/media/tegra-video/Kconfig" source "drivers/staging/media/ipu3/Kconfig" -source "drivers/staging/media/rkisp1/Kconfig" - endif diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index b59571826ba6..24b5873ff760 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -10,5 +10,4 @@ obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/ obj-$(CONFIG_TEGRA_VDE) += tegra-vde/ obj-$(CONFIG_VIDEO_HANTRO) += hantro/ obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/ -obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rkisp1/ obj-$(CONFIG_VIDEO_ZORAN) += zoran/ diff --git a/drivers/staging/media/rkisp1/Documentation/devicetree/bindings/media/rockchip-isp1.yaml b/drivers/staging/media/rkisp1/Documentation/devicetree/bindings/media/rockchip-isp1.yaml deleted file mode 100644 index 2004c054ed1a..000000000000 --- a/drivers/staging/media/rkisp1/Documentation/devicetree/bindings/media/rockchip-isp1.yaml +++ /dev/null @@ -1,215 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0+ OR MIT) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/media/rockchip-isp1.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Rockchip SoC Image Signal Processing unit v1 - -maintainers: - - Helen Koike - -description: | - Rockchip ISP1 is the Camera interface for the Rockchip series of SoCs - which contains image processing, scaling, and compression functions. - -properties: - compatible: - const: rockchip,rk3399-cif-isp - - reg: - maxItems: 1 - - interrupts: - maxItems: 1 - - clocks: - minItems: 3 - items: - # isp0 and isp1 - - description: ISP clock - - description: ISP AXI clock - - description: ISP AHB clock - # only for isp1 - - description: ISP Pixel clock - - clock-names: - minItems: 3 - items: - # isp0 and isp1 - - const: isp - - const: aclk - - const: hclk - # only for isp1 - - const: pclk_isp - - iommus: - maxItems: 1 - - phys: - maxItems: 1 - description: phandle for the PHY port - - phy-names: - const: dphy - - power-domains: - maxItems: 1 - - # See ./video-interfaces.txt for details - ports: - type: object - additionalProperties: false - - properties: - "#address-cells": - const: 1 - - "#size-cells": - const: 0 - - port@0: - type: object - description: connection point for sensors at MIPI-DPHY RX0 - additionalProperties: false - - properties: - "#address-cells": - const: 1 - - "#size-cells": - const: 0 - - reg: - const: 0 - - patternProperties: - endpoint: - type: object - additionalProperties: false - - properties: - reg: - maxItems: 1 - - data-lanes: - minItems: 1 - maxItems: 4 - - remote-endpoint: true - - required: - - reg - - "#address-cells" - - "#size-cells" - - required: - - "#address-cells" - - "#size-cells" - - port@0 - -required: - - compatible - - reg - - interrupts - - clocks - - clock-names - - iommus - - phys - - phy-names - - power-domains - - ports - -if: - properties: - compatible: - contains: - const: rockchip,rk3399-cif-isp -then: - properties: - clocks: - minItems: 3 - maxItems: 4 - clock-names: - minItems: 3 - maxItems: 4 - -additionalProperties: false - -examples: - - | - - #include - #include - #include - - parent0: parent { - #address-cells = <2>; - #size-cells = <2>; - - isp0: isp0@ff910000 { - compatible = "rockchip,rk3399-cif-isp"; - reg = <0x0 0xff910000 0x0 0x4000>; - interrupts = ; - clocks = <&cru SCLK_ISP0>, - <&cru ACLK_ISP0_WRAPPER>, - <&cru HCLK_ISP0_WRAPPER>; - clock-names = "isp", "aclk", "hclk"; - iommus = <&isp0_mmu>; - phys = <&dphy>; - phy-names = "dphy"; - power-domains = <&power RK3399_PD_ISP0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - mipi_in_wcam: endpoint@0 { - reg = <0>; - remote-endpoint = <&wcam_out>; - data-lanes = <1 2>; - }; - - mipi_in_ucam: endpoint@1 { - reg = <1>; - remote-endpoint = <&ucam_out>; - data-lanes = <1>; - }; - }; - }; - }; - - i2c7: i2c { - #address-cells = <1>; - #size-cells = <0>; - - wcam: camera@36 { - compatible = "ovti,ov5695"; - reg = <0x36>; - - port { - wcam_out: endpoint { - remote-endpoint = <&mipi_in_wcam>; - data-lanes = <1 2>; - }; - }; - }; - - ucam: camera@3c { - compatible = "ovti,ov2685"; - reg = <0x3c>; - - port { - ucam_out: endpoint { - remote-endpoint = <&mipi_in_ucam>; - data-lanes = <1>; - }; - }; - }; - }; - }; diff --git a/drivers/staging/media/rkisp1/Kconfig b/drivers/staging/media/rkisp1/Kconfig deleted file mode 100644 index 41f5def9ea44..000000000000 --- a/drivers/staging/media/rkisp1/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config VIDEO_ROCKCHIP_ISP1 - tristate "Rockchip Image Signal Processing v1 Unit driver" - depends on VIDEO_V4L2 && OF - depends on ARCH_ROCKCHIP || COMPILE_TEST - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select VIDEOBUF2_DMA_CONTIG - select VIDEOBUF2_VMALLOC - select V4L2_FWNODE - select GENERIC_PHY_MIPI_DPHY - default n - help - Enable this to support the Image Signal Processing (ISP) module - present in RK3399 SoCs. - - To compile this driver as a module, choose M here: the module - will be called rockchip-isp1. diff --git a/drivers/staging/media/rkisp1/Makefile b/drivers/staging/media/rkisp1/Makefile deleted file mode 100644 index ab32a77db8f7..000000000000 --- a/drivers/staging/media/rkisp1/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 - -obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip-isp1.o -rockchip-isp1-objs += rkisp1-capture.o \ - rkisp1-common.o \ - rkisp1-dev.o \ - rkisp1-isp.o \ - rkisp1-resizer.o \ - rkisp1-stats.o \ - rkisp1-params.o diff --git a/drivers/staging/media/rkisp1/TODO b/drivers/staging/media/rkisp1/TODO deleted file mode 100644 index ca3651fd0833..000000000000 --- a/drivers/staging/media/rkisp1/TODO +++ /dev/null @@ -1,8 +0,0 @@ -* Fix checkpatch errors. - -NOTES: -* All v4l2-compliance test must pass. -* Stats and params can be tested with libcamera and ChromiumOS stack. - -Please CC patches to Linux Media and -Helen Koike . diff --git a/drivers/staging/media/rkisp1/rkisp1-capture.c b/drivers/staging/media/rkisp1/rkisp1-capture.c deleted file mode 100644 index b81235afd053..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-capture.c +++ /dev/null @@ -1,1431 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - V4l capture device - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rkisp1-common.h" - -/* - * NOTE: There are two capture video devices in rkisp1, selfpath and mainpath. - * - * differences between selfpath and mainpath - * available mp sink input: isp - * available sp sink input : isp, dma(TODO) - * available mp sink pad fmts: yuv422, raw - * available sp sink pad fmts: yuv422, yuv420...... - * available mp source fmts: yuv, raw, jpeg(TODO) - * available sp source fmts: yuv, rgb - */ - -#define RKISP1_SP_DEV_NAME RKISP1_DRIVER_NAME "_selfpath" -#define RKISP1_MP_DEV_NAME RKISP1_DRIVER_NAME "_mainpath" - -#define RKISP1_MIN_BUFFERS_NEEDED 3 - -enum rkisp1_plane { - RKISP1_PLANE_Y = 0, - RKISP1_PLANE_CB = 1, - RKISP1_PLANE_CR = 2 -}; - -/* - * @fourcc: pixel format - * @fmt_type: helper filed for pixel format - * @uv_swap: if cb cr swaped, for yuv - * @write_format: defines how YCbCr self picture data is written to memory - * @output_format: defines sp output format - * @mbus: the mbus code on the src resizer pad that matches the pixel format - */ -struct rkisp1_capture_fmt_cfg { - u32 fourcc; - u8 uv_swap; - u32 write_format; - u32 output_format; - u32 mbus; -}; - -struct rkisp1_capture_ops { - void (*config)(struct rkisp1_capture *cap); - void (*stop)(struct rkisp1_capture *cap); - void (*enable)(struct rkisp1_capture *cap); - void (*disable)(struct rkisp1_capture *cap); - void (*set_data_path)(struct rkisp1_capture *cap); - bool (*is_stopped)(struct rkisp1_capture *cap); -}; - -struct rkisp1_capture_config { - const struct rkisp1_capture_fmt_cfg *fmts; - int fmt_size; - struct { - u32 y_size_init; - u32 cb_size_init; - u32 cr_size_init; - u32 y_base_ad_init; - u32 cb_base_ad_init; - u32 cr_base_ad_init; - u32 y_offs_cnt_init; - u32 cb_offs_cnt_init; - u32 cr_offs_cnt_init; - } mi; -}; - -/* - * The supported pixel formats for mainpath. NOTE, pixel formats with identical 'mbus' - * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes - */ -static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = { - /* yuv422 */ - { - .fourcc = V4L2_PIX_FMT_YUYV, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV422P, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV16, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV61, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU422M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv400 */ - { - .fourcc = V4L2_PIX_FMT_GREY, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv420 */ - { - .fourcc = V4L2_PIX_FMT_NV21, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV21M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12M, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV420, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU420, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, - /* raw */ - { - .fourcc = V4L2_PIX_FMT_SRGGB8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SRGGB8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SGRBG8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SGBRG8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SBGGR8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SRGGB10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGRBG10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGBRG10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SBGGR10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SRGGB12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGRBG12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGBRG12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SBGGR12_1X12, - }, -}; - -/* - * The supported pixel formats for selfpath. NOTE, pixel formats with identical 'mbus' - * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes - */ -static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = { - /* yuv422 */ - { - .fourcc = V4L2_PIX_FMT_YUYV, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_INT, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV422P, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV16, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV61, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU422M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv400 */ - { - .fourcc = V4L2_PIX_FMT_GREY, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV400, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* rgb */ - { - .fourcc = V4L2_PIX_FMT_XBGR32, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_RGB565, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv420 */ - { - .fourcc = V4L2_PIX_FMT_NV21, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV21M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12M, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV420, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU420, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, -}; - -static const struct rkisp1_capture_config rkisp1_capture_config_mp = { - .fmts = rkisp1_mp_fmts, - .fmt_size = ARRAY_SIZE(rkisp1_mp_fmts), - .mi = { - .y_size_init = RKISP1_CIF_MI_MP_Y_SIZE_INIT, - .cb_size_init = RKISP1_CIF_MI_MP_CB_SIZE_INIT, - .cr_size_init = RKISP1_CIF_MI_MP_CR_SIZE_INIT, - .y_base_ad_init = RKISP1_CIF_MI_MP_Y_BASE_AD_INIT, - .cb_base_ad_init = RKISP1_CIF_MI_MP_CB_BASE_AD_INIT, - .cr_base_ad_init = RKISP1_CIF_MI_MP_CR_BASE_AD_INIT, - .y_offs_cnt_init = RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT, - .cb_offs_cnt_init = RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT, - .cr_offs_cnt_init = RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT, - }, -}; - -static const struct rkisp1_capture_config rkisp1_capture_config_sp = { - .fmts = rkisp1_sp_fmts, - .fmt_size = ARRAY_SIZE(rkisp1_sp_fmts), - .mi = { - .y_size_init = RKISP1_CIF_MI_SP_Y_SIZE_INIT, - .cb_size_init = RKISP1_CIF_MI_SP_CB_SIZE_INIT, - .cr_size_init = RKISP1_CIF_MI_SP_CR_SIZE_INIT, - .y_base_ad_init = RKISP1_CIF_MI_SP_Y_BASE_AD_INIT, - .cb_base_ad_init = RKISP1_CIF_MI_SP_CB_BASE_AD_INIT, - .cr_base_ad_init = RKISP1_CIF_MI_SP_CR_BASE_AD_INIT, - .y_offs_cnt_init = RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT, - .cb_offs_cnt_init = RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT, - .cr_offs_cnt_init = RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT, - }, -}; - -static inline struct rkisp1_vdev_node * -rkisp1_vdev_to_node(struct video_device *vdev) -{ - return container_of(vdev, struct rkisp1_vdev_node, vdev); -} - -int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct rkisp1_capture_fmt_cfg *fmts = cap->config->fmts; - /* - * initialize curr_mbus to non existing mbus code 0 to ensure it is - * different from fmts[0].mbus - */ - u32 curr_mbus = 0; - int i, n = 0; - - for (i = 0; i < cap->config->fmt_size; i++) { - if (fmts[i].mbus == curr_mbus) - continue; - - curr_mbus = fmts[i].mbus; - if (n++ == code->index) { - code->code = curr_mbus; - return 0; - } - } - return -EINVAL; -} - -/* ---------------------------------------------------------------------------- - * Stream operations for self-picture path (sp) and main-picture path (mp) - */ - -static void rkisp1_mi_config_ctrl(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~GENMASK(17, 16); - mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64; - - mi_ctrl &= ~GENMASK(19, 18); - mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64; - - mi_ctrl |= RKISP1_CIF_MI_CTRL_INIT_BASE_EN | - RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN; - - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static u32 rkisp1_pixfmt_comp_size(const struct v4l2_pix_format_mplane *pixm, - unsigned int component) -{ - /* - * If packed format, then plane_fmt[0].sizeimage is the sum of all - * components, so we need to calculate just the size of Y component. - * See rkisp1_fill_pixfmt(). - */ - if (!component && pixm->num_planes == 1) - return pixm->plane_fmt[0].bytesperline * pixm->height; - return pixm->plane_fmt[component].sizeimage; -} - -static void rkisp1_irq_frame_end_enable(struct rkisp1_capture *cap) -{ - u32 mi_imsc = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_IMSC); - - mi_imsc |= RKISP1_CIF_MI_FRAME(cap); - rkisp1_write(cap->rkisp1, mi_imsc, RKISP1_CIF_MI_IMSC); -} - -static void rkisp1_mp_config(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_device *rkisp1 = cap->rkisp1; - u32 reg; - - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - cap->config->mi.y_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - cap->config->mi.cb_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), - cap->config->mi.cr_size_init); - - rkisp1_irq_frame_end_enable(cap); - - /* set uv swapping for semiplanar formats */ - if (cap->pix.info->comp_planes == 2) { - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - if (cap->pix.cfg->uv_swap) - reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; - else - reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - } - - rkisp1_mi_config_ctrl(cap); - - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - reg &= ~RKISP1_MI_CTRL_MP_FMT_MASK; - reg |= cap->pix.cfg->write_format; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); - - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - reg |= RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_config(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_device *rkisp1 = cap->rkisp1; - u32 mi_ctrl, reg; - - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - cap->config->mi.y_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - cap->config->mi.cb_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), - cap->config->mi.cr_size_init); - - rkisp1_write(rkisp1, pixm->width, RKISP1_CIF_MI_SP_Y_PIC_WIDTH); - rkisp1_write(rkisp1, pixm->height, RKISP1_CIF_MI_SP_Y_PIC_HEIGHT); - rkisp1_write(rkisp1, cap->sp_y_stride, RKISP1_CIF_MI_SP_Y_LLENGTH); - - rkisp1_irq_frame_end_enable(cap); - - /* set uv swapping for semiplanar formats */ - if (cap->pix.info->comp_planes == 2) { - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - if (cap->pix.cfg->uv_swap) - reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; - else - reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - } - - rkisp1_mi_config_ctrl(cap); - - mi_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - mi_ctrl &= ~RKISP1_MI_CTRL_SP_FMT_MASK; - mi_ctrl |= cap->pix.cfg->write_format | - RKISP1_MI_CTRL_SP_INPUT_YUV422 | - cap->pix.cfg->output_format | - RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE; - rkisp1_write(rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_disable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~(RKISP1_CIF_MI_CTRL_MP_ENABLE | - RKISP1_CIF_MI_CTRL_RAW_ENABLE); - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_disable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~RKISP1_CIF_MI_CTRL_SP_ENABLE; - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_enable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl; - - rkisp1_mp_disable(cap); - - mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - if (v4l2_is_format_bayer(cap->pix.info)) - mi_ctrl |= RKISP1_CIF_MI_CTRL_RAW_ENABLE; - /* YUV */ - else - mi_ctrl |= RKISP1_CIF_MI_CTRL_MP_ENABLE; - - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_enable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl |= RKISP1_CIF_MI_CTRL_SP_ENABLE; - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_sp_stop(struct rkisp1_capture *cap) -{ - if (!cap->is_streaming) - return; - rkisp1_write(cap->rkisp1, - RKISP1_CIF_MI_FRAME(cap), RKISP1_CIF_MI_ICR); - cap->ops->disable(cap); -} - -static bool rkisp1_mp_is_stopped(struct rkisp1_capture *cap) -{ - u32 en = RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED | - RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED; - - return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & en); -} - -static bool rkisp1_sp_is_stopped(struct rkisp1_capture *cap) -{ - return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & - RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED); -} - -static void rkisp1_mp_set_data_path(struct rkisp1_capture *cap) -{ - u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); - - dpcl = dpcl | RKISP1_CIF_VI_DPCL_CHAN_MODE_MP | - RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI; - rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); -} - -static void rkisp1_sp_set_data_path(struct rkisp1_capture *cap) -{ - u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); - - dpcl |= RKISP1_CIF_VI_DPCL_CHAN_MODE_SP; - rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); -} - -static struct rkisp1_capture_ops rkisp1_capture_ops_mp = { - .config = rkisp1_mp_config, - .enable = rkisp1_mp_enable, - .disable = rkisp1_mp_disable, - .stop = rkisp1_mp_sp_stop, - .set_data_path = rkisp1_mp_set_data_path, - .is_stopped = rkisp1_mp_is_stopped, -}; - -static struct rkisp1_capture_ops rkisp1_capture_ops_sp = { - .config = rkisp1_sp_config, - .enable = rkisp1_sp_enable, - .disable = rkisp1_sp_disable, - .stop = rkisp1_mp_sp_stop, - .set_data_path = rkisp1_sp_set_data_path, - .is_stopped = rkisp1_sp_is_stopped, -}; - -/* ---------------------------------------------------------------------------- - * Frame buffer operations - */ - -static int rkisp1_dummy_buf_create(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_dummy_buffer *dummy_buf = &cap->buf.dummy; - - dummy_buf->size = max3(rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); - - /* The driver never access vaddr, no mapping is required */ - dummy_buf->vaddr = dma_alloc_attrs(cap->rkisp1->dev, - dummy_buf->size, - &dummy_buf->dma_addr, - GFP_KERNEL, - DMA_ATTR_NO_KERNEL_MAPPING); - if (!dummy_buf->vaddr) - return -ENOMEM; - - return 0; -} - -static void rkisp1_dummy_buf_destroy(struct rkisp1_capture *cap) -{ - dma_free_attrs(cap->rkisp1->dev, - cap->buf.dummy.size, cap->buf.dummy.vaddr, - cap->buf.dummy.dma_addr, DMA_ATTR_NO_KERNEL_MAPPING); -} - -static void rkisp1_set_next_buf(struct rkisp1_capture *cap) -{ - cap->buf.curr = cap->buf.next; - cap->buf.next = NULL; - - if (!list_empty(&cap->buf.queue)) { - u32 *buff_addr; - - cap->buf.next = list_first_entry(&cap->buf.queue, struct rkisp1_buffer, queue); - list_del(&cap->buf.next->queue); - - buff_addr = cap->buf.next->buff_addr; - - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_Y], - cap->config->mi.y_base_ad_init); - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_CB], - cap->config->mi.cb_base_ad_init); - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_CR], - cap->config->mi.cr_base_ad_init); - } else { - /* - * Use the dummy space allocated by dma_alloc_coherent to - * throw data if there is no available buffer. - */ - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.y_base_ad_init); - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.cb_base_ad_init); - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.cr_base_ad_init); - } - - /* Set plane offsets */ - rkisp1_write(cap->rkisp1, 0, cap->config->mi.y_offs_cnt_init); - rkisp1_write(cap->rkisp1, 0, cap->config->mi.cb_offs_cnt_init); - rkisp1_write(cap->rkisp1, 0, cap->config->mi.cr_offs_cnt_init); -} - -/* - * This function is called when a frame end comes. The next frame - * is processing and we should set up buffer for next-next frame, - * otherwise it will overflow. - */ -static void rkisp1_handle_buffer(struct rkisp1_capture *cap) -{ - struct rkisp1_isp *isp = &cap->rkisp1->isp; - struct rkisp1_buffer *curr_buf; - - spin_lock(&cap->buf.lock); - curr_buf = cap->buf.curr; - - if (curr_buf) { - curr_buf->vb.sequence = isp->frame_sequence; - curr_buf->vb.vb2_buf.timestamp = ktime_get_boottime_ns(); - curr_buf->vb.field = V4L2_FIELD_NONE; - vb2_buffer_done(&curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } else { - cap->rkisp1->debug.frame_drop[cap->id]++; - } - - rkisp1_set_next_buf(cap); - spin_unlock(&cap->buf.lock); -} - -void rkisp1_capture_isr(struct rkisp1_device *rkisp1) -{ - unsigned int i; - u32 status; - - status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS); - rkisp1_write(rkisp1, status, RKISP1_CIF_MI_ICR); - - for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) { - struct rkisp1_capture *cap = &rkisp1->capture_devs[i]; - - if (!(status & RKISP1_CIF_MI_FRAME(cap))) - continue; - if (!cap->is_stopping) { - rkisp1_handle_buffer(cap); - continue; - } - /* - * Make sure stream is actually stopped, whose state - * can be read from the shadow register, before - * wake_up() thread which would immediately free all - * frame buffers. stop() takes effect at the next - * frame end that sync the configurations to shadow - * regs. - */ - if (!cap->ops->is_stopped(cap)) { - cap->ops->stop(cap); - continue; - } - cap->is_stopping = false; - cap->is_streaming = false; - wake_up(&cap->done); - } -} - -/* ---------------------------------------------------------------------------- - * Vb2 operations - */ - -static int rkisp1_vb2_queue_setup(struct vb2_queue *queue, - unsigned int *num_buffers, - unsigned int *num_planes, - unsigned int sizes[], - struct device *alloc_devs[]) -{ - struct rkisp1_capture *cap = queue->drv_priv; - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - unsigned int i; - - if (*num_planes) { - if (*num_planes != pixm->num_planes) - return -EINVAL; - - for (i = 0; i < pixm->num_planes; i++) - if (sizes[i] < pixm->plane_fmt[i].sizeimage) - return -EINVAL; - } else { - *num_planes = pixm->num_planes; - for (i = 0; i < pixm->num_planes; i++) - sizes[i] = pixm->plane_fmt[i].sizeimage; - } - - return 0; -} - -static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkisp1_buffer *ispbuf = - container_of(vbuf, struct rkisp1_buffer, vb); - struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - unsigned int i; - - memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr)); - for (i = 0; i < pixm->num_planes; i++) - ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); - - /* Convert to non-MPLANE */ - if (pixm->num_planes == 1) { - ispbuf->buff_addr[RKISP1_PLANE_CB] = - ispbuf->buff_addr[RKISP1_PLANE_Y] + - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y); - ispbuf->buff_addr[RKISP1_PLANE_CR] = - ispbuf->buff_addr[RKISP1_PLANE_CB] + - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB); - } - - /* - * uv swap can be supported for planar formats by switching - * the address of cb and cr - */ - if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap) - swap(ispbuf->buff_addr[RKISP1_PLANE_CR], - ispbuf->buff_addr[RKISP1_PLANE_CB]); - - spin_lock_irq(&cap->buf.lock); - list_add_tail(&ispbuf->queue, &cap->buf.queue); - spin_unlock_irq(&cap->buf.lock); -} - -static int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb) -{ - struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; - unsigned int i; - - for (i = 0; i < cap->pix.fmt.num_planes; i++) { - unsigned long size = cap->pix.fmt.plane_fmt[i].sizeimage; - - if (vb2_plane_size(vb, i) < size) { - dev_err(cap->rkisp1->dev, - "User buffer too small (%ld < %ld)\n", - vb2_plane_size(vb, i), size); - return -EINVAL; - } - vb2_set_plane_payload(vb, i, size); - } - - return 0; -} - -static void rkisp1_return_all_buffers(struct rkisp1_capture *cap, - enum vb2_buffer_state state) -{ - struct rkisp1_buffer *buf; - - spin_lock_irq(&cap->buf.lock); - if (cap->buf.curr) { - vb2_buffer_done(&cap->buf.curr->vb.vb2_buf, state); - cap->buf.curr = NULL; - } - if (cap->buf.next) { - vb2_buffer_done(&cap->buf.next->vb.vb2_buf, state); - cap->buf.next = NULL; - } - while (!list_empty(&cap->buf.queue)) { - buf = list_first_entry(&cap->buf.queue, - struct rkisp1_buffer, queue); - list_del(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, state); - } - spin_unlock_irq(&cap->buf.lock); -} - -/* - * Most of registers inside rockchip ISP1 have shadow register since - * they must be not be changed during processing a frame. - * Usually, each sub-module updates its shadow register after - * processing the last pixel of a frame. - */ -static void rkisp1_cap_stream_enable(struct rkisp1_capture *cap) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - struct rkisp1_capture *other = &rkisp1->capture_devs[cap->id ^ 1]; - - cap->ops->set_data_path(cap); - cap->ops->config(cap); - - /* Setup a buffer for the next frame */ - spin_lock_irq(&cap->buf.lock); - rkisp1_set_next_buf(cap); - cap->ops->enable(cap); - /* It's safe to config ACTIVE and SHADOW regs for the - * first stream. While when the second is starting, do NOT - * force update because it also update the first one. - * - * The latter case would drop one more buf(that is 2) since - * there's not buf in shadow when the second FE received. This's - * also required because the second FE maybe corrupt especially - * when run at 120fps. - */ - if (!other->is_streaming) { - /* force cfg update */ - rkisp1_write(rkisp1, - RKISP1_CIF_MI_INIT_SOFT_UPD, RKISP1_CIF_MI_INIT); - rkisp1_set_next_buf(cap); - } - spin_unlock_irq(&cap->buf.lock); - cap->is_streaming = true; -} - -static void rkisp1_cap_stream_disable(struct rkisp1_capture *cap) -{ - int ret; - - /* Stream should stop in interrupt. If it dosn't, stop it by force. */ - cap->is_stopping = true; - ret = wait_event_timeout(cap->done, - !cap->is_streaming, - msecs_to_jiffies(1000)); - if (!ret) { - cap->rkisp1->debug.stop_timeout[cap->id]++; - cap->ops->stop(cap); - cap->is_stopping = false; - cap->is_streaming = false; - } -} - -/* - * rkisp1_pipeline_stream_disable - disable nodes in the pipeline - * - * Call s_stream(false) in the reverse order from - * rkisp1_pipeline_stream_enable() and disable the DMA engine. - * Should be called before media_pipeline_stop() - */ -static void rkisp1_pipeline_stream_disable(struct rkisp1_capture *cap) - __must_hold(&cap->rkisp1->stream_lock) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - - rkisp1_cap_stream_disable(cap); - - /* - * If the other capture is streaming, isp and sensor nodes shouldn't - * be disabled, skip them. - */ - if (rkisp1->pipe.streaming_count < 2) { - v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, - false); - v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); - } - - v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, - false); -} - -/* - * rkisp1_pipeline_stream_enable - enable nodes in the pipeline - * - * Enable the DMA Engine and call s_stream(true) through the pipeline. - * Should be called after media_pipeline_start() - */ -static int rkisp1_pipeline_stream_enable(struct rkisp1_capture *cap) - __must_hold(&cap->rkisp1->stream_lock) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - int ret; - - rkisp1_cap_stream_enable(cap); - - ret = v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, - s_stream, true); - if (ret) - goto err_disable_cap; - - /* - * If the other capture is streaming, isp and sensor nodes are already - * enabled, skip them. - */ - if (rkisp1->pipe.streaming_count > 1) - return 0; - - ret = v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, true); - if (ret) - goto err_disable_rsz; - - ret = v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, - true); - if (ret) - goto err_disable_isp; - - return 0; - -err_disable_isp: - v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); -err_disable_rsz: - v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, - false); -err_disable_cap: - rkisp1_cap_stream_disable(cap); - - return ret; -} - -static void rkisp1_vb2_stop_streaming(struct vb2_queue *queue) -{ - struct rkisp1_capture *cap = queue->drv_priv; - struct rkisp1_vdev_node *node = &cap->vnode; - struct rkisp1_device *rkisp1 = cap->rkisp1; - int ret; - - mutex_lock(&cap->rkisp1->stream_lock); - - rkisp1_pipeline_stream_disable(cap); - - rkisp1_return_all_buffers(cap, VB2_BUF_STATE_ERROR); - - v4l2_pipeline_pm_put(&node->vdev.entity); - ret = pm_runtime_put(rkisp1->dev); - if (ret < 0) - dev_err(rkisp1->dev, "power down failed error:%d\n", ret); - - rkisp1_dummy_buf_destroy(cap); - - media_pipeline_stop(&node->vdev.entity); - - mutex_unlock(&cap->rkisp1->stream_lock); -} - -static int -rkisp1_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) -{ - struct rkisp1_capture *cap = queue->drv_priv; - struct media_entity *entity = &cap->vnode.vdev.entity; - int ret; - - mutex_lock(&cap->rkisp1->stream_lock); - - ret = media_pipeline_start(entity, &cap->rkisp1->pipe); - if (ret) { - dev_err(cap->rkisp1->dev, "start pipeline failed %d\n", ret); - goto err_ret_buffers; - } - - ret = rkisp1_dummy_buf_create(cap); - if (ret) - goto err_pipeline_stop; - - ret = pm_runtime_get_sync(cap->rkisp1->dev); - if (ret < 0) { - pm_runtime_put_noidle(cap->rkisp1->dev); - dev_err(cap->rkisp1->dev, "power up failed %d\n", ret); - goto err_destroy_dummy; - } - ret = v4l2_pipeline_pm_get(entity); - if (ret) { - dev_err(cap->rkisp1->dev, "open cif pipeline failed %d\n", ret); - goto err_pipe_pm_put; - } - - ret = rkisp1_pipeline_stream_enable(cap); - if (ret) - goto err_v4l2_pm_put; - - mutex_unlock(&cap->rkisp1->stream_lock); - - return 0; - -err_v4l2_pm_put: - v4l2_pipeline_pm_put(entity); -err_pipe_pm_put: - pm_runtime_put(cap->rkisp1->dev); -err_destroy_dummy: - rkisp1_dummy_buf_destroy(cap); -err_pipeline_stop: - media_pipeline_stop(entity); -err_ret_buffers: - rkisp1_return_all_buffers(cap, VB2_BUF_STATE_QUEUED); - mutex_unlock(&cap->rkisp1->stream_lock); - - return ret; -} - -static struct vb2_ops rkisp1_vb2_ops = { - .queue_setup = rkisp1_vb2_queue_setup, - .buf_queue = rkisp1_vb2_buf_queue, - .buf_prepare = rkisp1_vb2_buf_prepare, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .stop_streaming = rkisp1_vb2_stop_streaming, - .start_streaming = rkisp1_vb2_start_streaming, -}; - -/* ---------------------------------------------------------------------------- - * IOCTLs operations - */ - -static const struct v4l2_format_info * -rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm, - enum rkisp1_stream_id id) -{ - struct v4l2_plane_pix_format *plane_y = &pixm->plane_fmt[0]; - const struct v4l2_format_info *info; - unsigned int i; - u32 stride; - - memset(pixm->plane_fmt, 0, sizeof(pixm->plane_fmt)); - info = v4l2_format_info(pixm->pixelformat); - pixm->num_planes = info->mem_planes; - stride = info->bpp[0] * pixm->width; - /* Self path supports custom stride but Main path doesn't */ - if (id == RKISP1_MAINPATH || plane_y->bytesperline < stride) - plane_y->bytesperline = stride; - plane_y->sizeimage = plane_y->bytesperline * pixm->height; - - /* normalize stride to pixels per line */ - stride = DIV_ROUND_UP(plane_y->bytesperline, info->bpp[0]); - - for (i = 1; i < info->comp_planes; i++) { - struct v4l2_plane_pix_format *plane = &pixm->plane_fmt[i]; - - /* bytesperline for other components derive from Y component */ - plane->bytesperline = DIV_ROUND_UP(stride, info->hdiv) * - info->bpp[i]; - plane->sizeimage = plane->bytesperline * - DIV_ROUND_UP(pixm->height, info->vdiv); - } - - /* - * If pixfmt is packed, then plane_fmt[0] should contain the total size - * considering all components. plane_fmt[i] for i > 0 should be ignored - * by userspace as mem_planes == 1, but we are keeping information there - * for convenience. - */ - if (info->mem_planes == 1) - for (i = 1; i < info->comp_planes; i++) - plane_y->sizeimage += pixm->plane_fmt[i].sizeimage; - - return info; -} - -static const struct rkisp1_capture_fmt_cfg * -rkisp1_find_fmt_cfg(const struct rkisp1_capture *cap, const u32 pixelfmt) -{ - unsigned int i; - - for (i = 0; i < cap->config->fmt_size; i++) { - if (cap->config->fmts[i].fourcc == pixelfmt) - return &cap->config->fmts[i]; - } - return NULL; -} - -static void rkisp1_try_fmt(const struct rkisp1_capture *cap, - struct v4l2_pix_format_mplane *pixm, - const struct rkisp1_capture_fmt_cfg **fmt_cfg, - const struct v4l2_format_info **fmt_info) -{ - const struct rkisp1_capture_config *config = cap->config; - const struct rkisp1_capture_fmt_cfg *fmt; - const struct v4l2_format_info *info; - const unsigned int max_widths[] = { RKISP1_RSZ_MP_SRC_MAX_WIDTH, - RKISP1_RSZ_SP_SRC_MAX_WIDTH }; - const unsigned int max_heights[] = { RKISP1_RSZ_MP_SRC_MAX_HEIGHT, - RKISP1_RSZ_SP_SRC_MAX_HEIGHT}; - - fmt = rkisp1_find_fmt_cfg(cap, pixm->pixelformat); - if (!fmt) { - fmt = config->fmts; - pixm->pixelformat = fmt->fourcc; - } - - pixm->width = clamp_t(u32, pixm->width, - RKISP1_RSZ_SRC_MIN_WIDTH, max_widths[cap->id]); - pixm->height = clamp_t(u32, pixm->height, - RKISP1_RSZ_SRC_MIN_HEIGHT, max_heights[cap->id]); - - pixm->field = V4L2_FIELD_NONE; - pixm->colorspace = V4L2_COLORSPACE_DEFAULT; - pixm->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; - pixm->quantization = V4L2_QUANTIZATION_DEFAULT; - - info = rkisp1_fill_pixfmt(pixm, cap->id); - - if (fmt_cfg) - *fmt_cfg = fmt; - if (fmt_info) - *fmt_info = info; -} - -static void rkisp1_set_fmt(struct rkisp1_capture *cap, - struct v4l2_pix_format_mplane *pixm) -{ - rkisp1_try_fmt(cap, pixm, &cap->pix.cfg, &cap->pix.info); - cap->pix.fmt = *pixm; - - /* SP supports custom stride in number of pixels of the Y plane */ - if (cap->id == RKISP1_SELFPATH) - cap->sp_y_stride = pixm->plane_fmt[0].bytesperline / - cap->pix.info->bpp[0]; -} - -static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct rkisp1_capture *cap = video_drvdata(file); - - rkisp1_try_fmt(cap, &f->fmt.pix_mp, NULL, NULL); - - return 0; -} - -static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct rkisp1_capture *cap = video_drvdata(file); - const struct rkisp1_capture_fmt_cfg *fmt = NULL; - unsigned int i, n = 0; - - if (!f->mbus_code) { - if (f->index >= cap->config->fmt_size) - return -EINVAL; - - fmt = &cap->config->fmts[f->index]; - f->pixelformat = fmt->fourcc; - return 0; - } - - for (i = 0; i < cap->config->fmt_size; i++) { - if (cap->config->fmts[i].mbus != f->mbus_code) - continue; - - if (n++ == f->index) { - f->pixelformat = cap->config->fmts[i].fourcc; - return 0; - } - } - return -EINVAL; -} - -static int rkisp1_s_fmt_vid_cap_mplane(struct file *file, - void *priv, struct v4l2_format *f) -{ - struct rkisp1_capture *cap = video_drvdata(file); - struct rkisp1_vdev_node *node = - rkisp1_vdev_to_node(&cap->vnode.vdev); - - if (vb2_is_busy(&node->buf_queue)) - return -EBUSY; - - rkisp1_set_fmt(cap, &f->fmt.pix_mp); - - return 0; -} - -static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct rkisp1_capture *cap = video_drvdata(file); - - f->fmt.pix_mp = cap->pix.fmt; - - return 0; -} - -static int -rkisp1_querycap(struct file *file, void *priv, struct v4l2_capability *cap) -{ - struct rkisp1_capture *cap_dev = video_drvdata(file); - struct rkisp1_device *rkisp1 = cap_dev->rkisp1; - - strscpy(cap->driver, rkisp1->dev->driver->name, sizeof(cap->driver)); - strscpy(cap->card, rkisp1->dev->driver->name, sizeof(cap->card)); - strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); - - return 0; -} - -static const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = { - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane, - .vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane, - .vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane, - .vidioc_enum_fmt_vid_cap = rkisp1_enum_fmt_vid_cap_mplane, - .vidioc_querycap = rkisp1_querycap, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static int rkisp1_capture_link_validate(struct media_link *link) -{ - struct video_device *vdev = - media_entity_to_video_device(link->sink->entity); - struct v4l2_subdev *sd = - media_entity_to_v4l2_subdev(link->source->entity); - struct rkisp1_capture *cap = video_get_drvdata(vdev); - const struct rkisp1_capture_fmt_cfg *fmt = - rkisp1_find_fmt_cfg(cap, cap->pix.fmt.pixelformat); - struct v4l2_subdev_format sd_fmt; - int ret; - - sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - sd_fmt.pad = link->source->index; - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt); - if (ret) - return ret; - - if (sd_fmt.format.height != cap->pix.fmt.height || - sd_fmt.format.width != cap->pix.fmt.width || - sd_fmt.format.code != fmt->mbus) - return -EPIPE; - - return 0; -} - -/* ---------------------------------------------------------------------------- - * core functions - */ - -static const struct media_entity_operations rkisp1_media_ops = { - .link_validate = rkisp1_capture_link_validate, -}; - -static const struct v4l2_file_operations rkisp1_fops = { - .open = v4l2_fh_open, - .release = vb2_fop_release, - .unlocked_ioctl = video_ioctl2, - .poll = vb2_fop_poll, - .mmap = vb2_fop_mmap, -}; - -static void rkisp1_unregister_capture(struct rkisp1_capture *cap) -{ - media_entity_cleanup(&cap->vnode.vdev.entity); - vb2_video_unregister_device(&cap->vnode.vdev); -} - -void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1) -{ - struct rkisp1_capture *mp = &rkisp1->capture_devs[RKISP1_MAINPATH]; - struct rkisp1_capture *sp = &rkisp1->capture_devs[RKISP1_SELFPATH]; - - rkisp1_unregister_capture(mp); - rkisp1_unregister_capture(sp); -} - -static int rkisp1_register_capture(struct rkisp1_capture *cap) -{ - const char * const dev_names[] = {RKISP1_MP_DEV_NAME, - RKISP1_SP_DEV_NAME}; - struct v4l2_device *v4l2_dev = &cap->rkisp1->v4l2_dev; - struct video_device *vdev = &cap->vnode.vdev; - struct rkisp1_vdev_node *node; - struct vb2_queue *q; - int ret; - - strscpy(vdev->name, dev_names[cap->id], sizeof(vdev->name)); - node = rkisp1_vdev_to_node(vdev); - mutex_init(&node->vlock); - - vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops; - vdev->release = video_device_release_empty; - vdev->fops = &rkisp1_fops; - vdev->minor = -1; - vdev->v4l2_dev = v4l2_dev; - vdev->lock = &node->vlock; - vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | - V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; - vdev->entity.ops = &rkisp1_media_ops; - video_set_drvdata(vdev, cap); - vdev->vfl_dir = VFL_DIR_RX; - node->pad.flags = MEDIA_PAD_FL_SINK; - - q = &node->buf_queue; - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - q->io_modes = VB2_MMAP | VB2_DMABUF; - q->drv_priv = cap; - q->ops = &rkisp1_vb2_ops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct rkisp1_buffer); - q->min_buffers_needed = RKISP1_MIN_BUFFERS_NEEDED; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; - q->dev = cap->rkisp1->dev; - ret = vb2_queue_init(q); - if (ret) { - dev_err(cap->rkisp1->dev, - "vb2 queue init failed (err=%d)\n", ret); - return ret; - } - - vdev->queue = q; - - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret) { - dev_err(cap->rkisp1->dev, - "failed to register %s, ret=%d\n", vdev->name, ret); - return ret; - } - v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name, - vdev->num); - - ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); - if (ret) { - video_unregister_device(vdev); - return ret; - } - - return 0; -} - -static void -rkisp1_capture_init(struct rkisp1_device *rkisp1, enum rkisp1_stream_id id) -{ - struct rkisp1_capture *cap = &rkisp1->capture_devs[id]; - struct v4l2_pix_format_mplane pixm; - - memset(cap, 0, sizeof(*cap)); - cap->id = id; - cap->rkisp1 = rkisp1; - - INIT_LIST_HEAD(&cap->buf.queue); - init_waitqueue_head(&cap->done); - spin_lock_init(&cap->buf.lock); - if (cap->id == RKISP1_SELFPATH) { - cap->ops = &rkisp1_capture_ops_sp; - cap->config = &rkisp1_capture_config_sp; - } else { - cap->ops = &rkisp1_capture_ops_mp; - cap->config = &rkisp1_capture_config_mp; - } - - cap->is_streaming = false; - - memset(&pixm, 0, sizeof(pixm)); - pixm.pixelformat = V4L2_PIX_FMT_YUYV; - pixm.width = RKISP1_DEFAULT_WIDTH; - pixm.height = RKISP1_DEFAULT_HEIGHT; - rkisp1_set_fmt(cap, &pixm); -} - -int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1) -{ - struct rkisp1_capture *cap; - unsigned int i, j; - int ret; - - for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); i++) { - rkisp1_capture_init(rkisp1, i); - cap = &rkisp1->capture_devs[i]; - cap->rkisp1 = rkisp1; - ret = rkisp1_register_capture(cap); - if (ret) - goto err_unreg_capture_devs; - } - - return 0; - -err_unreg_capture_devs: - for (j = 0; j < i; j++) { - cap = &rkisp1->capture_devs[j]; - rkisp1_unregister_capture(cap); - } - - return ret; -} diff --git a/drivers/staging/media/rkisp1/rkisp1-common.c b/drivers/staging/media/rkisp1/rkisp1-common.c deleted file mode 100644 index cf889666e166..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-common.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - Common definitions - * - * Copyright (C) 2019 Collabora, Ltd. - */ - -#include - -#include "rkisp1-common.h" - -static const struct v4l2_rect rkisp1_sd_min_crop = { - .width = RKISP1_ISP_MIN_WIDTH, - .height = RKISP1_ISP_MIN_HEIGHT, - .top = 0, - .left = 0, -}; - -void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop, - const struct v4l2_rect *bounds) -{ - v4l2_rect_set_min_size(crop, &rkisp1_sd_min_crop); - v4l2_rect_map_inside(crop, bounds); -} - -void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, - const struct v4l2_mbus_framefmt *bounds) -{ - struct v4l2_rect crop_bounds = { - .left = 0, - .top = 0, - .width = bounds->width, - .height = bounds->height, - }; - - rkisp1_sd_adjust_crop_rect(crop, &crop_bounds); -} diff --git a/drivers/staging/media/rkisp1/rkisp1-common.h b/drivers/staging/media/rkisp1/rkisp1-common.h deleted file mode 100644 index 692333c66f9d..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-common.h +++ /dev/null @@ -1,485 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Rockchip ISP1 Driver - Common definitions - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#ifndef _RKISP1_COMMON_H -#define _RKISP1_COMMON_H - -#include -#include -#include -#include -#include -#include -#include - -#include "rkisp1-regs.h" -#include "uapi/rkisp1-config.h" - -/* - * flags on the 'direction' field in struct 'rkisp1_isp_mbus_info' that indicate - * on which pad the media bus format is supported - */ -#define RKISP1_ISP_SD_SRC BIT(0) -#define RKISP1_ISP_SD_SINK BIT(1) - -/* min and max values for the widths and heights of the entities */ -#define RKISP1_ISP_MAX_WIDTH 4032 -#define RKISP1_ISP_MAX_HEIGHT 3024 -#define RKISP1_ISP_MIN_WIDTH 32 -#define RKISP1_ISP_MIN_HEIGHT 32 - -#define RKISP1_RSZ_MP_SRC_MAX_WIDTH 4416 -#define RKISP1_RSZ_MP_SRC_MAX_HEIGHT 3312 -#define RKISP1_RSZ_SP_SRC_MAX_WIDTH 1920 -#define RKISP1_RSZ_SP_SRC_MAX_HEIGHT 1920 -#define RKISP1_RSZ_SRC_MIN_WIDTH 32 -#define RKISP1_RSZ_SRC_MIN_HEIGHT 16 - -/* the default width and height of all the entities */ -#define RKISP1_DEFAULT_WIDTH 800 -#define RKISP1_DEFAULT_HEIGHT 600 - -#define RKISP1_DRIVER_NAME "rkisp1" -#define RKISP1_BUS_INFO "platform:" RKISP1_DRIVER_NAME - -/* maximum number of clocks */ -#define RKISP1_MAX_BUS_CLK 8 - -/* a bitmask of the ready stats */ -#define RKISP1_STATS_MEAS_MASK (RKISP1_CIF_ISP_AWB_DONE | \ - RKISP1_CIF_ISP_AFM_FIN | \ - RKISP1_CIF_ISP_EXP_END | \ - RKISP1_CIF_ISP_HIST_MEASURE_RDY) - -/* enum for the resizer pads */ -enum rkisp1_rsz_pad { - RKISP1_RSZ_PAD_SINK, - RKISP1_RSZ_PAD_SRC, - RKISP1_RSZ_PAD_MAX -}; - -/* enum for the capture id */ -enum rkisp1_stream_id { - RKISP1_MAINPATH, - RKISP1_SELFPATH, -}; - -/* bayer patterns */ -enum rkisp1_fmt_raw_pat_type { - RKISP1_RAW_RGGB = 0, - RKISP1_RAW_GRBG, - RKISP1_RAW_GBRG, - RKISP1_RAW_BGGR, -}; - -/* enum for the isp pads */ -enum rkisp1_isp_pad { - RKISP1_ISP_PAD_SINK_VIDEO, - RKISP1_ISP_PAD_SINK_PARAMS, - RKISP1_ISP_PAD_SOURCE_VIDEO, - RKISP1_ISP_PAD_SOURCE_STATS, - RKISP1_ISP_PAD_MAX -}; - -/* - * struct rkisp1_sensor_async - A container for the v4l2_async_subdev to add to the notifier - * of the v4l2-async API - * - * @asd: async_subdev variable for the sensor - * @lanes: number of lanes - * @mbus_type: type of bus (currently only CSI2 is supported) - * @mbus_flags: media bus (V4L2_MBUS_*) flags - * @sd: a pointer to v4l2_subdev struct of the sensor - * @pixel_rate_ctrl: pixel rate of the sensor, used to initialize the phy - * @dphy: a pointer to the phy - */ -struct rkisp1_sensor_async { - struct v4l2_async_subdev asd; - unsigned int lanes; - enum v4l2_mbus_type mbus_type; - unsigned int mbus_flags; - struct v4l2_subdev *sd; - struct v4l2_ctrl *pixel_rate_ctrl; - struct phy *dphy; -}; - -/* - * struct rkisp1_isp - ISP subdev entity - * - * @sd: v4l2_subdev variable - * @rkisp1: pointer to rkisp1_device - * @pads: media pads - * @pad_cfg: pads configurations - * @sink_fmt: input format - * @src_fmt: output format - * @ops_lock: ops serialization - * @is_dphy_errctrl_disabled: if dphy errctrl is disabled (avoid endless interrupt) - * @frame_sequence: used to synchronize frame_id between video devices. - */ -struct rkisp1_isp { - struct v4l2_subdev sd; - struct media_pad pads[RKISP1_ISP_PAD_MAX]; - struct v4l2_subdev_pad_config pad_cfg[RKISP1_ISP_PAD_MAX]; - const struct rkisp1_isp_mbus_info *sink_fmt; - const struct rkisp1_isp_mbus_info *src_fmt; - struct mutex ops_lock; /* serialize the subdevice ops */ - bool is_dphy_errctrl_disabled; - __u32 frame_sequence; -}; - -/* - * struct rkisp1_vdev_node - Container for the video nodes: params, stats, mainpath, selfpath - * - * @buf_queue: queue of buffers - * @vlock: lock of the video node - * @vdev: video node - * @pad: media pad - */ -struct rkisp1_vdev_node { - struct vb2_queue buf_queue; - struct mutex vlock; /* ioctl serialization mutex */ - struct video_device vdev; - struct media_pad pad; -}; - -/* - * struct rkisp1_buffer - A container for the vb2 buffers used by the video devices: - * params, stats, mainpath, selfpath - * - * @vb: vb2 buffer - * @queue: entry of the buffer in the queue - * @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath - * @vaddr: virtual address for buffers used by params and stats devices - */ -struct rkisp1_buffer { - struct vb2_v4l2_buffer vb; - struct list_head queue; - union { - u32 buff_addr[VIDEO_MAX_PLANES]; - void *vaddr; - }; -}; - -/* - * struct rkisp1_dummy_buffer - A buffer to write the next frame to in case - * there are no vb2 buffers available. - * - * @vaddr: return value of call to dma_alloc_attrs. - * @dma_addr: dma address of the buffer. - * @size: size of the buffer. - */ -struct rkisp1_dummy_buffer { - void *vaddr; - dma_addr_t dma_addr; - u32 size; -}; - -struct rkisp1_device; - -/* - * struct rkisp1_capture - ISP capture video device - * - * @vnode: video node - * @rkisp1: pointer to rkisp1_device - * @id: id of the capture, one of RKISP1_SELFPATH, RKISP1_MAINPATH - * @ops: list of callbacks to configure the capture device. - * @config: a pointer to the list of registers to configure the capture format. - * @is_streaming: device is streaming - * @is_stopping: stop_streaming callback was called and the device is in the process of - * stopping the streaming. - * @done: when stop_streaming callback is called, the device waits for the next irq - * handler to stop the streaming by waiting on the 'done' wait queue. - * If the irq handler is not called, the stream is stopped by the callback - * after timeout. - * @sp_y_stride: the selfpath allows to configure a y stride that is longer than the image width. - * @buf.lock: lock to protect buf.queue - * @buf.queue: queued buffer list - * @buf.dummy: dummy space to store dropped data - * - * rkisp1 uses shadow registers, so it needs two buffers at a time - * @buf.curr: the buffer used for current frame - * @buf.next: the buffer used for next frame - * @pix.cfg: pixel configuration - * @pix.info: a pointer to the v4l2_format_info of the pixel format - * @pix.fmt: buffer format - */ -struct rkisp1_capture { - struct rkisp1_vdev_node vnode; - struct rkisp1_device *rkisp1; - enum rkisp1_stream_id id; - struct rkisp1_capture_ops *ops; - const struct rkisp1_capture_config *config; - bool is_streaming; - bool is_stopping; - wait_queue_head_t done; - unsigned int sp_y_stride; - struct { - /* protects queue, curr and next */ - spinlock_t lock; - struct list_head queue; - struct rkisp1_dummy_buffer dummy; - struct rkisp1_buffer *curr; - struct rkisp1_buffer *next; - } buf; - struct { - const struct rkisp1_capture_fmt_cfg *cfg; - const struct v4l2_format_info *info; - struct v4l2_pix_format_mplane fmt; - } pix; -}; - -/* - * struct rkisp1_stats - ISP Statistics device - * - * @vnode: video node - * @rkisp1: pointer to the rkisp1 device - * @lock: locks the buffer list 'stat' - * @stat: queue of rkisp1_buffer - * @vdev_fmt: v4l2_format of the metadata format - */ -struct rkisp1_stats { - struct rkisp1_vdev_node vnode; - struct rkisp1_device *rkisp1; - - spinlock_t lock; /* locks the buffers list 'stats' */ - struct list_head stat; - struct v4l2_format vdev_fmt; -}; - -/* - * struct rkisp1_params - ISP input parameters device - * - * @vnode: video node - * @rkisp1: pointer to the rkisp1 device - * @config_lock: locks the buffer list 'params' - * @params: queue of rkisp1_buffer - * @vdev_fmt: v4l2_format of the metadata format - * @quantization: the quantization configured on the isp's src pad - * @raw_type: the bayer pattern on the isp video sink pad - */ -struct rkisp1_params { - struct rkisp1_vdev_node vnode; - struct rkisp1_device *rkisp1; - - spinlock_t config_lock; /* locks the buffers list 'params' */ - struct list_head params; - struct v4l2_format vdev_fmt; - - enum v4l2_quantization quantization; - enum rkisp1_fmt_raw_pat_type raw_type; -}; - -/* - * struct rkisp1_resizer - Resizer subdev - * - * @sd: v4l2_subdev variable - * @id: id of the resizer, one of RKISP1_SELFPATH, RKISP1_MAINPATH - * @rkisp1: pointer to the rkisp1 device - * @pads: media pads - * @pad_cfg: configurations for the pads - * @config: the set of registers to configure the resizer - * @pixel_enc: pixel encoding of the resizer - * @ops_lock: a lock for the subdev ops - */ -struct rkisp1_resizer { - struct v4l2_subdev sd; - enum rkisp1_stream_id id; - struct rkisp1_device *rkisp1; - struct media_pad pads[RKISP1_RSZ_PAD_MAX]; - struct v4l2_subdev_pad_config pad_cfg[RKISP1_RSZ_PAD_MAX]; - const struct rkisp1_rsz_config *config; - enum v4l2_pixel_encoding pixel_enc; - struct mutex ops_lock; /* serialize the subdevice ops */ -}; - -/* - * struct rkisp1_debug - Values to be exposed on debugfs. - * The parameters are counters of the number of times the - * event occurred since the driver was loaded. - * - * @data_loss: loss of data occurred within a line, processing failure - * @outform_size_error: size error is generated in outmux submodule - * @img_stabilization_size_error: size error is generated in image stabilization submodule - * @inform_size_err: size error is generated in inform submodule - * @mipi_error: mipi error occurred - * @stats_error: writing to the 'Interrupt clear register' did not clear - * it in the register 'Masked interrupt status' - * @stop_timeout: upon stream stop, the capture waits 1 second for the isr to stop - * the stream. This param is incremented in case of timeout. - * @frame_drop: a frame was ready but the buffer queue was empty so the frame - * was not sent to userspace - */ -struct rkisp1_debug { - struct dentry *debugfs_dir; - unsigned long data_loss; - unsigned long outform_size_error; - unsigned long img_stabilization_size_error; - unsigned long inform_size_error; - unsigned long irq_delay; - unsigned long mipi_error; - unsigned long stats_error; - unsigned long stop_timeout[2]; - unsigned long frame_drop[2]; -}; - -/* - * struct rkisp1_device - ISP platform device - * - * @base_addr: base register address - * @irq: the irq number - * @dev: a pointer to the struct device - * @clk_size: number of clocks - * @clks: array of clocks - * @v4l2_dev: v4l2_device variable - * @media_dev: media_device variable - * @notifier: a notifier to register on the v4l2-async API to be notified on the sensor - * @active_sensor: sensor in-use, set when streaming on - * @isp: ISP sub-device - * @resizer_devs: resizer sub-devices - * @capture_devs: capture devices - * @stats: ISP statistics metadata capture device - * @params: ISP parameters metadata output device - * @pipe: media pipeline - * @stream_lock: serializes {start/stop}_streaming callbacks between the capture devices. - * @debug: debug params to be exposed on debugfs - */ -struct rkisp1_device { - void __iomem *base_addr; - int irq; - struct device *dev; - unsigned int clk_size; - struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK]; - struct v4l2_device v4l2_dev; - struct media_device media_dev; - struct v4l2_async_notifier notifier; - struct rkisp1_sensor_async *active_sensor; - struct rkisp1_isp isp; - struct rkisp1_resizer resizer_devs[2]; - struct rkisp1_capture capture_devs[2]; - struct rkisp1_stats stats; - struct rkisp1_params params; - struct media_pipeline pipe; - struct mutex stream_lock; /* serialize {start/stop}_streaming cb between capture devices */ - struct rkisp1_debug debug; -}; - -/* - * struct rkisp1_isp_mbus_info - ISP media bus info, Translates media bus code to hardware - * format values - * - * @mbus_code: media bus code - * @pixel_enc: pixel encoding - * @mipi_dt: mipi data type - * @yuv_seq: the order of the Y, Cb, Cr values - * @bus_width: bus width - * @bayer_pat: bayer pattern - * @direction: a bitmask of the flags indicating on which pad the format is supported on - */ -struct rkisp1_isp_mbus_info { - u32 mbus_code; - enum v4l2_pixel_encoding pixel_enc; - u32 mipi_dt; - u32 yuv_seq; - u8 bus_width; - enum rkisp1_fmt_raw_pat_type bayer_pat; - unsigned int direction; -}; - -static inline void -rkisp1_write(struct rkisp1_device *rkisp1, u32 val, unsigned int addr) -{ - writel(val, rkisp1->base_addr + addr); -} - -static inline u32 rkisp1_read(struct rkisp1_device *rkisp1, unsigned int addr) -{ - return readl(rkisp1->base_addr + addr); -} - -/* - * rkisp1_cap_enum_mbus_codes - A helper function that return the i'th supported mbus code - * of the capture entity. This is used to enumerate the supported - * mbus codes on the source pad of the resizer. - * - * @cap: the capture entity - * @code: the mbus code, the function reads the code->index and fills the code->code - */ -int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, - struct v4l2_subdev_mbus_code_enum *code); - -/* - * rkisp1_sd_adjust_crop_rect - adjust a rectangle to fit into another rectangle. - * - * @crop: rectangle to adjust. - * @bounds: rectangle used as bounds. - */ -void rkisp1_sd_adjust_crop_rect(struct v4l2_rect *crop, - const struct v4l2_rect *bounds); - -/* - * rkisp1_sd_adjust_crop - adjust a rectangle to fit into media bus format - * - * @crop: rectangle to adjust. - * @bounds: media bus format used as bounds. - */ -void rkisp1_sd_adjust_crop(struct v4l2_rect *crop, - const struct v4l2_mbus_framefmt *bounds); - -/* - * rkisp1_isp_mbus_info - get the isp info of the media bus code - * - * @mbus_code: the media bus code - */ -const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code); - -/* rkisp1_params_configure - configure the params when stream starts. - * This function is called by the isp entity upon stream starts. - * The function applies the initial configuration of the parameters. - * - * @params: pointer to rkisp1_params. - * @bayer_pat: the bayer pattern on the isp video sink pad - * @quantization: the quantization configured on the isp's src pad - */ -void rkisp1_params_configure(struct rkisp1_params *params, - enum rkisp1_fmt_raw_pat_type bayer_pat, - enum v4l2_quantization quantization); - -/* rkisp1_params_disable - disable all parameters. - * This function is called by the isp entity upon stream start - * when capturing bayer format. - * - * @params: pointer to rkisp1_params. - */ -void rkisp1_params_disable(struct rkisp1_params *params); - -/* irq handlers */ -void rkisp1_isp_isr(struct rkisp1_device *rkisp1); -void rkisp1_mipi_isr(struct rkisp1_device *rkisp1); -void rkisp1_capture_isr(struct rkisp1_device *rkisp1); -void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris); -void rkisp1_params_isr(struct rkisp1_device *rkisp1); - -/* register/unregisters functions of the entities */ -int rkisp1_capture_devs_register(struct rkisp1_device *rkisp1); -void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1); - -int rkisp1_isp_register(struct rkisp1_device *rkisp1); -void rkisp1_isp_unregister(struct rkisp1_device *rkisp1); - -int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1); -void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1); - -int rkisp1_stats_register(struct rkisp1_device *rkisp1); -void rkisp1_stats_unregister(struct rkisp1_device *rkisp1); - -int rkisp1_params_register(struct rkisp1_device *rkisp1); -void rkisp1_params_unregister(struct rkisp1_device *rkisp1); - -#endif /* _RKISP1_COMMON_H */ diff --git a/drivers/staging/media/rkisp1/rkisp1-dev.c b/drivers/staging/media/rkisp1/rkisp1-dev.c deleted file mode 100644 index 90d654346556..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-dev.c +++ /dev/null @@ -1,580 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - Base driver - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rkisp1-common.h" - -/* - * ISP Details - * ----------- - * - * ISP Comprises with: - * MIPI serial camera interface - * Image Signal Processing - * Many Image Enhancement Blocks - * Crop - * Resizer - * RBG display ready image - * Image Rotation - * - * ISP Block Diagram - * ----------------- - * rkisp1-resizer.c rkisp1-capture.c - * |====================| |=======================| - * rkisp1-isp.c Main Picture Path - * |==========================| |===============================================| - * +-----------+ +--+--+--+--+ +--------+ +--------+ +-----------+ - * | | | | | | | | | | | | | - * +--------+ |\ | | | | | | | -->| Crop |->| RSZ |------------->| | - * | MIPI |--->| \ | | | | | | | | | | | | | | - * +--------+ | | | | |IE|IE|IE|IE| | +--------+ +--------+ | Memory | - * |MUX|--->| ISP |->|0 |1 |2 |3 |---+ | Interface | - * +--------+ | | | | | | | | | | +--------+ +--------+ +--------+ | | - * |Parallel|--->| / | | | | | | | | | | | | | | | | - * +--------+ |/ | | | | | | | -->| Crop |->| RSZ |->| RGB |->| | - * | | | | | | | | | | | | Rotate | | | - * +-----------+ +--+--+--+--+ +--------+ +--------+ +--------+ +-----------+ - * ^ - * +--------+ | |===============================================| - * | DMA |------------------------------------+ Self Picture Path - * +--------+ - * - * rkisp1-stats.c rkisp1-params.c - * |===============| |===============| - * +---------------+ +---------------+ - * | | | | - * | ISP | | ISP | - * | | | | - * +---------------+ +---------------+ - * - * - * Media Topology - * -------------- - * +----------+ +----------+ - * | Sensor 2 | | Sensor X | - * ------------ ... ------------ - * | 0 | | 0 | - * +----------+ +----------+ +-----------+ - * \ | | params | - * \ | | (output) | - * +----------+ \ | +-----------+ - * | Sensor 1 | v v | - * ------------ +------+------+ | - * | 0 |----->| 0 | 1 |<---------+ - * +----------+ |------+------| - * | ISP | - * |------+------| - * +-------------| 2 | 3 |----------+ - * | +------+------+ | - * | | | - * v v v - * +- ---------+ +-----------+ +-----------+ - * | 0 | | 0 | | stats | - * ------------- ------------- | (capture) | - * | Resizer | | Resizer | +-----------+ - * ------------| ------------| - * | 1 | | 1 | - * +-----------+ +-----------+ - * | | - * v v - * +-----------+ +-----------+ - * | selfpath | | mainpath | - * | (capture) | | (capture) | - * +-----------+ +-----------+ - */ - -struct rkisp1_match_data { - const char * const *clks; - unsigned int size; -}; - -/* ---------------------------------------------------------------------------- - * Sensor DT bindings - */ - -static int rkisp1_create_links(struct rkisp1_device *rkisp1) -{ - struct media_entity *source, *sink; - unsigned int flags, source_pad; - struct v4l2_subdev *sd; - unsigned int i; - int ret; - - /* sensor links */ - flags = MEDIA_LNK_FL_ENABLED; - list_for_each_entry(sd, &rkisp1->v4l2_dev.subdevs, list) { - if (sd == &rkisp1->isp.sd || - sd == &rkisp1->resizer_devs[RKISP1_MAINPATH].sd || - sd == &rkisp1->resizer_devs[RKISP1_SELFPATH].sd) - continue; - - ret = media_entity_get_fwnode_pad(&sd->entity, sd->fwnode, - MEDIA_PAD_FL_SOURCE); - if (ret < 0) { - dev_err(rkisp1->dev, "failed to find src pad for %s\n", - sd->name); - return ret; - } - source_pad = ret; - - ret = media_create_pad_link(&sd->entity, source_pad, - &rkisp1->isp.sd.entity, - RKISP1_ISP_PAD_SINK_VIDEO, - flags); - if (ret) - return ret; - - flags = 0; - } - - flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; - - /* create ISP->RSZ->CAP links */ - for (i = 0; i < 2; i++) { - source = &rkisp1->isp.sd.entity; - sink = &rkisp1->resizer_devs[i].sd.entity; - ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_VIDEO, - sink, RKISP1_RSZ_PAD_SINK, - MEDIA_LNK_FL_ENABLED); - if (ret) - return ret; - - source = sink; - sink = &rkisp1->capture_devs[i].vnode.vdev.entity; - ret = media_create_pad_link(source, RKISP1_RSZ_PAD_SRC, - sink, 0, flags); - if (ret) - return ret; - } - - /* params links */ - source = &rkisp1->params.vnode.vdev.entity; - sink = &rkisp1->isp.sd.entity; - ret = media_create_pad_link(source, 0, sink, - RKISP1_ISP_PAD_SINK_PARAMS, flags); - if (ret) - return ret; - - /* 3A stats links */ - source = &rkisp1->isp.sd.entity; - sink = &rkisp1->stats.vnode.vdev.entity; - return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS, - sink, 0, flags); -} - -static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) -{ - struct rkisp1_device *rkisp1 = - container_of(notifier, struct rkisp1_device, notifier); - struct rkisp1_sensor_async *s_asd = - container_of(asd, struct rkisp1_sensor_async, asd); - - s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, - V4L2_CID_PIXEL_RATE); - s_asd->sd = sd; - s_asd->dphy = devm_phy_get(rkisp1->dev, "dphy"); - if (IS_ERR(s_asd->dphy)) { - if (PTR_ERR(s_asd->dphy) != -EPROBE_DEFER) - dev_err(rkisp1->dev, "Couldn't get the MIPI D-PHY\n"); - return PTR_ERR(s_asd->dphy); - } - - phy_init(s_asd->dphy); - - return 0; -} - -static void rkisp1_subdev_notifier_unbind(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) -{ - struct rkisp1_sensor_async *s_asd = - container_of(asd, struct rkisp1_sensor_async, asd); - - phy_exit(s_asd->dphy); -} - -static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier) -{ - struct rkisp1_device *rkisp1 = - container_of(notifier, struct rkisp1_device, notifier); - int ret; - - ret = rkisp1_create_links(rkisp1); - if (ret) - return ret; - - ret = v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev); - if (ret) - return ret; - - dev_dbg(rkisp1->dev, "Async subdev notifier completed\n"); - - return 0; -} - -static const struct v4l2_async_notifier_operations rkisp1_subdev_notifier_ops = { - .bound = rkisp1_subdev_notifier_bound, - .unbind = rkisp1_subdev_notifier_unbind, - .complete = rkisp1_subdev_notifier_complete, -}; - -static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) -{ - struct v4l2_async_notifier *ntf = &rkisp1->notifier; - unsigned int next_id = 0; - int ret; - - v4l2_async_notifier_init(ntf); - - while (1) { - struct v4l2_fwnode_endpoint vep = { - .bus_type = V4L2_MBUS_CSI2_DPHY - }; - struct rkisp1_sensor_async *rk_asd = NULL; - struct fwnode_handle *ep; - - ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev), - 0, next_id, FWNODE_GRAPH_ENDPOINT_NEXT); - if (!ep) - break; - - ret = v4l2_fwnode_endpoint_parse(ep, &vep); - if (ret) - goto err_parse; - - rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL); - if (!rk_asd) { - ret = -ENOMEM; - goto err_parse; - } - - rk_asd->mbus_type = vep.bus_type; - rk_asd->mbus_flags = vep.bus.mipi_csi2.flags; - rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes; - - ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep, - &rk_asd->asd); - if (ret) - goto err_parse; - - dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n", - vep.base.id, rk_asd->lanes); - - next_id = vep.base.id + 1; - - fwnode_handle_put(ep); - - continue; -err_parse: - fwnode_handle_put(ep); - kfree(rk_asd); - v4l2_async_notifier_cleanup(ntf); - return ret; - } - - if (next_id == 0) - dev_dbg(rkisp1->dev, "no remote subdevice found\n"); - ntf->ops = &rkisp1_subdev_notifier_ops; - ret = v4l2_async_notifier_register(&rkisp1->v4l2_dev, ntf); - if (ret) { - v4l2_async_notifier_cleanup(ntf); - return ret; - } - return 0; -} - -/* ---------------------------------------------------------------------------- - * Power - */ - -static int __maybe_unused rkisp1_runtime_suspend(struct device *dev) -{ - struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); - - clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks); - return pinctrl_pm_select_sleep_state(dev); -} - -static int __maybe_unused rkisp1_runtime_resume(struct device *dev) -{ - struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); - int ret; - - ret = pinctrl_pm_select_default_state(dev); - if (ret) - return ret; - ret = clk_bulk_prepare_enable(rkisp1->clk_size, rkisp1->clks); - if (ret) - return ret; - - return 0; -} - -static const struct dev_pm_ops rkisp1_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL) -}; - -/* ---------------------------------------------------------------------------- - * Core - */ - -static int rkisp1_entities_register(struct rkisp1_device *rkisp1) -{ - int ret; - - ret = rkisp1_isp_register(rkisp1); - if (ret) - return ret; - - ret = rkisp1_resizer_devs_register(rkisp1); - if (ret) - goto err_unreg_isp_subdev; - - ret = rkisp1_capture_devs_register(rkisp1); - if (ret) - goto err_unreg_resizer_devs; - - ret = rkisp1_stats_register(rkisp1); - if (ret) - goto err_unreg_capture_devs; - - ret = rkisp1_params_register(rkisp1); - if (ret) - goto err_unreg_stats; - - ret = rkisp1_subdev_notifier(rkisp1); - if (ret) { - dev_err(rkisp1->dev, - "Failed to register subdev notifier(%d)\n", ret); - goto err_unreg_params; - } - - return 0; -err_unreg_params: - rkisp1_params_unregister(rkisp1); -err_unreg_stats: - rkisp1_stats_unregister(rkisp1); -err_unreg_capture_devs: - rkisp1_capture_devs_unregister(rkisp1); -err_unreg_resizer_devs: - rkisp1_resizer_devs_unregister(rkisp1); -err_unreg_isp_subdev: - rkisp1_isp_unregister(rkisp1); - return ret; -} - -static irqreturn_t rkisp1_isr(int irq, void *ctx) -{ - struct device *dev = ctx; - struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); - - /* - * Call rkisp1_capture_isr() first to handle the frame that - * potentially completed using the current frame_sequence number before - * it is potentially incremented by rkisp1_isp_isr() in the vertical - * sync. - */ - rkisp1_capture_isr(rkisp1); - rkisp1_isp_isr(rkisp1); - rkisp1_mipi_isr(rkisp1); - - return IRQ_HANDLED; -} - -static const char * const rk3399_isp_clks[] = { - "isp", - "aclk", - "hclk", -}; - -static const struct rkisp1_match_data rk3399_isp_clk_data = { - .clks = rk3399_isp_clks, - .size = ARRAY_SIZE(rk3399_isp_clks), -}; - -static const struct of_device_id rkisp1_of_match[] = { - { - .compatible = "rockchip,rk3399-cif-isp", - .data = &rk3399_isp_clk_data, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, rkisp1_of_match); - -static void rkisp1_debug_init(struct rkisp1_device *rkisp1) -{ - struct rkisp1_debug *debug = &rkisp1->debug; - - debug->debugfs_dir = debugfs_create_dir(RKISP1_DRIVER_NAME, NULL); - if (!debug->debugfs_dir) { - dev_dbg(rkisp1->dev, "failed to create debugfs directory\n"); - return; - } - debugfs_create_ulong("data_loss", 0444, debug->debugfs_dir, - &debug->data_loss); - debugfs_create_ulong("outform_size_err", 0444, debug->debugfs_dir, - &debug->outform_size_error); - debugfs_create_ulong("img_stabilization_size_error", 0444, - debug->debugfs_dir, - &debug->img_stabilization_size_error); - debugfs_create_ulong("inform_size_error", 0444, debug->debugfs_dir, - &debug->inform_size_error); - debugfs_create_ulong("irq_delay", 0444, debug->debugfs_dir, - &debug->irq_delay); - debugfs_create_ulong("mipi_error", 0444, debug->debugfs_dir, - &debug->mipi_error); - debugfs_create_ulong("stats_error", 0444, debug->debugfs_dir, - &debug->stats_error); - debugfs_create_ulong("mp_stop_timeout", 0444, debug->debugfs_dir, - &debug->stop_timeout[RKISP1_MAINPATH]); - debugfs_create_ulong("sp_stop_timeout", 0444, debug->debugfs_dir, - &debug->stop_timeout[RKISP1_SELFPATH]); - debugfs_create_ulong("mp_frame_drop", 0444, debug->debugfs_dir, - &debug->frame_drop[RKISP1_MAINPATH]); - debugfs_create_ulong("sp_frame_drop", 0444, debug->debugfs_dir, - &debug->frame_drop[RKISP1_SELFPATH]); -} - -static int rkisp1_probe(struct platform_device *pdev) -{ - const struct rkisp1_match_data *clk_data; - struct device *dev = &pdev->dev; - struct rkisp1_device *rkisp1; - struct v4l2_device *v4l2_dev; - unsigned int i; - int ret, irq; - - clk_data = of_device_get_match_data(&pdev->dev); - if (!clk_data) - return -ENODEV; - - rkisp1 = devm_kzalloc(dev, sizeof(*rkisp1), GFP_KERNEL); - if (!rkisp1) - return -ENOMEM; - - dev_set_drvdata(dev, rkisp1); - rkisp1->dev = dev; - - mutex_init(&rkisp1->stream_lock); - - rkisp1->base_addr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(rkisp1->base_addr)) - return PTR_ERR(rkisp1->base_addr); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - ret = devm_request_irq(dev, irq, rkisp1_isr, IRQF_SHARED, - dev_driver_string(dev), dev); - if (ret) { - dev_err(dev, "request irq failed: %d\n", ret); - return ret; - } - - rkisp1->irq = irq; - - for (i = 0; i < clk_data->size; i++) - rkisp1->clks[i].id = clk_data->clks[i]; - ret = devm_clk_bulk_get(dev, clk_data->size, rkisp1->clks); - if (ret) - return ret; - rkisp1->clk_size = clk_data->size; - - pm_runtime_enable(&pdev->dev); - - strscpy(rkisp1->media_dev.model, RKISP1_DRIVER_NAME, - sizeof(rkisp1->media_dev.model)); - rkisp1->media_dev.dev = &pdev->dev; - strscpy(rkisp1->media_dev.bus_info, RKISP1_BUS_INFO, - sizeof(rkisp1->media_dev.bus_info)); - media_device_init(&rkisp1->media_dev); - - v4l2_dev = &rkisp1->v4l2_dev; - v4l2_dev->mdev = &rkisp1->media_dev; - strscpy(v4l2_dev->name, RKISP1_DRIVER_NAME, sizeof(v4l2_dev->name)); - - ret = v4l2_device_register(rkisp1->dev, &rkisp1->v4l2_dev); - if (ret) - return ret; - - ret = media_device_register(&rkisp1->media_dev); - if (ret) { - dev_err(dev, "Failed to register media device: %d\n", ret); - goto err_unreg_v4l2_dev; - } - - ret = rkisp1_entities_register(rkisp1); - if (ret) - goto err_unreg_media_dev; - - rkisp1_debug_init(rkisp1); - - return 0; - -err_unreg_media_dev: - media_device_unregister(&rkisp1->media_dev); -err_unreg_v4l2_dev: - v4l2_device_unregister(&rkisp1->v4l2_dev); - pm_runtime_disable(&pdev->dev); - return ret; -} - -static int rkisp1_remove(struct platform_device *pdev) -{ - struct rkisp1_device *rkisp1 = platform_get_drvdata(pdev); - - v4l2_async_notifier_unregister(&rkisp1->notifier); - v4l2_async_notifier_cleanup(&rkisp1->notifier); - - rkisp1_params_unregister(rkisp1); - rkisp1_stats_unregister(rkisp1); - rkisp1_capture_devs_unregister(rkisp1); - rkisp1_resizer_devs_unregister(rkisp1); - rkisp1_isp_unregister(rkisp1); - - media_device_unregister(&rkisp1->media_dev); - v4l2_device_unregister(&rkisp1->v4l2_dev); - - pm_runtime_disable(&pdev->dev); - - debugfs_remove_recursive(rkisp1->debug.debugfs_dir); - return 0; -} - -static struct platform_driver rkisp1_drv = { - .driver = { - .name = RKISP1_DRIVER_NAME, - .of_match_table = of_match_ptr(rkisp1_of_match), - .pm = &rkisp1_pm_ops, - }, - .probe = rkisp1_probe, - .remove = rkisp1_remove, -}; - -module_platform_driver(rkisp1_drv); -MODULE_DESCRIPTION("Rockchip ISP1 platform driver"); -MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/staging/media/rkisp1/rkisp1-isp.c b/drivers/staging/media/rkisp1/rkisp1-isp.c deleted file mode 100644 index 48d08ff87da2..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-isp.c +++ /dev/null @@ -1,1161 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - ISP Subdevice - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rkisp1-common.h" - -#define RKISP1_DEF_SINK_PAD_FMT MEDIA_BUS_FMT_SRGGB10_1X10 -#define RKISP1_DEF_SRC_PAD_FMT MEDIA_BUS_FMT_YUYV8_2X8 - -#define RKISP1_ISP_DEV_NAME RKISP1_DRIVER_NAME "_isp" - -/* - * NOTE: MIPI controller and input MUX are also configured in this file. - * This is because ISP Subdev describes not only ISP submodule (input size, - * format, output size, format), but also a virtual route device. - */ - -/* - * There are many variables named with format/frame in below code, - * please see here for their meaning. - * Cropping in the sink pad defines the image region from the sensor. - * Cropping in the source pad defines the region for the Image Stabilizer (IS) - * - * Cropping regions of ISP - * - * +---------------------------------------------------------+ - * | Sensor image | - * | +---------------------------------------------------+ | - * | | CIF_ISP_ACQ (for black level) | | - * | | sink pad format | | - * | | +--------------------------------------------+ | | - * | | | CIF_ISP_OUT | | | - * | | | sink pad crop | | | - * | | | +---------------------------------+ | | | - * | | | | CIF_ISP_IS | | | | - * | | | | source pad crop and format | | | | - * | | | +---------------------------------+ | | | - * | | +--------------------------------------------+ | | - * | +---------------------------------------------------+ | - * +---------------------------------------------------------+ - */ - -static const struct rkisp1_isp_mbus_info rkisp1_isp_formats[] = { - { - .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, - .pixel_enc = V4L2_PIXEL_ENC_YUV, - .direction = RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, - .bayer_pat = RKISP1_RAW_RGGB, - .bus_width = 10, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, - .bayer_pat = RKISP1_RAW_BGGR, - .bus_width = 10, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, - .bayer_pat = RKISP1_RAW_GBRG, - .bus_width = 10, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW10, - .bayer_pat = RKISP1_RAW_GRBG, - .bus_width = 10, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, - .bayer_pat = RKISP1_RAW_RGGB, - .bus_width = 12, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, - .bayer_pat = RKISP1_RAW_BGGR, - .bus_width = 12, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, - .bayer_pat = RKISP1_RAW_GBRG, - .bus_width = 12, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW12, - .bayer_pat = RKISP1_RAW_GRBG, - .bus_width = 12, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, - .bayer_pat = RKISP1_RAW_RGGB, - .bus_width = 8, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, - .bayer_pat = RKISP1_RAW_BGGR, - .bus_width = 8, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, - .bayer_pat = RKISP1_RAW_GBRG, - .bus_width = 8, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, - .pixel_enc = V4L2_PIXEL_ENC_BAYER, - .mipi_dt = RKISP1_CIF_CSI2_DT_RAW8, - .bayer_pat = RKISP1_RAW_GRBG, - .bus_width = 8, - .direction = RKISP1_ISP_SD_SINK | RKISP1_ISP_SD_SRC, - }, { - .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, - .pixel_enc = V4L2_PIXEL_ENC_YUV, - .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, - .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_YCBYCR, - .bus_width = 16, - .direction = RKISP1_ISP_SD_SINK, - }, { - .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, - .pixel_enc = V4L2_PIXEL_ENC_YUV, - .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, - .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_YCRYCB, - .bus_width = 16, - .direction = RKISP1_ISP_SD_SINK, - }, { - .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, - .pixel_enc = V4L2_PIXEL_ENC_YUV, - .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, - .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_CBYCRY, - .bus_width = 16, - .direction = RKISP1_ISP_SD_SINK, - }, { - .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, - .pixel_enc = V4L2_PIXEL_ENC_YUV, - .mipi_dt = RKISP1_CIF_CSI2_DT_YUV422_8b, - .yuv_seq = RKISP1_CIF_ISP_ACQ_PROP_CRYCBY, - .bus_width = 16, - .direction = RKISP1_ISP_SD_SINK, - }, -}; - -/* ---------------------------------------------------------------------------- - * Helpers - */ - -const struct rkisp1_isp_mbus_info *rkisp1_isp_mbus_info_get(u32 mbus_code) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rkisp1_isp_formats); i++) { - const struct rkisp1_isp_mbus_info *fmt = &rkisp1_isp_formats[i]; - - if (fmt->mbus_code == mbus_code) - return fmt; - } - - return NULL; -} - -static struct v4l2_subdev *rkisp1_get_remote_sensor(struct v4l2_subdev *sd) -{ - struct media_pad *local, *remote; - struct media_entity *sensor_me; - - local = &sd->entity.pads[RKISP1_ISP_PAD_SINK_VIDEO]; - remote = media_entity_remote_pad(local); - if (!remote) - return NULL; - - sensor_me = remote->entity; - return media_entity_to_v4l2_subdev(sensor_me); -} - -static struct v4l2_mbus_framefmt * -rkisp1_isp_get_pad_fmt(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&isp->sd, cfg, pad); - else - return v4l2_subdev_get_try_format(&isp->sd, isp->pad_cfg, pad); -} - -static struct v4l2_rect * -rkisp1_isp_get_pad_crop(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_crop(&isp->sd, cfg, pad); - else - return v4l2_subdev_get_try_crop(&isp->sd, isp->pad_cfg, pad); -} - -/* ---------------------------------------------------------------------------- - * Camera Interface registers configurations - */ - -/* - * Image Stabilization. - * This should only be called when configuring CIF - * or at the frame end interrupt - */ -static void rkisp1_config_ism(struct rkisp1_device *rkisp1) -{ - struct v4l2_rect *src_crop = - rkisp1_isp_get_pad_crop(&rkisp1->isp, NULL, - RKISP1_ISP_PAD_SOURCE_VIDEO, - V4L2_SUBDEV_FORMAT_ACTIVE); - u32 val; - - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_RECENTER); - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_MAX_DX); - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_MAX_DY); - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IS_DISPLACE); - rkisp1_write(rkisp1, src_crop->left, RKISP1_CIF_ISP_IS_H_OFFS); - rkisp1_write(rkisp1, src_crop->top, RKISP1_CIF_ISP_IS_V_OFFS); - rkisp1_write(rkisp1, src_crop->width, RKISP1_CIF_ISP_IS_H_SIZE); - rkisp1_write(rkisp1, src_crop->height, RKISP1_CIF_ISP_IS_V_SIZE); - - /* IS(Image Stabilization) is always on, working as output crop */ - rkisp1_write(rkisp1, 1, RKISP1_CIF_ISP_IS_CTRL); - val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); - val |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD; - rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); -} - -/* - * configure ISP blocks with input format, size...... - */ -static int rkisp1_config_isp(struct rkisp1_device *rkisp1) -{ - u32 isp_ctrl = 0, irq_mask = 0, acq_mult = 0, signal = 0; - const struct rkisp1_isp_mbus_info *src_fmt, *sink_fmt; - struct rkisp1_sensor_async *sensor; - struct v4l2_mbus_framefmt *sink_frm; - struct v4l2_rect *sink_crop; - - sensor = rkisp1->active_sensor; - sink_fmt = rkisp1->isp.sink_fmt; - src_fmt = rkisp1->isp.src_fmt; - sink_frm = rkisp1_isp_get_pad_fmt(&rkisp1->isp, NULL, - RKISP1_ISP_PAD_SINK_VIDEO, - V4L2_SUBDEV_FORMAT_ACTIVE); - sink_crop = rkisp1_isp_get_pad_crop(&rkisp1->isp, NULL, - RKISP1_ISP_PAD_SINK_VIDEO, - V4L2_SUBDEV_FORMAT_ACTIVE); - - if (sink_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { - acq_mult = 1; - if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { - if (sensor->mbus_type == V4L2_MBUS_BT656) - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656; - else - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT; - } else { - rkisp1_write(rkisp1, RKISP1_CIF_ISP_DEMOSAIC_TH(0xc), - RKISP1_CIF_ISP_DEMOSAIC); - - if (sensor->mbus_type == V4L2_MBUS_BT656) - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656; - else - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601; - } - } else if (sink_fmt->pixel_enc == V4L2_PIXEL_ENC_YUV) { - acq_mult = 2; - if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601; - } else { - if (sensor->mbus_type == V4L2_MBUS_BT656) - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU656; - else - isp_ctrl = RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601; - } - - irq_mask |= RKISP1_CIF_ISP_DATA_LOSS; - } - - /* Set up input acquisition properties */ - if (sensor->mbus_type == V4L2_MBUS_BT656 || - sensor->mbus_type == V4L2_MBUS_PARALLEL) { - if (sensor->mbus_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) - signal = RKISP1_CIF_ISP_ACQ_PROP_POS_EDGE; - } - - if (sensor->mbus_type == V4L2_MBUS_PARALLEL) { - if (sensor->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - signal |= RKISP1_CIF_ISP_ACQ_PROP_VSYNC_LOW; - - if (sensor->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - signal |= RKISP1_CIF_ISP_ACQ_PROP_HSYNC_LOW; - } - - rkisp1_write(rkisp1, isp_ctrl, RKISP1_CIF_ISP_CTRL); - rkisp1_write(rkisp1, signal | sink_fmt->yuv_seq | - RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT(sink_fmt->bayer_pat) | - RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ALL, - RKISP1_CIF_ISP_ACQ_PROP); - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_NR_FRAMES); - - /* Acquisition Size */ - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_H_OFFS); - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_ACQ_V_OFFS); - rkisp1_write(rkisp1, - acq_mult * sink_frm->width, RKISP1_CIF_ISP_ACQ_H_SIZE); - rkisp1_write(rkisp1, sink_frm->height, RKISP1_CIF_ISP_ACQ_V_SIZE); - - /* ISP Out Area */ - rkisp1_write(rkisp1, sink_crop->left, RKISP1_CIF_ISP_OUT_H_OFFS); - rkisp1_write(rkisp1, sink_crop->top, RKISP1_CIF_ISP_OUT_V_OFFS); - rkisp1_write(rkisp1, sink_crop->width, RKISP1_CIF_ISP_OUT_H_SIZE); - rkisp1_write(rkisp1, sink_crop->height, RKISP1_CIF_ISP_OUT_V_SIZE); - - irq_mask |= RKISP1_CIF_ISP_FRAME | RKISP1_CIF_ISP_V_START | - RKISP1_CIF_ISP_PIC_SIZE_ERROR; - rkisp1_write(rkisp1, irq_mask, RKISP1_CIF_ISP_IMSC); - - if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { - rkisp1_params_disable(&rkisp1->params); - } else { - struct v4l2_mbus_framefmt *src_frm; - - src_frm = rkisp1_isp_get_pad_fmt(&rkisp1->isp, NULL, - RKISP1_ISP_PAD_SINK_VIDEO, - V4L2_SUBDEV_FORMAT_ACTIVE); - rkisp1_params_configure(&rkisp1->params, sink_fmt->bayer_pat, - src_frm->quantization); - } - - return 0; -} - -static int rkisp1_config_dvp(struct rkisp1_device *rkisp1) -{ - const struct rkisp1_isp_mbus_info *sink_fmt = rkisp1->isp.sink_fmt; - u32 val, input_sel; - - switch (sink_fmt->bus_width) { - case 8: - input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO; - break; - case 10: - input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO; - break; - case 12: - input_sel = RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_12B; - break; - default: - dev_err(rkisp1->dev, "Invalid bus width\n"); - return -EINVAL; - } - - val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ACQ_PROP); - rkisp1_write(rkisp1, val | input_sel, RKISP1_CIF_ISP_ACQ_PROP); - - return 0; -} - -static int rkisp1_config_mipi(struct rkisp1_device *rkisp1) -{ - const struct rkisp1_isp_mbus_info *sink_fmt = rkisp1->isp.sink_fmt; - unsigned int lanes = rkisp1->active_sensor->lanes; - u32 mipi_ctrl; - - if (lanes < 1 || lanes > 4) - return -EINVAL; - - mipi_ctrl = RKISP1_CIF_MIPI_CTRL_NUM_LANES(lanes - 1) | - RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) | - RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP | - RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA; - - rkisp1_write(rkisp1, mipi_ctrl, RKISP1_CIF_MIPI_CTRL); - - /* Configure Data Type and Virtual Channel */ - rkisp1_write(rkisp1, - RKISP1_CIF_MIPI_DATA_SEL_DT(sink_fmt->mipi_dt) | - RKISP1_CIF_MIPI_DATA_SEL_VC(0), - RKISP1_CIF_MIPI_IMG_DATA_SEL); - - /* Clear MIPI interrupts */ - rkisp1_write(rkisp1, ~0, RKISP1_CIF_MIPI_ICR); - /* - * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for - * isp bus may be dead when switch isp. - */ - rkisp1_write(rkisp1, - RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI | - RKISP1_CIF_MIPI_ERR_DPHY | - RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | - RKISP1_CIF_MIPI_ADD_DATA_OVFLW, - RKISP1_CIF_MIPI_IMSC); - - dev_dbg(rkisp1->dev, "\n MIPI_CTRL 0x%08x\n" - " MIPI_IMG_DATA_SEL 0x%08x\n" - " MIPI_STATUS 0x%08x\n" - " MIPI_IMSC 0x%08x\n", - rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL), - rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL), - rkisp1_read(rkisp1, RKISP1_CIF_MIPI_STATUS), - rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC)); - - return 0; -} - -/* Configure MUX */ -static int rkisp1_config_path(struct rkisp1_device *rkisp1) -{ - struct rkisp1_sensor_async *sensor = rkisp1->active_sensor; - u32 dpcl = rkisp1_read(rkisp1, RKISP1_CIF_VI_DPCL); - int ret = 0; - - if (sensor->mbus_type == V4L2_MBUS_BT656 || - sensor->mbus_type == V4L2_MBUS_PARALLEL) { - ret = rkisp1_config_dvp(rkisp1); - dpcl |= RKISP1_CIF_VI_DPCL_IF_SEL_PARALLEL; - } else if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { - ret = rkisp1_config_mipi(rkisp1); - dpcl |= RKISP1_CIF_VI_DPCL_IF_SEL_MIPI; - } - - rkisp1_write(rkisp1, dpcl, RKISP1_CIF_VI_DPCL); - - return ret; -} - -/* Hardware configure Entry */ -static int rkisp1_config_cif(struct rkisp1_device *rkisp1) -{ - u32 cif_id; - int ret; - - cif_id = rkisp1_read(rkisp1, RKISP1_CIF_VI_ID); - dev_dbg(rkisp1->dev, "CIF_ID 0x%08x\n", cif_id); - - ret = rkisp1_config_isp(rkisp1); - if (ret) - return ret; - ret = rkisp1_config_path(rkisp1); - if (ret) - return ret; - rkisp1_config_ism(rkisp1); - - return 0; -} - -static void rkisp1_isp_stop(struct rkisp1_device *rkisp1) -{ - u32 val; - - /* - * ISP(mi) stop in mi frame end -> Stop ISP(mipi) -> - * Stop ISP(isp) ->wait for ISP isp off - */ - /* stop and clear MI, MIPI, and ISP interrupts */ - rkisp1_write(rkisp1, 0, RKISP1_CIF_MIPI_IMSC); - rkisp1_write(rkisp1, ~0, RKISP1_CIF_MIPI_ICR); - - rkisp1_write(rkisp1, 0, RKISP1_CIF_ISP_IMSC); - rkisp1_write(rkisp1, ~0, RKISP1_CIF_ISP_ICR); - - rkisp1_write(rkisp1, 0, RKISP1_CIF_MI_IMSC); - rkisp1_write(rkisp1, ~0, RKISP1_CIF_MI_ICR); - val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); - rkisp1_write(rkisp1, val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA), - RKISP1_CIF_MIPI_CTRL); - /* stop ISP */ - val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); - val &= ~(RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE | - RKISP1_CIF_ISP_CTRL_ISP_ENABLE); - rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); - - val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); - rkisp1_write(rkisp1, val | RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD, - RKISP1_CIF_ISP_CTRL); - - readx_poll_timeout(readl, rkisp1->base_addr + RKISP1_CIF_ISP_RIS, - val, val & RKISP1_CIF_ISP_OFF, 20, 100); - rkisp1_write(rkisp1, - RKISP1_CIF_IRCL_MIPI_SW_RST | RKISP1_CIF_IRCL_ISP_SW_RST, - RKISP1_CIF_IRCL); - rkisp1_write(rkisp1, 0x0, RKISP1_CIF_IRCL); -} - -static void rkisp1_config_clk(struct rkisp1_device *rkisp1) -{ - u32 val = RKISP1_CIF_ICCL_ISP_CLK | RKISP1_CIF_ICCL_CP_CLK | - RKISP1_CIF_ICCL_MRSZ_CLK | RKISP1_CIF_ICCL_SRSZ_CLK | - RKISP1_CIF_ICCL_JPEG_CLK | RKISP1_CIF_ICCL_MI_CLK | - RKISP1_CIF_ICCL_IE_CLK | RKISP1_CIF_ICCL_MIPI_CLK | - RKISP1_CIF_ICCL_DCROP_CLK; - - rkisp1_write(rkisp1, val, RKISP1_CIF_ICCL); -} - -static void rkisp1_isp_start(struct rkisp1_device *rkisp1) -{ - struct rkisp1_sensor_async *sensor = rkisp1->active_sensor; - u32 val; - - rkisp1_config_clk(rkisp1); - - /* Activate MIPI */ - if (sensor->mbus_type == V4L2_MBUS_CSI2_DPHY) { - val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); - rkisp1_write(rkisp1, val | RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA, - RKISP1_CIF_MIPI_CTRL); - } - /* Activate ISP */ - val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL); - val |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD | - RKISP1_CIF_ISP_CTRL_ISP_ENABLE | - RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE; - rkisp1_write(rkisp1, val, RKISP1_CIF_ISP_CTRL); - - /* - * CIF spec says to wait for sufficient time after enabling - * the MIPI interface and before starting the sensor output. - */ - usleep_range(1000, 1200); -} - -/* ---------------------------------------------------------------------------- - * Subdev pad operations - */ - -static int rkisp1_isp_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - unsigned int i, dir; - int pos = 0; - - if (code->pad == RKISP1_ISP_PAD_SINK_VIDEO) { - dir = RKISP1_ISP_SD_SINK; - } else if (code->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) { - dir = RKISP1_ISP_SD_SRC; - } else { - if (code->index > 0) - return -EINVAL; - code->code = MEDIA_BUS_FMT_METADATA_FIXED; - return 0; - } - - if (code->index >= ARRAY_SIZE(rkisp1_isp_formats)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(rkisp1_isp_formats); i++) { - const struct rkisp1_isp_mbus_info *fmt = &rkisp1_isp_formats[i]; - - if (fmt->direction & dir) - pos++; - - if (code->index == pos - 1) { - code->code = fmt->mbus_code; - if (fmt->pixel_enc == V4L2_PIXEL_ENC_YUV && - dir == RKISP1_ISP_SD_SRC) - code->flags = - V4L2_SUBDEV_MBUS_CODE_CSC_QUANTIZATION; - return 0; - } - } - - return -EINVAL; -} - -static int rkisp1_isp_init_config(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg) -{ - struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; - struct v4l2_rect *sink_crop, *src_crop; - - sink_fmt = v4l2_subdev_get_try_format(sd, cfg, - RKISP1_ISP_PAD_SINK_VIDEO); - sink_fmt->width = RKISP1_DEFAULT_WIDTH; - sink_fmt->height = RKISP1_DEFAULT_HEIGHT; - sink_fmt->field = V4L2_FIELD_NONE; - sink_fmt->code = RKISP1_DEF_SINK_PAD_FMT; - - sink_crop = v4l2_subdev_get_try_crop(sd, cfg, - RKISP1_ISP_PAD_SINK_VIDEO); - sink_crop->width = RKISP1_DEFAULT_WIDTH; - sink_crop->height = RKISP1_DEFAULT_HEIGHT; - sink_crop->left = 0; - sink_crop->top = 0; - - src_fmt = v4l2_subdev_get_try_format(sd, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO); - *src_fmt = *sink_fmt; - src_fmt->code = RKISP1_DEF_SRC_PAD_FMT; - - src_crop = v4l2_subdev_get_try_crop(sd, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO); - *src_crop = *sink_crop; - - sink_fmt = v4l2_subdev_get_try_format(sd, cfg, - RKISP1_ISP_PAD_SINK_PARAMS); - src_fmt = v4l2_subdev_get_try_format(sd, cfg, - RKISP1_ISP_PAD_SOURCE_STATS); - sink_fmt->width = 0; - sink_fmt->height = 0; - sink_fmt->field = V4L2_FIELD_NONE; - sink_fmt->code = MEDIA_BUS_FMT_METADATA_FIXED; - *src_fmt = *sink_fmt; - - return 0; -} - -static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_mbus_framefmt *format, - unsigned int which) -{ - const struct rkisp1_isp_mbus_info *mbus_info; - struct v4l2_mbus_framefmt *src_fmt; - const struct v4l2_rect *src_crop; - - src_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO, which); - src_crop = rkisp1_isp_get_pad_crop(isp, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO, which); - - src_fmt->code = format->code; - mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); - if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) { - src_fmt->code = RKISP1_DEF_SRC_PAD_FMT; - mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); - } - if (which == V4L2_SUBDEV_FORMAT_ACTIVE) - isp->src_fmt = mbus_info; - src_fmt->width = src_crop->width; - src_fmt->height = src_crop->height; - - /* - * The CSC API is used to allow userspace to force full - * quantization on YUV formats. - */ - if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC && - format->quantization == V4L2_QUANTIZATION_FULL_RANGE && - mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV) - src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; - else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV) - src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE; - else - src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; - - *format = *src_fmt; -} - -static void rkisp1_isp_set_src_crop(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_rect *r, unsigned int which) -{ - struct v4l2_mbus_framefmt *src_fmt; - const struct v4l2_rect *sink_crop; - struct v4l2_rect *src_crop; - - src_crop = rkisp1_isp_get_pad_crop(isp, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO, - which); - sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, - RKISP1_ISP_PAD_SINK_VIDEO, - which); - - src_crop->left = ALIGN(r->left, 2); - src_crop->width = ALIGN(r->width, 2); - src_crop->top = r->top; - src_crop->height = r->height; - rkisp1_sd_adjust_crop_rect(src_crop, sink_crop); - - *r = *src_crop; - - /* Propagate to out format */ - src_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO, which); - rkisp1_isp_set_src_fmt(isp, cfg, src_fmt, which); -} - -static void rkisp1_isp_set_sink_crop(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_rect *r, unsigned int which) -{ - struct v4l2_rect *sink_crop, *src_crop; - struct v4l2_mbus_framefmt *sink_fmt; - - sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, - which); - sink_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, - which); - - sink_crop->left = ALIGN(r->left, 2); - sink_crop->width = ALIGN(r->width, 2); - sink_crop->top = r->top; - sink_crop->height = r->height; - rkisp1_sd_adjust_crop(sink_crop, sink_fmt); - - *r = *sink_crop; - - /* Propagate to out crop */ - src_crop = rkisp1_isp_get_pad_crop(isp, cfg, - RKISP1_ISP_PAD_SOURCE_VIDEO, which); - rkisp1_isp_set_src_crop(isp, cfg, src_crop, which); -} - -static void rkisp1_isp_set_sink_fmt(struct rkisp1_isp *isp, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_mbus_framefmt *format, - unsigned int which) -{ - const struct rkisp1_isp_mbus_info *mbus_info; - struct v4l2_mbus_framefmt *sink_fmt; - struct v4l2_rect *sink_crop; - - sink_fmt = rkisp1_isp_get_pad_fmt(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, - which); - sink_fmt->code = format->code; - mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); - if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SINK)) { - sink_fmt->code = RKISP1_DEF_SINK_PAD_FMT; - mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); - } - if (which == V4L2_SUBDEV_FORMAT_ACTIVE) - isp->sink_fmt = mbus_info; - - sink_fmt->width = clamp_t(u32, format->width, - RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); - sink_fmt->height = clamp_t(u32, format->height, - RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); - - *format = *sink_fmt; - - /* Propagate to in crop */ - sink_crop = rkisp1_isp_get_pad_crop(isp, cfg, RKISP1_ISP_PAD_SINK_VIDEO, - which); - rkisp1_isp_set_sink_crop(isp, cfg, sink_crop, which); -} - -static int rkisp1_isp_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); - - mutex_lock(&isp->ops_lock); - fmt->format = *rkisp1_isp_get_pad_fmt(isp, cfg, fmt->pad, fmt->which); - mutex_unlock(&isp->ops_lock); - return 0; -} - -static int rkisp1_isp_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); - - mutex_lock(&isp->ops_lock); - if (fmt->pad == RKISP1_ISP_PAD_SINK_VIDEO) - rkisp1_isp_set_sink_fmt(isp, cfg, &fmt->format, fmt->which); - else if (fmt->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) - rkisp1_isp_set_src_fmt(isp, cfg, &fmt->format, fmt->which); - else - fmt->format = *rkisp1_isp_get_pad_fmt(isp, cfg, fmt->pad, - fmt->which); - - mutex_unlock(&isp->ops_lock); - return 0; -} - -static int rkisp1_isp_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); - int ret = 0; - - if (sel->pad != RKISP1_ISP_PAD_SOURCE_VIDEO && - sel->pad != RKISP1_ISP_PAD_SINK_VIDEO) - return -EINVAL; - - mutex_lock(&isp->ops_lock); - switch (sel->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - if (sel->pad == RKISP1_ISP_PAD_SINK_VIDEO) { - struct v4l2_mbus_framefmt *fmt; - - fmt = rkisp1_isp_get_pad_fmt(isp, cfg, sel->pad, - sel->which); - sel->r.height = fmt->height; - sel->r.width = fmt->width; - sel->r.left = 0; - sel->r.top = 0; - } else { - sel->r = *rkisp1_isp_get_pad_crop(isp, cfg, - RKISP1_ISP_PAD_SINK_VIDEO, - sel->which); - } - break; - case V4L2_SEL_TGT_CROP: - sel->r = *rkisp1_isp_get_pad_crop(isp, cfg, sel->pad, - sel->which); - break; - default: - ret = -EINVAL; - } - mutex_unlock(&isp->ops_lock); - return ret; -} - -static int rkisp1_isp_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct rkisp1_device *rkisp1 = - container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev); - struct rkisp1_isp *isp = container_of(sd, struct rkisp1_isp, sd); - int ret = 0; - - if (sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - dev_dbg(rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, - sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); - mutex_lock(&isp->ops_lock); - if (sel->pad == RKISP1_ISP_PAD_SINK_VIDEO) - rkisp1_isp_set_sink_crop(isp, cfg, &sel->r, sel->which); - else if (sel->pad == RKISP1_ISP_PAD_SOURCE_VIDEO) - rkisp1_isp_set_src_crop(isp, cfg, &sel->r, sel->which); - else - ret = -EINVAL; - - mutex_unlock(&isp->ops_lock); - return ret; -} - -static int rkisp1_subdev_link_validate(struct media_link *link) -{ - if (link->sink->index == RKISP1_ISP_PAD_SINK_PARAMS) - return 0; - - return v4l2_subdev_link_validate(link); -} - -static const struct v4l2_subdev_pad_ops rkisp1_isp_pad_ops = { - .enum_mbus_code = rkisp1_isp_enum_mbus_code, - .get_selection = rkisp1_isp_get_selection, - .set_selection = rkisp1_isp_set_selection, - .init_cfg = rkisp1_isp_init_config, - .get_fmt = rkisp1_isp_get_fmt, - .set_fmt = rkisp1_isp_set_fmt, - .link_validate = v4l2_subdev_link_validate_default, -}; - -/* ---------------------------------------------------------------------------- - * Stream operations - */ - -static int rkisp1_mipi_csi2_start(struct rkisp1_isp *isp, - struct rkisp1_sensor_async *sensor) -{ - struct rkisp1_device *rkisp1 = - container_of(isp->sd.v4l2_dev, struct rkisp1_device, v4l2_dev); - union phy_configure_opts opts; - struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; - s64 pixel_clock; - - if (!sensor->pixel_rate_ctrl) { - dev_warn(rkisp1->dev, "No pixel rate control in sensor subdev\n"); - return -EPIPE; - } - - pixel_clock = v4l2_ctrl_g_ctrl_int64(sensor->pixel_rate_ctrl); - if (!pixel_clock) { - dev_err(rkisp1->dev, "Invalid pixel rate value\n"); - return -EINVAL; - } - - phy_mipi_dphy_get_default_config(pixel_clock, isp->sink_fmt->bus_width, - sensor->lanes, cfg); - phy_set_mode(sensor->dphy, PHY_MODE_MIPI_DPHY); - phy_configure(sensor->dphy, &opts); - phy_power_on(sensor->dphy); - - return 0; -} - -static void rkisp1_mipi_csi2_stop(struct rkisp1_sensor_async *sensor) -{ - phy_power_off(sensor->dphy); -} - -static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct rkisp1_device *rkisp1 = - container_of(sd->v4l2_dev, struct rkisp1_device, v4l2_dev); - struct rkisp1_isp *isp = &rkisp1->isp; - struct v4l2_subdev *sensor_sd; - int ret = 0; - - if (!enable) { - rkisp1_isp_stop(rkisp1); - rkisp1_mipi_csi2_stop(rkisp1->active_sensor); - return 0; - } - - sensor_sd = rkisp1_get_remote_sensor(sd); - if (!sensor_sd) { - dev_warn(rkisp1->dev, "No link between isp and sensor\n"); - return -ENODEV; - } - - rkisp1->active_sensor = container_of(sensor_sd->asd, - struct rkisp1_sensor_async, asd); - - if (rkisp1->active_sensor->mbus_type != V4L2_MBUS_CSI2_DPHY) - return -EINVAL; - - rkisp1->isp.frame_sequence = -1; - mutex_lock(&isp->ops_lock); - ret = rkisp1_config_cif(rkisp1); - if (ret) - goto mutex_unlock; - - ret = rkisp1_mipi_csi2_start(&rkisp1->isp, rkisp1->active_sensor); - if (ret) - goto mutex_unlock; - - rkisp1_isp_start(rkisp1); - -mutex_unlock: - mutex_unlock(&isp->ops_lock); - return ret; -} - -static int rkisp1_isp_subs_evt(struct v4l2_subdev *sd, struct v4l2_fh *fh, - struct v4l2_event_subscription *sub) -{ - if (sub->type != V4L2_EVENT_FRAME_SYNC) - return -EINVAL; - - /* V4L2_EVENT_FRAME_SYNC doesn't require an id, so zero should be set */ - if (sub->id != 0) - return -EINVAL; - - return v4l2_event_subscribe(fh, sub, 0, NULL); -} - -static const struct media_entity_operations rkisp1_isp_media_ops = { - .link_validate = rkisp1_subdev_link_validate, -}; - -static const struct v4l2_subdev_video_ops rkisp1_isp_video_ops = { - .s_stream = rkisp1_isp_s_stream, -}; - -static const struct v4l2_subdev_core_ops rkisp1_isp_core_ops = { - .subscribe_event = rkisp1_isp_subs_evt, - .unsubscribe_event = v4l2_event_subdev_unsubscribe, -}; - -static const struct v4l2_subdev_ops rkisp1_isp_ops = { - .core = &rkisp1_isp_core_ops, - .video = &rkisp1_isp_video_ops, - .pad = &rkisp1_isp_pad_ops, -}; - -int rkisp1_isp_register(struct rkisp1_device *rkisp1) -{ - struct rkisp1_isp *isp = &rkisp1->isp; - struct media_pad *pads = isp->pads; - struct v4l2_subdev *sd = &isp->sd; - int ret; - - v4l2_subdev_init(sd, &rkisp1_isp_ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; - sd->entity.ops = &rkisp1_isp_media_ops; - sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; - sd->owner = THIS_MODULE; - strscpy(sd->name, RKISP1_ISP_DEV_NAME, sizeof(sd->name)); - - pads[RKISP1_ISP_PAD_SINK_VIDEO].flags = MEDIA_PAD_FL_SINK | - MEDIA_PAD_FL_MUST_CONNECT; - pads[RKISP1_ISP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK; - pads[RKISP1_ISP_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; - pads[RKISP1_ISP_PAD_SOURCE_STATS].flags = MEDIA_PAD_FL_SOURCE; - - isp->sink_fmt = rkisp1_isp_mbus_info_get(RKISP1_DEF_SINK_PAD_FMT); - isp->src_fmt = rkisp1_isp_mbus_info_get(RKISP1_DEF_SRC_PAD_FMT); - - mutex_init(&isp->ops_lock); - ret = media_entity_pads_init(&sd->entity, RKISP1_ISP_PAD_MAX, pads); - if (ret) - return ret; - - ret = v4l2_device_register_subdev(&rkisp1->v4l2_dev, sd); - if (ret) { - dev_err(rkisp1->dev, "Failed to register isp subdev\n"); - goto err_cleanup_media_entity; - } - - rkisp1_isp_init_config(sd, rkisp1->isp.pad_cfg); - return 0; - -err_cleanup_media_entity: - media_entity_cleanup(&sd->entity); - - return ret; -} - -void rkisp1_isp_unregister(struct rkisp1_device *rkisp1) -{ - struct v4l2_subdev *sd = &rkisp1->isp.sd; - - v4l2_device_unregister_subdev(sd); - media_entity_cleanup(&sd->entity); -} - -/* ---------------------------------------------------------------------------- - * Interrupt handlers - */ - -void rkisp1_mipi_isr(struct rkisp1_device *rkisp1) -{ - u32 val, status; - - status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS); - if (!status) - return; - - rkisp1_write(rkisp1, status, RKISP1_CIF_MIPI_ICR); - - /* - * Disable DPHY errctrl interrupt, because this dphy - * erctrl signal is asserted until the next changes - * of line state. This time is may be too long and cpu - * is hold in this interrupt. - */ - if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) { - val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); - rkisp1_write(rkisp1, val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f), - RKISP1_CIF_MIPI_IMSC); - rkisp1->isp.is_dphy_errctrl_disabled = true; - } - - /* - * Enable DPHY errctrl interrupt again, if mipi have receive - * the whole frame without any error. - */ - if (status == RKISP1_CIF_MIPI_FRAME_END) { - /* - * Enable DPHY errctrl interrupt again, if mipi have receive - * the whole frame without any error. - */ - if (rkisp1->isp.is_dphy_errctrl_disabled) { - val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); - val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f); - rkisp1_write(rkisp1, val, RKISP1_CIF_MIPI_IMSC); - rkisp1->isp.is_dphy_errctrl_disabled = false; - } - } else { - rkisp1->debug.mipi_error++; - } -} - -static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp) -{ - struct v4l2_event event = { - .type = V4L2_EVENT_FRAME_SYNC, - }; - event.u.frame_sync.frame_sequence = isp->frame_sequence; - - v4l2_event_queue(isp->sd.devnode, &event); -} - -void rkisp1_isp_isr(struct rkisp1_device *rkisp1) -{ - u32 status, isp_err; - - status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); - if (!status) - return; - - rkisp1_write(rkisp1, status, RKISP1_CIF_ISP_ICR); - - /* Vertical sync signal, starting generating new frame */ - if (status & RKISP1_CIF_ISP_V_START) { - rkisp1->isp.frame_sequence++; - rkisp1_isp_queue_event_sof(&rkisp1->isp); - if (status & RKISP1_CIF_ISP_FRAME) { - WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n"); - rkisp1->debug.irq_delay++; - } - } - if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) { - /* Clear pic_size_error */ - isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR); - if (isp_err & RKISP1_CIF_ISP_ERR_INFORM_SIZE) - rkisp1->debug.inform_size_error++; - if (isp_err & RKISP1_CIF_ISP_ERR_IS_SIZE) - rkisp1->debug.img_stabilization_size_error++; - if (isp_err & RKISP1_CIF_ISP_ERR_OUTFORM_SIZE) - rkisp1->debug.outform_size_error++; - rkisp1_write(rkisp1, isp_err, RKISP1_CIF_ISP_ERR_CLR); - } else if (status & RKISP1_CIF_ISP_DATA_LOSS) { - /* keep track of data_loss in debugfs */ - rkisp1->debug.data_loss++; - } - - if (status & RKISP1_CIF_ISP_FRAME) { - u32 isp_ris; - - /* New frame from the sensor received */ - isp_ris = rkisp1_read(rkisp1, RKISP1_CIF_ISP_RIS); - if (isp_ris & RKISP1_STATS_MEAS_MASK) - rkisp1_stats_isr(&rkisp1->stats, isp_ris); - /* - * Then update changed configs. Some of them involve - * lot of register writes. Do those only one per frame. - * Do the updates in the order of the processing flow. - */ - rkisp1_params_isr(rkisp1); - } - -} diff --git a/drivers/staging/media/rkisp1/rkisp1-params.c b/drivers/staging/media/rkisp1/rkisp1-params.c deleted file mode 100644 index 298c16736b1c..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-params.c +++ /dev/null @@ -1,1572 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - Params subdevice - * - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include /* for ISP params */ - -#include "rkisp1-common.h" - -#define RKISP1_PARAMS_DEV_NAME RKISP1_DRIVER_NAME "_params" - -#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2 -#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8 - -#define RKISP1_ISP_DPCC_LINE_THRESH(n) \ - (RKISP1_CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * (n)) -#define RKISP1_ISP_DPCC_LINE_MAD_FAC(n) \ - (RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * (n)) -#define RKISP1_ISP_DPCC_PG_FAC(n) \ - (RKISP1_CIF_ISP_DPCC_PG_FAC_1 + 0x14 * (n)) -#define RKISP1_ISP_DPCC_RND_THRESH(n) \ - (RKISP1_CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * (n)) -#define RKISP1_ISP_DPCC_RG_FAC(n) \ - (RKISP1_CIF_ISP_DPCC_RG_FAC_1 + 0x14 * (n)) -#define RKISP1_ISP_CC_COEFF(n) \ - (RKISP1_CIF_ISP_CC_COEFF_0 + (n) * 4) - -static inline void -rkisp1_param_set_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) -{ - u32 val; - - val = rkisp1_read(params->rkisp1, reg); - rkisp1_write(params->rkisp1, val | bit_mask, reg); -} - -static inline void -rkisp1_param_clear_bits(struct rkisp1_params *params, u32 reg, u32 bit_mask) -{ - u32 val; - - val = rkisp1_read(params->rkisp1, reg); - rkisp1_write(params->rkisp1, val & ~bit_mask, reg); -} - -/* ISP BP interface function */ -static void rkisp1_dpcc_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_dpcc_config *arg) -{ - unsigned int i; - u32 mode; - - /* avoid to override the old enable value */ - mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DPCC_MODE); - mode &= RKISP1_CIF_ISP_DPCC_ENA; - mode |= arg->mode & ~RKISP1_CIF_ISP_DPCC_ENA; - rkisp1_write(params->rkisp1, mode, RKISP1_CIF_ISP_DPCC_MODE); - rkisp1_write(params->rkisp1, arg->output_mode, - RKISP1_CIF_ISP_DPCC_OUTPUT_MODE); - rkisp1_write(params->rkisp1, arg->set_use, - RKISP1_CIF_ISP_DPCC_SET_USE); - - rkisp1_write(params->rkisp1, arg->methods[0].method, - RKISP1_CIF_ISP_DPCC_METHODS_SET_1); - rkisp1_write(params->rkisp1, arg->methods[1].method, - RKISP1_CIF_ISP_DPCC_METHODS_SET_2); - rkisp1_write(params->rkisp1, arg->methods[2].method, - RKISP1_CIF_ISP_DPCC_METHODS_SET_3); - for (i = 0; i < RKISP1_CIF_ISP_DPCC_METHODS_MAX; i++) { - rkisp1_write(params->rkisp1, arg->methods[i].line_thresh, - RKISP1_ISP_DPCC_LINE_THRESH(i)); - rkisp1_write(params->rkisp1, arg->methods[i].line_mad_fac, - RKISP1_ISP_DPCC_LINE_MAD_FAC(i)); - rkisp1_write(params->rkisp1, arg->methods[i].pg_fac, - RKISP1_ISP_DPCC_PG_FAC(i)); - rkisp1_write(params->rkisp1, arg->methods[i].rnd_thresh, - RKISP1_ISP_DPCC_RND_THRESH(i)); - rkisp1_write(params->rkisp1, arg->methods[i].rg_fac, - RKISP1_ISP_DPCC_RG_FAC(i)); - } - - rkisp1_write(params->rkisp1, arg->rnd_offs, - RKISP1_CIF_ISP_DPCC_RND_OFFS); - rkisp1_write(params->rkisp1, arg->ro_limits, - RKISP1_CIF_ISP_DPCC_RO_LIMITS); -} - -/* ISP black level subtraction interface function */ -static void rkisp1_bls_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_bls_config *arg) -{ - /* avoid to override the old enable value */ - u32 new_control; - - new_control = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_BLS_CTRL); - new_control &= RKISP1_CIF_ISP_BLS_ENA; - /* fixed subtraction values */ - if (!arg->enable_auto) { - const struct rkisp1_cif_isp_bls_fixed_val *pval = - &arg->fixed_val; - - switch (params->raw_type) { - case RKISP1_RAW_BGGR: - rkisp1_write(params->rkisp1, - pval->r, RKISP1_CIF_ISP_BLS_D_FIXED); - rkisp1_write(params->rkisp1, - pval->gr, RKISP1_CIF_ISP_BLS_C_FIXED); - rkisp1_write(params->rkisp1, - pval->gb, RKISP1_CIF_ISP_BLS_B_FIXED); - rkisp1_write(params->rkisp1, - pval->b, RKISP1_CIF_ISP_BLS_A_FIXED); - break; - case RKISP1_RAW_GBRG: - rkisp1_write(params->rkisp1, - pval->r, RKISP1_CIF_ISP_BLS_C_FIXED); - rkisp1_write(params->rkisp1, - pval->gr, RKISP1_CIF_ISP_BLS_D_FIXED); - rkisp1_write(params->rkisp1, - pval->gb, RKISP1_CIF_ISP_BLS_A_FIXED); - rkisp1_write(params->rkisp1, - pval->b, RKISP1_CIF_ISP_BLS_B_FIXED); - break; - case RKISP1_RAW_GRBG: - rkisp1_write(params->rkisp1, - pval->r, RKISP1_CIF_ISP_BLS_B_FIXED); - rkisp1_write(params->rkisp1, - pval->gr, RKISP1_CIF_ISP_BLS_A_FIXED); - rkisp1_write(params->rkisp1, - pval->gb, RKISP1_CIF_ISP_BLS_D_FIXED); - rkisp1_write(params->rkisp1, - pval->b, RKISP1_CIF_ISP_BLS_C_FIXED); - break; - case RKISP1_RAW_RGGB: - rkisp1_write(params->rkisp1, - pval->r, RKISP1_CIF_ISP_BLS_A_FIXED); - rkisp1_write(params->rkisp1, - pval->gr, RKISP1_CIF_ISP_BLS_B_FIXED); - rkisp1_write(params->rkisp1, - pval->gb, RKISP1_CIF_ISP_BLS_C_FIXED); - rkisp1_write(params->rkisp1, - pval->b, RKISP1_CIF_ISP_BLS_D_FIXED); - break; - default: - break; - } - - } else { - if (arg->en_windows & BIT(1)) { - rkisp1_write(params->rkisp1, arg->bls_window2.h_offs, - RKISP1_CIF_ISP_BLS_H2_START); - rkisp1_write(params->rkisp1, arg->bls_window2.h_size, - RKISP1_CIF_ISP_BLS_H2_STOP); - rkisp1_write(params->rkisp1, arg->bls_window2.v_offs, - RKISP1_CIF_ISP_BLS_V2_START); - rkisp1_write(params->rkisp1, arg->bls_window2.v_size, - RKISP1_CIF_ISP_BLS_V2_STOP); - new_control |= RKISP1_CIF_ISP_BLS_WINDOW_2; - } - - if (arg->en_windows & BIT(0)) { - rkisp1_write(params->rkisp1, arg->bls_window1.h_offs, - RKISP1_CIF_ISP_BLS_H1_START); - rkisp1_write(params->rkisp1, arg->bls_window1.h_size, - RKISP1_CIF_ISP_BLS_H1_STOP); - rkisp1_write(params->rkisp1, arg->bls_window1.v_offs, - RKISP1_CIF_ISP_BLS_V1_START); - rkisp1_write(params->rkisp1, arg->bls_window1.v_size, - RKISP1_CIF_ISP_BLS_V1_STOP); - new_control |= RKISP1_CIF_ISP_BLS_WINDOW_1; - } - - rkisp1_write(params->rkisp1, arg->bls_samples, - RKISP1_CIF_ISP_BLS_SAMPLES); - - new_control |= RKISP1_CIF_ISP_BLS_MODE_MEASURED; - } - rkisp1_write(params->rkisp1, new_control, RKISP1_CIF_ISP_BLS_CTRL); -} - -/* ISP LS correction interface function */ -static void -rkisp1_lsc_correct_matrix_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_lsc_config *pconfig) -{ - unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel, i, j, data; - - isp_lsc_status = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_LSC_STATUS); - - /* RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 = ( 17 * 18 ) >> 1 */ - sram_addr = (isp_lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE) ? - RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 : - RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153; - rkisp1_write(params->rkisp1, sram_addr, - RKISP1_CIF_ISP_LSC_R_TABLE_ADDR); - rkisp1_write(params->rkisp1, sram_addr, - RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR); - rkisp1_write(params->rkisp1, sram_addr, - RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR); - rkisp1_write(params->rkisp1, sram_addr, - RKISP1_CIF_ISP_LSC_B_TABLE_ADDR); - - /* program data tables (table size is 9 * 17 = 153) */ - for (i = 0; i < RKISP1_CIF_ISP_LSC_SAMPLES_MAX; i++) { - /* - * 17 sectors with 2 values in one DWORD = 9 - * DWORDs (2nd value of last DWORD unused) - */ - for (j = 0; j < RKISP1_CIF_ISP_LSC_SAMPLES_MAX - 1; j += 2) { - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j], - pconfig->r_data_tbl[i][j + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_R_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j], - pconfig->gr_data_tbl[i][j + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_GR_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j], - pconfig->gb_data_tbl[i][j + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_GB_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j], - pconfig->b_data_tbl[i][j + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_B_TABLE_DATA); - } - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->r_data_tbl[i][j], 0); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_R_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gr_data_tbl[i][j], 0); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_GR_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->gb_data_tbl[i][j], 0); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_GB_TABLE_DATA); - - data = RKISP1_CIF_ISP_LSC_TABLE_DATA(pconfig->b_data_tbl[i][j], 0); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_B_TABLE_DATA); - } - isp_lsc_table_sel = (isp_lsc_status & RKISP1_CIF_ISP_LSC_ACTIVE_TABLE) ? - RKISP1_CIF_ISP_LSC_TABLE_0 : - RKISP1_CIF_ISP_LSC_TABLE_1; - rkisp1_write(params->rkisp1, isp_lsc_table_sel, - RKISP1_CIF_ISP_LSC_TABLE_SEL); -} - -static void rkisp1_lsc_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_lsc_config *arg) -{ - unsigned int i, data; - u32 lsc_ctrl; - - /* To config must be off , store the current status firstly */ - lsc_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_LSC_CTRL); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - rkisp1_lsc_correct_matrix_config(params, arg); - - for (i = 0; i < RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE / 2; i++) { - /* program x size tables */ - data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_size_tbl[i * 2], - arg->x_size_tbl[i * 2 + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_XSIZE_01 + i * 4); - - /* program x grad tables */ - data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2], - arg->x_grad_tbl[i * 2 + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_XGRAD_01 + i * 4); - - /* program y size tables */ - data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_size_tbl[i * 2], - arg->y_size_tbl[i * 2 + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_YSIZE_01 + i * 4); - - /* program y grad tables */ - data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2], - arg->y_grad_tbl[i * 2 + 1]); - rkisp1_write(params->rkisp1, data, - RKISP1_CIF_ISP_LSC_YGRAD_01 + i * 4); - } - - /* restore the lsc ctrl status */ - if (lsc_ctrl & RKISP1_CIF_ISP_LSC_CTRL_ENA) { - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - } else { - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - } -} - -/* ISP Filtering function */ -static void rkisp1_flt_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_flt_config *arg) -{ - u32 filt_mode; - - rkisp1_write(params->rkisp1, - arg->thresh_bl0, RKISP1_CIF_ISP_FILT_THRESH_BL0); - rkisp1_write(params->rkisp1, - arg->thresh_bl1, RKISP1_CIF_ISP_FILT_THRESH_BL1); - rkisp1_write(params->rkisp1, - arg->thresh_sh0, RKISP1_CIF_ISP_FILT_THRESH_SH0); - rkisp1_write(params->rkisp1, - arg->thresh_sh1, RKISP1_CIF_ISP_FILT_THRESH_SH1); - rkisp1_write(params->rkisp1, arg->fac_bl0, RKISP1_CIF_ISP_FILT_FAC_BL0); - rkisp1_write(params->rkisp1, arg->fac_bl1, RKISP1_CIF_ISP_FILT_FAC_BL1); - rkisp1_write(params->rkisp1, arg->fac_mid, RKISP1_CIF_ISP_FILT_FAC_MID); - rkisp1_write(params->rkisp1, arg->fac_sh0, RKISP1_CIF_ISP_FILT_FAC_SH0); - rkisp1_write(params->rkisp1, arg->fac_sh1, RKISP1_CIF_ISP_FILT_FAC_SH1); - rkisp1_write(params->rkisp1, - arg->lum_weight, RKISP1_CIF_ISP_FILT_LUM_WEIGHT); - - rkisp1_write(params->rkisp1, - (arg->mode ? RKISP1_CIF_ISP_FLT_MODE_DNR : 0) | - RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | - RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | - RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1), - RKISP1_CIF_ISP_FILT_MODE); - - /* avoid to override the old enable value */ - filt_mode = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_FILT_MODE); - filt_mode &= RKISP1_CIF_ISP_FLT_ENA; - if (arg->mode) - filt_mode |= RKISP1_CIF_ISP_FLT_MODE_DNR; - filt_mode |= RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(arg->chr_v_mode) | - RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(arg->chr_h_mode) | - RKISP1_CIF_ISP_FLT_GREEN_STAGE1(arg->grn_stage1); - rkisp1_write(params->rkisp1, filt_mode, RKISP1_CIF_ISP_FILT_MODE); -} - -/* ISP demosaic interface function */ -static int rkisp1_bdm_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_bdm_config *arg) -{ - u32 bdm_th; - - /* avoid to override the old enable value */ - bdm_th = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_DEMOSAIC); - bdm_th &= RKISP1_CIF_ISP_DEMOSAIC_BYPASS; - bdm_th |= arg->demosaic_th & ~RKISP1_CIF_ISP_DEMOSAIC_BYPASS; - /* set demosaic threshold */ - rkisp1_write(params->rkisp1, bdm_th, RKISP1_CIF_ISP_DEMOSAIC); - return 0; -} - -/* ISP GAMMA correction interface function */ -static void rkisp1_sdg_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_sdg_config *arg) -{ - unsigned int i; - - rkisp1_write(params->rkisp1, - arg->xa_pnts.gamma_dx0, RKISP1_CIF_ISP_GAMMA_DX_LO); - rkisp1_write(params->rkisp1, - arg->xa_pnts.gamma_dx1, RKISP1_CIF_ISP_GAMMA_DX_HI); - - for (i = 0; i < RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE; i++) { - rkisp1_write(params->rkisp1, arg->curve_r.gamma_y[i], - RKISP1_CIF_ISP_GAMMA_R_Y0 + i * 4); - rkisp1_write(params->rkisp1, arg->curve_g.gamma_y[i], - RKISP1_CIF_ISP_GAMMA_G_Y0 + i * 4); - rkisp1_write(params->rkisp1, arg->curve_b.gamma_y[i], - RKISP1_CIF_ISP_GAMMA_B_Y0 + i * 4); - } -} - -/* ISP GAMMA correction interface function */ -static void rkisp1_goc_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_goc_config *arg) -{ - unsigned int i; - - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); - rkisp1_write(params->rkisp1, arg->mode, RKISP1_CIF_ISP_GAMMA_OUT_MODE); - - for (i = 0; i < RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES; i++) - rkisp1_write(params->rkisp1, arg->gamma_y[i], - RKISP1_CIF_ISP_GAMMA_OUT_Y_0 + i * 4); -} - -/* ISP Cross Talk */ -static void rkisp1_ctk_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_ctk_config *arg) -{ - unsigned int i, j, k = 0; - - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) - rkisp1_write(params->rkisp1, arg->coeff[i][j], - RKISP1_CIF_ISP_CT_COEFF_0 + 4 * k++); - for (i = 0; i < 3; i++) - rkisp1_write(params->rkisp1, arg->ct_offset[i], - RKISP1_CIF_ISP_CT_OFFSET_R + i * 4); -} - -static void rkisp1_ctk_enable(struct rkisp1_params *params, bool en) -{ - if (en) - return; - - /* Write back the default values. */ - rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_0); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_1); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_2); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_3); - rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_4); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_5); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_6); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_COEFF_7); - rkisp1_write(params->rkisp1, 0x80, RKISP1_CIF_ISP_CT_COEFF_8); - - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_R); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_G); - rkisp1_write(params->rkisp1, 0, RKISP1_CIF_ISP_CT_OFFSET_B); -} - -/* ISP White Balance Mode */ -static void rkisp1_awb_meas_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_awb_meas_config *arg) -{ - u32 reg_val = 0; - /* based on the mode,configure the awb module */ - if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_YCBCR) { - /* Reference Cb and Cr */ - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AWB_REF_CR_SET(arg->awb_ref_cr) | - arg->awb_ref_cb, RKISP1_CIF_ISP_AWB_REF); - /* Yc Threshold */ - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AWB_MAX_Y_SET(arg->max_y) | - RKISP1_CIF_ISP_AWB_MIN_Y_SET(arg->min_y) | - RKISP1_CIF_ISP_AWB_MAX_CS_SET(arg->max_csum) | - arg->min_c, RKISP1_CIF_ISP_AWB_THRESH); - } - - reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP); - if (arg->enable_ymax_cmp) - reg_val |= RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; - else - reg_val &= ~RKISP1_CIF_ISP_AWB_YMAX_CMP_EN; - rkisp1_write(params->rkisp1, reg_val, RKISP1_CIF_ISP_AWB_PROP); - - /* window offset */ - rkisp1_write(params->rkisp1, - arg->awb_wnd.v_offs, RKISP1_CIF_ISP_AWB_WND_V_OFFS); - rkisp1_write(params->rkisp1, - arg->awb_wnd.h_offs, RKISP1_CIF_ISP_AWB_WND_H_OFFS); - /* AWB window size */ - rkisp1_write(params->rkisp1, - arg->awb_wnd.v_size, RKISP1_CIF_ISP_AWB_WND_V_SIZE); - rkisp1_write(params->rkisp1, - arg->awb_wnd.h_size, RKISP1_CIF_ISP_AWB_WND_H_SIZE); - /* Number of frames */ - rkisp1_write(params->rkisp1, - arg->frames, RKISP1_CIF_ISP_AWB_FRAMES); -} - -static void -rkisp1_awb_meas_enable(struct rkisp1_params *params, - const struct rkisp1_cif_isp_awb_meas_config *arg, - bool en) -{ - u32 reg_val = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AWB_PROP); - - /* switch off */ - reg_val &= RKISP1_CIF_ISP_AWB_MODE_MASK_NONE; - - if (en) { - if (arg->awb_mode == RKISP1_CIF_ISP_AWB_MODE_RGB) - reg_val |= RKISP1_CIF_ISP_AWB_MODE_RGB_EN; - else - reg_val |= RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN; - - rkisp1_write(params->rkisp1, reg_val, RKISP1_CIF_ISP_AWB_PROP); - - /* Measurements require AWB block be active. */ - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); - } else { - rkisp1_write(params->rkisp1, - reg_val, RKISP1_CIF_ISP_AWB_PROP); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); - } -} - -static void -rkisp1_awb_gain_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_awb_gain_config *arg) -{ - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_green_r) | - arg->gain_green_b, RKISP1_CIF_ISP_AWB_GAIN_G); - - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AWB_GAIN_R_SET(arg->gain_red) | - arg->gain_blue, RKISP1_CIF_ISP_AWB_GAIN_RB); -} - -static void rkisp1_aec_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_aec_config *arg) -{ - unsigned int block_hsize, block_vsize; - u32 exp_ctrl; - - /* avoid to override the old enable value */ - exp_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_EXP_CTRL); - exp_ctrl &= RKISP1_CIF_ISP_EXP_ENA; - if (arg->autostop) - exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP; - if (arg->mode == RKISP1_CIF_ISP_EXP_MEASURING_MODE_1) - exp_ctrl |= RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1; - rkisp1_write(params->rkisp1, exp_ctrl, RKISP1_CIF_ISP_EXP_CTRL); - - rkisp1_write(params->rkisp1, - arg->meas_window.h_offs, RKISP1_CIF_ISP_EXP_H_OFFSET); - rkisp1_write(params->rkisp1, - arg->meas_window.v_offs, RKISP1_CIF_ISP_EXP_V_OFFSET); - - block_hsize = arg->meas_window.h_size / - RKISP1_CIF_ISP_EXP_COLUMN_NUM - 1; - block_vsize = arg->meas_window.v_size / - RKISP1_CIF_ISP_EXP_ROW_NUM - 1; - - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_EXP_H_SIZE_SET(block_hsize), - RKISP1_CIF_ISP_EXP_H_SIZE); - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_EXP_V_SIZE_SET(block_vsize), - RKISP1_CIF_ISP_EXP_V_SIZE); -} - -static void rkisp1_cproc_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_cproc_config *arg) -{ - struct rkisp1_cif_isp_isp_other_cfg *cur_other_cfg = - container_of(arg, struct rkisp1_cif_isp_isp_other_cfg, cproc_config); - struct rkisp1_cif_isp_ie_config *cur_ie_config = - &cur_other_cfg->ie_config; - u32 effect = cur_ie_config->effect; - u32 quantization = params->quantization; - - rkisp1_write(params->rkisp1, arg->contrast, RKISP1_CIF_C_PROC_CONTRAST); - rkisp1_write(params->rkisp1, arg->hue, RKISP1_CIF_C_PROC_HUE); - rkisp1_write(params->rkisp1, arg->sat, RKISP1_CIF_C_PROC_SATURATION); - rkisp1_write(params->rkisp1, arg->brightness, - RKISP1_CIF_C_PROC_BRIGHTNESS); - - if (quantization != V4L2_QUANTIZATION_FULL_RANGE || - effect != V4L2_COLORFX_NONE) { - rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, - RKISP1_CIF_C_PROC_YOUT_FULL | - RKISP1_CIF_C_PROC_YIN_FULL | - RKISP1_CIF_C_PROC_COUT_FULL); - } else { - rkisp1_param_set_bits(params, RKISP1_CIF_C_PROC_CTRL, - RKISP1_CIF_C_PROC_YOUT_FULL | - RKISP1_CIF_C_PROC_YIN_FULL | - RKISP1_CIF_C_PROC_COUT_FULL); - } -} - -static void rkisp1_hst_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_hst_config *arg) -{ - unsigned int block_hsize, block_vsize; - static const u32 hist_weight_regs[] = { - RKISP1_CIF_ISP_HIST_WEIGHT_00TO30, - RKISP1_CIF_ISP_HIST_WEIGHT_40TO21, - RKISP1_CIF_ISP_HIST_WEIGHT_31TO12, - RKISP1_CIF_ISP_HIST_WEIGHT_22TO03, - RKISP1_CIF_ISP_HIST_WEIGHT_13TO43, - RKISP1_CIF_ISP_HIST_WEIGHT_04TO34, - RKISP1_CIF_ISP_HIST_WEIGHT_44, - }; - const u8 *weight; - unsigned int i; - u32 hist_prop; - - /* avoid to override the old enable value */ - hist_prop = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_HIST_PROP); - hist_prop &= RKISP1_CIF_ISP_HIST_PROP_MODE_MASK; - hist_prop |= RKISP1_CIF_ISP_HIST_PREDIV_SET(arg->histogram_predivider); - rkisp1_write(params->rkisp1, hist_prop, RKISP1_CIF_ISP_HIST_PROP); - rkisp1_write(params->rkisp1, - arg->meas_window.h_offs, - RKISP1_CIF_ISP_HIST_H_OFFS); - rkisp1_write(params->rkisp1, - arg->meas_window.v_offs, - RKISP1_CIF_ISP_HIST_V_OFFS); - - block_hsize = arg->meas_window.h_size / - RKISP1_CIF_ISP_HIST_COLUMN_NUM - 1; - block_vsize = arg->meas_window.v_size / RKISP1_CIF_ISP_HIST_ROW_NUM - 1; - - rkisp1_write(params->rkisp1, block_hsize, RKISP1_CIF_ISP_HIST_H_SIZE); - rkisp1_write(params->rkisp1, block_vsize, RKISP1_CIF_ISP_HIST_V_SIZE); - - weight = arg->hist_weight; - for (i = 0; i < ARRAY_SIZE(hist_weight_regs); ++i, weight += 4) - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_HIST_WEIGHT_SET(weight[0], - weight[1], - weight[2], - weight[3]), - hist_weight_regs[i]); -} - -static void -rkisp1_hst_enable(struct rkisp1_params *params, - const struct rkisp1_cif_isp_hst_config *arg, bool en) -{ - if (en) { - u32 hist_prop = rkisp1_read(params->rkisp1, - RKISP1_CIF_ISP_HIST_PROP); - - hist_prop &= ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK; - hist_prop |= arg->mode; - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP, - hist_prop); - } else { - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_HIST_PROP, - RKISP1_CIF_ISP_HIST_PROP_MODE_MASK); - } -} - -static void rkisp1_afm_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_afc_config *arg) -{ - size_t num_of_win = min_t(size_t, ARRAY_SIZE(arg->afm_win), - arg->num_afm_win); - u32 afm_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_ISP_AFM_CTRL); - unsigned int i; - - /* Switch off to configure. */ - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, - RKISP1_CIF_ISP_AFM_ENA); - - for (i = 0; i < num_of_win; i++) { - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_offs) | - RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_offs), - RKISP1_CIF_ISP_AFM_LT_A + i * 8); - rkisp1_write(params->rkisp1, - RKISP1_CIF_ISP_AFM_WINDOW_X(arg->afm_win[i].h_size + - arg->afm_win[i].h_offs) | - RKISP1_CIF_ISP_AFM_WINDOW_Y(arg->afm_win[i].v_size + - arg->afm_win[i].v_offs), - RKISP1_CIF_ISP_AFM_RB_A + i * 8); - } - rkisp1_write(params->rkisp1, arg->thres, RKISP1_CIF_ISP_AFM_THRES); - rkisp1_write(params->rkisp1, arg->var_shift, - RKISP1_CIF_ISP_AFM_VAR_SHIFT); - /* restore afm status */ - rkisp1_write(params->rkisp1, afm_ctrl, RKISP1_CIF_ISP_AFM_CTRL); -} - -static void rkisp1_ie_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_ie_config *arg) -{ - u32 eff_ctrl; - - eff_ctrl = rkisp1_read(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL); - eff_ctrl &= ~RKISP1_CIF_IMG_EFF_CTRL_MODE_MASK; - - if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_YCBCR_FULL; - - switch (arg->effect) { - case V4L2_COLORFX_SEPIA: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; - break; - case V4L2_COLORFX_SET_CBCR: - rkisp1_write(params->rkisp1, arg->eff_tint, - RKISP1_CIF_IMG_EFF_TINT); - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA; - break; - /* - * Color selection is similar to water color(AQUA): - * grayscale + selected color w threshold - */ - case V4L2_COLORFX_AQUA: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL; - rkisp1_write(params->rkisp1, arg->color_sel, - RKISP1_CIF_IMG_EFF_COLOR_SEL); - break; - case V4L2_COLORFX_EMBOSS: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS; - rkisp1_write(params->rkisp1, arg->eff_mat_1, - RKISP1_CIF_IMG_EFF_MAT_1); - rkisp1_write(params->rkisp1, arg->eff_mat_2, - RKISP1_CIF_IMG_EFF_MAT_2); - rkisp1_write(params->rkisp1, arg->eff_mat_3, - RKISP1_CIF_IMG_EFF_MAT_3); - break; - case V4L2_COLORFX_SKETCH: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH; - rkisp1_write(params->rkisp1, arg->eff_mat_3, - RKISP1_CIF_IMG_EFF_MAT_3); - rkisp1_write(params->rkisp1, arg->eff_mat_4, - RKISP1_CIF_IMG_EFF_MAT_4); - rkisp1_write(params->rkisp1, arg->eff_mat_5, - RKISP1_CIF_IMG_EFF_MAT_5); - break; - case V4L2_COLORFX_BW: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE; - break; - case V4L2_COLORFX_NEGATIVE: - eff_ctrl |= RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE; - break; - default: - break; - } - - rkisp1_write(params->rkisp1, eff_ctrl, RKISP1_CIF_IMG_EFF_CTRL); -} - -static void rkisp1_ie_enable(struct rkisp1_params *params, bool en) -{ - if (en) { - rkisp1_param_set_bits(params, RKISP1_CIF_ICCL, - RKISP1_CIF_ICCL_IE_CLK); - rkisp1_write(params->rkisp1, RKISP1_CIF_IMG_EFF_CTRL_ENABLE, - RKISP1_CIF_IMG_EFF_CTRL); - rkisp1_param_set_bits(params, RKISP1_CIF_IMG_EFF_CTRL, - RKISP1_CIF_IMG_EFF_CTRL_CFG_UPD); - } else { - rkisp1_param_clear_bits(params, RKISP1_CIF_IMG_EFF_CTRL, - RKISP1_CIF_IMG_EFF_CTRL_ENABLE); - rkisp1_param_clear_bits(params, RKISP1_CIF_ICCL, - RKISP1_CIF_ICCL_IE_CLK); - } -} - -static void rkisp1_csm_config(struct rkisp1_params *params, bool full_range) -{ - static const u16 full_range_coeff[] = { - 0x0026, 0x004b, 0x000f, - 0x01ea, 0x01d6, 0x0040, - 0x0040, 0x01ca, 0x01f6 - }; - static const u16 limited_range_coeff[] = { - 0x0021, 0x0040, 0x000d, - 0x01ed, 0x01db, 0x0038, - 0x0038, 0x01d1, 0x01f7, - }; - unsigned int i; - - if (full_range) { - for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++) - rkisp1_write(params->rkisp1, full_range_coeff[i], - RKISP1_CIF_ISP_CC_COEFF_0 + i * 4); - - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | - RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); - } else { - for (i = 0; i < ARRAY_SIZE(limited_range_coeff); i++) - rkisp1_write(params->rkisp1, limited_range_coeff[i], - RKISP1_CIF_ISP_CC_COEFF_0 + i * 4); - - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA | - RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA); - } -} - -/* ISP De-noise Pre-Filter(DPF) function */ -static void rkisp1_dpf_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_dpf_config *arg) -{ - unsigned int isp_dpf_mode, spatial_coeff, i; - - switch (arg->gain.mode) { - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS: - isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | - RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; - break; - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS: - isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; - break; - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS: - isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN | - RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP | - RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP; - break; - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS: - isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; - break; - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS: - isp_dpf_mode = RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP | - RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP; - break; - case RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED: - default: - isp_dpf_mode = 0; - break; - } - - if (arg->nll.scale_mode == RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_NLL_SEGMENTATION; - if (arg->rb_flt.fltsize == RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9; - if (!arg->rb_flt.r_enable) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_R_FLT_DIS; - if (!arg->rb_flt.b_enable) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_B_FLT_DIS; - if (!arg->g_flt.gb_enable) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GB_FLT_DIS; - if (!arg->g_flt.gr_enable) - isp_dpf_mode |= RKISP1_CIF_ISP_DPF_MODE_GR_FLT_DIS; - - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_DPF_MODE, - isp_dpf_mode); - rkisp1_write(params->rkisp1, arg->gain.nf_b_gain, - RKISP1_CIF_ISP_DPF_NF_GAIN_B); - rkisp1_write(params->rkisp1, arg->gain.nf_r_gain, - RKISP1_CIF_ISP_DPF_NF_GAIN_R); - rkisp1_write(params->rkisp1, arg->gain.nf_gb_gain, - RKISP1_CIF_ISP_DPF_NF_GAIN_GB); - rkisp1_write(params->rkisp1, arg->gain.nf_gr_gain, - RKISP1_CIF_ISP_DPF_NF_GAIN_GR); - - for (i = 0; i < RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS; i++) { - rkisp1_write(params->rkisp1, arg->nll.coeff[i], - RKISP1_CIF_ISP_DPF_NULL_COEFF_0 + i * 4); - } - - spatial_coeff = arg->g_flt.spatial_coeff[0] | - (arg->g_flt.spatial_coeff[1] << 8) | - (arg->g_flt.spatial_coeff[2] << 16) | - (arg->g_flt.spatial_coeff[3] << 24); - rkisp1_write(params->rkisp1, spatial_coeff, - RKISP1_CIF_ISP_DPF_S_WEIGHT_G_1_4); - - spatial_coeff = arg->g_flt.spatial_coeff[4] | - (arg->g_flt.spatial_coeff[5] << 8); - rkisp1_write(params->rkisp1, spatial_coeff, - RKISP1_CIF_ISP_DPF_S_WEIGHT_G_5_6); - - spatial_coeff = arg->rb_flt.spatial_coeff[0] | - (arg->rb_flt.spatial_coeff[1] << 8) | - (arg->rb_flt.spatial_coeff[2] << 16) | - (arg->rb_flt.spatial_coeff[3] << 24); - rkisp1_write(params->rkisp1, spatial_coeff, - RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_1_4); - - spatial_coeff = arg->rb_flt.spatial_coeff[4] | - (arg->rb_flt.spatial_coeff[5] << 8); - rkisp1_write(params->rkisp1, spatial_coeff, - RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_5_6); -} - -static void -rkisp1_dpf_strength_config(struct rkisp1_params *params, - const struct rkisp1_cif_isp_dpf_strength_config *arg) -{ - rkisp1_write(params->rkisp1, arg->b, RKISP1_CIF_ISP_DPF_STRENGTH_B); - rkisp1_write(params->rkisp1, arg->g, RKISP1_CIF_ISP_DPF_STRENGTH_G); - rkisp1_write(params->rkisp1, arg->r, RKISP1_CIF_ISP_DPF_STRENGTH_R); -} - -static void -rkisp1_isp_isr_other_config(struct rkisp1_params *params, - const struct rkisp1_params_cfg *new_params) -{ - unsigned int module_en_update, module_cfg_update, module_ens; - - module_en_update = new_params->module_en_update; - module_cfg_update = new_params->module_cfg_update; - module_ens = new_params->module_ens; - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPCC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC)) { - /*update dpc config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPCC) - rkisp1_dpcc_config(params, - &new_params->others.dpcc_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_DPCC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_DPCC) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_DPCC_MODE, - RKISP1_CIF_ISP_DPCC_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_DPCC_MODE, - RKISP1_CIF_ISP_DPCC_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_BLS) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_BLS)) { - /* update bls config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BLS) - rkisp1_bls_config(params, - &new_params->others.bls_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_BLS) { - if (module_ens & RKISP1_CIF_ISP_MODULE_BLS) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_BLS_CTRL, - RKISP1_CIF_ISP_BLS_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_BLS_CTRL, - RKISP1_CIF_ISP_BLS_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_SDG) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_SDG)) { - /* update sdg config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_SDG) - rkisp1_sdg_config(params, - &new_params->others.sdg_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_SDG) { - if (module_ens & RKISP1_CIF_ISP_MODULE_SDG) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_LSC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_LSC)) { - /* update lsc config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_LSC) - rkisp1_lsc_config(params, - &new_params->others.lsc_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_LSC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_LSC) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN)) { - /* update awb gains */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) - rkisp1_awb_gain_config(params, - &new_params->others.awb_gain_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB_GAIN) { - if (module_ens & RKISP1_CIF_ISP_MODULE_AWB_GAIN) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_BDM) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_BDM)) { - /* update bdm config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_BDM) - rkisp1_bdm_config(params, - &new_params->others.bdm_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_BDM) { - if (module_ens & RKISP1_CIF_ISP_MODULE_BDM) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_DEMOSAIC, - RKISP1_CIF_ISP_DEMOSAIC_BYPASS); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_DEMOSAIC, - RKISP1_CIF_ISP_DEMOSAIC_BYPASS); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_FLT) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_FLT)) { - /* update filter config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_FLT) - rkisp1_flt_config(params, - &new_params->others.flt_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_FLT) { - if (module_ens & RKISP1_CIF_ISP_MODULE_FLT) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_FILT_MODE, - RKISP1_CIF_ISP_FLT_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_FILT_MODE, - RKISP1_CIF_ISP_FLT_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_CTK) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_CTK)) { - /* update ctk config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CTK) - rkisp1_ctk_config(params, - &new_params->others.ctk_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_CTK) - rkisp1_ctk_enable(params, - !!(module_ens & RKISP1_CIF_ISP_MODULE_CTK)); - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_GOC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_GOC)) { - /* update goc config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_GOC) - rkisp1_goc_config(params, - &new_params->others.goc_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_GOC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_GOC) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_CPROC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_CPROC)) { - /* update cproc config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_CPROC) { - rkisp1_cproc_config(params, - &new_params->others.cproc_config); - } - - if (module_en_update & RKISP1_CIF_ISP_MODULE_CPROC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_CPROC) - rkisp1_param_set_bits(params, - RKISP1_CIF_C_PROC_CTRL, - RKISP1_CIF_C_PROC_CTR_ENABLE); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_C_PROC_CTRL, - RKISP1_CIF_C_PROC_CTR_ENABLE); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_IE) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_IE)) { - /* update ie config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_IE) - rkisp1_ie_config(params, - &new_params->others.ie_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_IE) - rkisp1_ie_enable(params, - !!(module_ens & RKISP1_CIF_ISP_MODULE_IE)); - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPF) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF)) { - /* update dpf config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF) - rkisp1_dpf_config(params, - &new_params->others.dpf_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_DPF) { - if (module_ens & RKISP1_CIF_ISP_MODULE_DPF) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_DPF_MODE, - RKISP1_CIF_ISP_DPF_MODE_EN); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_DPF_MODE, - RKISP1_CIF_ISP_DPF_MODE_EN); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_DPF_STRENGTH)) { - /* update dpf strength config */ - rkisp1_dpf_strength_config(params, - &new_params->others.dpf_strength_config); - } -} - -static void rkisp1_isp_isr_meas_config(struct rkisp1_params *params, - struct rkisp1_params_cfg *new_params) -{ - unsigned int module_en_update, module_cfg_update, module_ens; - - module_en_update = new_params->module_en_update; - module_cfg_update = new_params->module_cfg_update; - module_ens = new_params->module_ens; - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_AWB) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB)) { - /* update awb config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AWB) - rkisp1_awb_meas_config(params, - &new_params->meas.awb_meas_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_AWB) - rkisp1_awb_meas_enable(params, - &new_params->meas.awb_meas_config, - !!(module_ens & RKISP1_CIF_ISP_MODULE_AWB)); - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_AFC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_AFC)) { - /* update afc config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AFC) - rkisp1_afm_config(params, - &new_params->meas.afc_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_AFC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_AFC) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_AFM_CTRL, - RKISP1_CIF_ISP_AFM_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_AFM_CTRL, - RKISP1_CIF_ISP_AFM_ENA); - } - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_HST) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_HST)) { - /* update hst config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_HST) - rkisp1_hst_config(params, - &new_params->meas.hst_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_HST) - rkisp1_hst_enable(params, - &new_params->meas.hst_config, - !!(module_ens & RKISP1_CIF_ISP_MODULE_HST)); - } - - if ((module_en_update & RKISP1_CIF_ISP_MODULE_AEC) || - (module_cfg_update & RKISP1_CIF_ISP_MODULE_AEC)) { - /* update aec config */ - if (module_cfg_update & RKISP1_CIF_ISP_MODULE_AEC) - rkisp1_aec_config(params, - &new_params->meas.aec_config); - - if (module_en_update & RKISP1_CIF_ISP_MODULE_AEC) { - if (module_ens & RKISP1_CIF_ISP_MODULE_AEC) - rkisp1_param_set_bits(params, - RKISP1_CIF_ISP_EXP_CTRL, - RKISP1_CIF_ISP_EXP_ENA); - else - rkisp1_param_clear_bits(params, - RKISP1_CIF_ISP_EXP_CTRL, - RKISP1_CIF_ISP_EXP_ENA); - } - } -} - -static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params, - unsigned int frame_sequence) -{ - struct rkisp1_params_cfg *new_params; - struct rkisp1_buffer *cur_buf = NULL; - - if (list_empty(¶ms->params)) - return; - - cur_buf = list_first_entry(¶ms->params, - struct rkisp1_buffer, queue); - - new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr); - - rkisp1_isp_isr_other_config(params, new_params); - rkisp1_isp_isr_meas_config(params, new_params); - - /* update shadow register immediately */ - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_CTRL, RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD); - - list_del(&cur_buf->queue); - - cur_buf->vb.sequence = frame_sequence; - vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); -} - -void rkisp1_params_isr(struct rkisp1_device *rkisp1) -{ - /* - * This isr is called when the ISR finishes processing a frame (RKISP1_CIF_ISP_FRAME). - * Configurations performed here will be applied on the next frame. - * Since frame_sequence is updated on the vertical sync signal, we should use - * frame_sequence + 1 here to indicate to userspace on which frame these parameters - * are being applied. - */ - unsigned int frame_sequence = rkisp1->isp.frame_sequence + 1; - struct rkisp1_params *params = &rkisp1->params; - - spin_lock(¶ms->config_lock); - rkisp1_params_apply_params_cfg(params, frame_sequence); - - spin_unlock(¶ms->config_lock); -} - -static const struct rkisp1_cif_isp_awb_meas_config rkisp1_awb_params_default_config = { - { - 0, 0, RKISP1_DEFAULT_WIDTH, RKISP1_DEFAULT_HEIGHT - }, - RKISP1_CIF_ISP_AWB_MODE_YCBCR, 200, 30, 20, 20, 0, 128, 128 -}; - -static const struct rkisp1_cif_isp_aec_config rkisp1_aec_params_default_config = { - RKISP1_CIF_ISP_EXP_MEASURING_MODE_0, - RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0, - { - RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, - RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 - } -}; - -static const struct rkisp1_cif_isp_hst_config rkisp1_hst_params_default_config = { - RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED, - 3, - { - RKISP1_DEFAULT_WIDTH >> 2, RKISP1_DEFAULT_HEIGHT >> 2, - RKISP1_DEFAULT_WIDTH >> 1, RKISP1_DEFAULT_HEIGHT >> 1 - }, - { - 0, /* To be filled in with 0x01 at runtime. */ - } -}; - -static const struct rkisp1_cif_isp_afc_config rkisp1_afc_params_default_config = { - 1, - { - { - 300, 225, 200, 150 - } - }, - 4, - 14 -}; - -static void rkisp1_params_config_parameter(struct rkisp1_params *params) -{ - struct rkisp1_cif_isp_hst_config hst = rkisp1_hst_params_default_config; - - rkisp1_awb_meas_config(params, &rkisp1_awb_params_default_config); - rkisp1_awb_meas_enable(params, &rkisp1_awb_params_default_config, - true); - - rkisp1_aec_config(params, &rkisp1_aec_params_default_config); - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_EXP_CTRL, - RKISP1_CIF_ISP_EXP_ENA); - - rkisp1_afm_config(params, &rkisp1_afc_params_default_config); - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_AFM_CTRL, - RKISP1_CIF_ISP_AFM_ENA); - - memset(hst.hist_weight, 0x01, sizeof(hst.hist_weight)); - rkisp1_hst_config(params, &hst); - rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP, - ~RKISP1_CIF_ISP_HIST_PROP_MODE_MASK | - rkisp1_hst_params_default_config.mode); - - /* set the range */ - if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) - rkisp1_csm_config(params, true); - else - rkisp1_csm_config(params, false); - - spin_lock_irq(¶ms->config_lock); - - /* apply the first buffer if there is one already */ - rkisp1_params_apply_params_cfg(params, 0); - - spin_unlock_irq(¶ms->config_lock); -} - -void rkisp1_params_configure(struct rkisp1_params *params, - enum rkisp1_fmt_raw_pat_type bayer_pat, - enum v4l2_quantization quantization) -{ - params->quantization = quantization; - params->raw_type = bayer_pat; - rkisp1_params_config_parameter(params); -} - -/* Not called when the camera active, thus not isr protection. */ -void rkisp1_params_disable(struct rkisp1_params *params) -{ - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPCC_MODE, - RKISP1_CIF_ISP_DPCC_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_LSC_CTRL, - RKISP1_CIF_ISP_LSC_CTRL_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_BLS_CTRL, - RKISP1_CIF_ISP_BLS_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DEMOSAIC, - RKISP1_CIF_ISP_DEMOSAIC_BYPASS); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_FILT_MODE, - RKISP1_CIF_ISP_FLT_ENA); - rkisp1_awb_meas_enable(params, NULL, false); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_CTRL, - RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_EXP_CTRL, - RKISP1_CIF_ISP_EXP_ENA); - rkisp1_ctk_enable(params, false); - rkisp1_param_clear_bits(params, RKISP1_CIF_C_PROC_CTRL, - RKISP1_CIF_C_PROC_CTR_ENABLE); - rkisp1_hst_enable(params, NULL, false); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_AFM_CTRL, - RKISP1_CIF_ISP_AFM_ENA); - rkisp1_ie_enable(params, false); - rkisp1_param_clear_bits(params, RKISP1_CIF_ISP_DPF_MODE, - RKISP1_CIF_ISP_DPF_MODE_EN); -} - -static int rkisp1_params_enum_fmt_meta_out(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct video_device *video = video_devdata(file); - struct rkisp1_params *params = video_get_drvdata(video); - - if (f->index > 0 || f->type != video->queue->type) - return -EINVAL; - - f->pixelformat = params->vdev_fmt.fmt.meta.dataformat; - - return 0; -} - -static int rkisp1_params_g_fmt_meta_out(struct file *file, void *fh, - struct v4l2_format *f) -{ - struct video_device *video = video_devdata(file); - struct rkisp1_params *params = video_get_drvdata(video); - struct v4l2_meta_format *meta = &f->fmt.meta; - - if (f->type != video->queue->type) - return -EINVAL; - - memset(meta, 0, sizeof(*meta)); - meta->dataformat = params->vdev_fmt.fmt.meta.dataformat; - meta->buffersize = params->vdev_fmt.fmt.meta.buffersize; - - return 0; -} - -static int rkisp1_params_querycap(struct file *file, - void *priv, struct v4l2_capability *cap) -{ - struct video_device *vdev = video_devdata(file); - - strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); - strscpy(cap->card, vdev->name, sizeof(cap->card)); - strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); - - return 0; -} - -/* ISP params video device IOCTLs */ -static const struct v4l2_ioctl_ops rkisp1_params_ioctl = { - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_enum_fmt_meta_out = rkisp1_params_enum_fmt_meta_out, - .vidioc_g_fmt_meta_out = rkisp1_params_g_fmt_meta_out, - .vidioc_s_fmt_meta_out = rkisp1_params_g_fmt_meta_out, - .vidioc_try_fmt_meta_out = rkisp1_params_g_fmt_meta_out, - .vidioc_querycap = rkisp1_params_querycap, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static int rkisp1_params_vb2_queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, - unsigned int *num_planes, - unsigned int sizes[], - struct device *alloc_devs[]) -{ - *num_buffers = clamp_t(u32, *num_buffers, - RKISP1_ISP_PARAMS_REQ_BUFS_MIN, - RKISP1_ISP_PARAMS_REQ_BUFS_MAX); - - *num_planes = 1; - - sizes[0] = sizeof(struct rkisp1_params_cfg); - - return 0; -} - -static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkisp1_buffer *params_buf = - container_of(vbuf, struct rkisp1_buffer, vb); - struct vb2_queue *vq = vb->vb2_queue; - struct rkisp1_params *params = vq->drv_priv; - - params_buf->vaddr = vb2_plane_vaddr(vb, 0); - spin_lock_irq(¶ms->config_lock); - list_add_tail(¶ms_buf->queue, ¶ms->params); - spin_unlock_irq(¶ms->config_lock); -} - -static int rkisp1_params_vb2_buf_prepare(struct vb2_buffer *vb) -{ - if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_params_cfg)) - return -EINVAL; - - vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_params_cfg)); - - return 0; -} - -static void rkisp1_params_vb2_stop_streaming(struct vb2_queue *vq) -{ - struct rkisp1_params *params = vq->drv_priv; - struct rkisp1_buffer *buf; - LIST_HEAD(tmp_list); - - /* - * we first move the buffers into a local list 'tmp_list' - * and then we can iterate it and call vb2_buffer_done - * without holding the lock - */ - spin_lock_irq(¶ms->config_lock); - list_splice_init(¶ms->params, &tmp_list); - spin_unlock_irq(¶ms->config_lock); - - list_for_each_entry(buf, &tmp_list, queue) - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); -} - -static struct vb2_ops rkisp1_params_vb2_ops = { - .queue_setup = rkisp1_params_vb2_queue_setup, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .buf_queue = rkisp1_params_vb2_buf_queue, - .buf_prepare = rkisp1_params_vb2_buf_prepare, - .stop_streaming = rkisp1_params_vb2_stop_streaming, - -}; - -static struct v4l2_file_operations rkisp1_params_fops = { - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, - .poll = vb2_fop_poll, - .open = v4l2_fh_open, - .release = vb2_fop_release -}; - -static int rkisp1_params_init_vb2_queue(struct vb2_queue *q, - struct rkisp1_params *params) -{ - struct rkisp1_vdev_node *node; - - node = container_of(q, struct rkisp1_vdev_node, buf_queue); - - q->type = V4L2_BUF_TYPE_META_OUTPUT; - q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - q->drv_priv = params; - q->ops = &rkisp1_params_vb2_ops; - q->mem_ops = &vb2_vmalloc_memops; - q->buf_struct_size = sizeof(struct rkisp1_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; - - return vb2_queue_init(q); -} - -static void rkisp1_init_params(struct rkisp1_params *params) -{ - params->vdev_fmt.fmt.meta.dataformat = - V4L2_META_FMT_RK_ISP1_PARAMS; - params->vdev_fmt.fmt.meta.buffersize = - sizeof(struct rkisp1_params_cfg); -} - -int rkisp1_params_register(struct rkisp1_device *rkisp1) -{ - struct rkisp1_params *params = &rkisp1->params; - struct rkisp1_vdev_node *node = ¶ms->vnode; - struct video_device *vdev = &node->vdev; - int ret; - - params->rkisp1 = rkisp1; - mutex_init(&node->vlock); - INIT_LIST_HEAD(¶ms->params); - spin_lock_init(¶ms->config_lock); - - strscpy(vdev->name, RKISP1_PARAMS_DEV_NAME, sizeof(vdev->name)); - - video_set_drvdata(vdev, params); - vdev->ioctl_ops = &rkisp1_params_ioctl; - vdev->fops = &rkisp1_params_fops; - vdev->release = video_device_release_empty; - /* - * Provide a mutex to v4l2 core. It will be used - * to protect all fops and v4l2 ioctls. - */ - vdev->lock = &node->vlock; - vdev->v4l2_dev = &rkisp1->v4l2_dev; - vdev->queue = &node->buf_queue; - vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; - vdev->vfl_dir = VFL_DIR_TX; - rkisp1_params_init_vb2_queue(vdev->queue, params); - rkisp1_init_params(params); - video_set_drvdata(vdev, params); - - node->pad.flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); - if (ret) - return ret; - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret) { - dev_err(rkisp1->dev, - "failed to register %s, ret=%d\n", vdev->name, ret); - goto err_cleanup_media_entity; - } - return 0; -err_cleanup_media_entity: - media_entity_cleanup(&vdev->entity); - return ret; -} - -void rkisp1_params_unregister(struct rkisp1_device *rkisp1) -{ - struct rkisp1_params *params = &rkisp1->params; - struct rkisp1_vdev_node *node = ¶ms->vnode; - struct video_device *vdev = &node->vdev; - - vb2_video_unregister_device(vdev); - media_entity_cleanup(&vdev->entity); -} diff --git a/drivers/staging/media/rkisp1/rkisp1-regs.h b/drivers/staging/media/rkisp1/rkisp1-regs.h deleted file mode 100644 index 049f6c3a11df..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-regs.h +++ /dev/null @@ -1,1262 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ -/* - * Rockchip ISP1 Driver - Registers header - * - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#ifndef _RKISP1_REGS_H -#define _RKISP1_REGS_H - -/* ISP_CTRL */ -#define RKISP1_CIF_ISP_CTRL_ISP_ENABLE BIT(0) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT (0 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU656 BIT(1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_ITU601 (2 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601 (3 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_DATA_MODE (4 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656 (5 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656 (6 << 1) -#define RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE BIT(4) -#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_IN_ENA BIT(6) -#define RKISP1_CIF_ISP_CTRL_ISP_AWB_ENA BIT(7) -#define RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT BIT(8) -#define RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD BIT(9) -#define RKISP1_CIF_ISP_CTRL_ISP_GEN_CFG_UPD BIT(10) -#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA BIT(11) -#define RKISP1_CIF_ISP_CTRL_ISP_FLASH_MODE_ENA BIT(12) -#define RKISP1_CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA BIT(13) -#define RKISP1_CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA BIT(14) - -/* ISP_ACQ_PROP */ -#define RKISP1_CIF_ISP_ACQ_PROP_POS_EDGE BIT(0) -#define RKISP1_CIF_ISP_ACQ_PROP_HSYNC_LOW BIT(1) -#define RKISP1_CIF_ISP_ACQ_PROP_VSYNC_LOW BIT(2) -#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB (0 << 3) -#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG BIT(3) -#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG (2 << 3) -#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR (3 << 3) -#define RKISP1_CIF_ISP_ACQ_PROP_BAYER_PAT(pat) ((pat) << 3) -#define RKISP1_CIF_ISP_ACQ_PROP_YCBYCR (0 << 7) -#define RKISP1_CIF_ISP_ACQ_PROP_YCRYCB BIT(7) -#define RKISP1_CIF_ISP_ACQ_PROP_CBYCRY (2 << 7) -#define RKISP1_CIF_ISP_ACQ_PROP_CRYCBY (3 << 7) -#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ALL (0 << 9) -#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN BIT(9) -#define RKISP1_CIF_ISP_ACQ_PROP_FIELD_SEL_ODD (2 << 9) -#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_12B (0 << 12) -#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO BIT(12) -#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB (2 << 12) -#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO (3 << 12) -#define RKISP1_CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB (4 << 12) - -/* VI_DPCL */ -#define RKISP1_CIF_VI_DPCL_DMA_JPEG (0 << 0) -#define RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI BIT(0) -#define RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_JPEG (2 << 0) -#define RKISP1_CIF_VI_DPCL_CHAN_MODE_MP BIT(2) -#define RKISP1_CIF_VI_DPCL_CHAN_MODE_SP (2 << 2) -#define RKISP1_CIF_VI_DPCL_CHAN_MODE_MPSP (3 << 2) -#define RKISP1_CIF_VI_DPCL_DMA_SW_SPMUX (0 << 4) -#define RKISP1_CIF_VI_DPCL_DMA_SW_SI BIT(4) -#define RKISP1_CIF_VI_DPCL_DMA_SW_IE (2 << 4) -#define RKISP1_CIF_VI_DPCL_DMA_SW_JPEG (3 << 4) -#define RKISP1_CIF_VI_DPCL_DMA_SW_ISP (4 << 4) -#define RKISP1_CIF_VI_DPCL_IF_SEL_PARALLEL (0 << 8) -#define RKISP1_CIF_VI_DPCL_IF_SEL_SMIA BIT(8) -#define RKISP1_CIF_VI_DPCL_IF_SEL_MIPI (2 << 8) -#define RKISP1_CIF_VI_DPCL_DMA_IE_MUX_DMA BIT(10) -#define RKISP1_CIF_VI_DPCL_DMA_SP_MUX_DMA BIT(11) - -/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */ -#define RKISP1_CIF_ISP_OFF BIT(0) -#define RKISP1_CIF_ISP_FRAME BIT(1) -#define RKISP1_CIF_ISP_DATA_LOSS BIT(2) -#define RKISP1_CIF_ISP_PIC_SIZE_ERROR BIT(3) -#define RKISP1_CIF_ISP_AWB_DONE BIT(4) -#define RKISP1_CIF_ISP_FRAME_IN BIT(5) -#define RKISP1_CIF_ISP_V_START BIT(6) -#define RKISP1_CIF_ISP_H_START BIT(7) -#define RKISP1_CIF_ISP_FLASH_ON BIT(8) -#define RKISP1_CIF_ISP_FLASH_OFF BIT(9) -#define RKISP1_CIF_ISP_SHUTTER_ON BIT(10) -#define RKISP1_CIF_ISP_SHUTTER_OFF BIT(11) -#define RKISP1_CIF_ISP_AFM_SUM_OF BIT(12) -#define RKISP1_CIF_ISP_AFM_LUM_OF BIT(13) -#define RKISP1_CIF_ISP_AFM_FIN BIT(14) -#define RKISP1_CIF_ISP_HIST_MEASURE_RDY BIT(15) -#define RKISP1_CIF_ISP_FLASH_CAP BIT(17) -#define RKISP1_CIF_ISP_EXP_END BIT(18) -#define RKISP1_CIF_ISP_VSM_END BIT(19) - -/* ISP_ERR */ -#define RKISP1_CIF_ISP_ERR_INFORM_SIZE BIT(0) -#define RKISP1_CIF_ISP_ERR_IS_SIZE BIT(1) -#define RKISP1_CIF_ISP_ERR_OUTFORM_SIZE BIT(2) - -/* MI_CTRL */ -#define RKISP1_CIF_MI_CTRL_MP_ENABLE BIT(0) -#define RKISP1_CIF_MI_CTRL_SP_ENABLE (2 << 0) -#define RKISP1_CIF_MI_CTRL_JPEG_ENABLE (4 << 0) -#define RKISP1_CIF_MI_CTRL_RAW_ENABLE (8 << 0) -#define RKISP1_CIF_MI_CTRL_HFLIP BIT(4) -#define RKISP1_CIF_MI_CTRL_VFLIP BIT(5) -#define RKISP1_CIF_MI_CTRL_ROT BIT(6) -#define RKISP1_CIF_MI_BYTE_SWAP BIT(7) -#define RKISP1_CIF_MI_SP_Y_FULL_YUV2RGB BIT(8) -#define RKISP1_CIF_MI_SP_CBCR_FULL_YUV2RGB BIT(9) -#define RKISP1_CIF_MI_SP_422NONCOSITEED BIT(10) -#define RKISP1_CIF_MI_MP_PINGPONG_ENABEL BIT(11) -#define RKISP1_CIF_MI_SP_PINGPONG_ENABEL BIT(12) -#define RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE BIT(13) -#define RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE BIT(14) -#define RKISP1_CIF_MI_LAST_PIXEL_SIG_ENABLE BIT(15) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_16 (0 << 16) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_32 BIT(16) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64 (2 << 16) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_16 (0 << 18) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_32 BIT(18) -#define RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64 (2 << 18) -#define RKISP1_CIF_MI_CTRL_INIT_BASE_EN BIT(20) -#define RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN BIT(21) -#define RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8 (0 << 22) -#define RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA BIT(22) -#define RKISP1_MI_CTRL_MP_WRITE_YUVINT (2 << 22) -#define RKISP1_MI_CTRL_MP_WRITE_RAW12 (2 << 22) -#define RKISP1_MI_CTRL_SP_WRITE_PLA (0 << 24) -#define RKISP1_MI_CTRL_SP_WRITE_SPLA BIT(24) -#define RKISP1_MI_CTRL_SP_WRITE_INT (2 << 24) -#define RKISP1_MI_CTRL_SP_INPUT_YUV400 (0 << 26) -#define RKISP1_MI_CTRL_SP_INPUT_YUV420 BIT(26) -#define RKISP1_MI_CTRL_SP_INPUT_YUV422 (2 << 26) -#define RKISP1_MI_CTRL_SP_INPUT_YUV444 (3 << 26) -#define RKISP1_MI_CTRL_SP_OUTPUT_YUV400 (0 << 28) -#define RKISP1_MI_CTRL_SP_OUTPUT_YUV420 BIT(28) -#define RKISP1_MI_CTRL_SP_OUTPUT_YUV422 (2 << 28) -#define RKISP1_MI_CTRL_SP_OUTPUT_YUV444 (3 << 28) -#define RKISP1_MI_CTRL_SP_OUTPUT_RGB565 (4 << 28) -#define RKISP1_MI_CTRL_SP_OUTPUT_RGB666 (5 << 28) -#define RKISP1_MI_CTRL_SP_OUTPUT_RGB888 (6 << 28) - -#define RKISP1_MI_CTRL_MP_FMT_MASK GENMASK(23, 22) -#define RKISP1_MI_CTRL_SP_FMT_MASK GENMASK(30, 24) - -/* MI_INIT */ -#define RKISP1_CIF_MI_INIT_SKIP BIT(2) -#define RKISP1_CIF_MI_INIT_SOFT_UPD BIT(4) - -/* MI_CTRL_SHD */ -#define RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED BIT(0) -#define RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED BIT(1) -#define RKISP1_CIF_MI_CTRL_SHD_JPEG_IN_ENABLED BIT(2) -#define RKISP1_CIF_MI_CTRL_SHD_RAW_IN_ENABLED BIT(3) -#define RKISP1_CIF_MI_CTRL_SHD_MP_OUT_ENABLED BIT(16) -#define RKISP1_CIF_MI_CTRL_SHD_SP_OUT_ENABLED BIT(17) -#define RKISP1_CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED BIT(18) -#define RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED BIT(19) - -/* RSZ_CTRL */ -#define RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE BIT(0) -#define RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE BIT(1) -#define RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE BIT(2) -#define RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE BIT(3) -#define RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP BIT(4) -#define RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP BIT(5) -#define RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP BIT(6) -#define RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP BIT(7) -#define RKISP1_CIF_RSZ_CTRL_CFG_UPD BIT(8) -#define RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO BIT(9) -#define RKISP1_CIF_RSZ_SCALER_FACTOR BIT(16) - -/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */ -#define RKISP1_CIF_MI_FRAME(stream) BIT((stream)->id) -#define RKISP1_CIF_MI_MBLK_LINE BIT(2) -#define RKISP1_CIF_MI_FILL_MP_Y BIT(3) -#define RKISP1_CIF_MI_WRAP_MP_Y BIT(4) -#define RKISP1_CIF_MI_WRAP_MP_CB BIT(5) -#define RKISP1_CIF_MI_WRAP_MP_CR BIT(6) -#define RKISP1_CIF_MI_WRAP_SP_Y BIT(7) -#define RKISP1_CIF_MI_WRAP_SP_CB BIT(8) -#define RKISP1_CIF_MI_WRAP_SP_CR BIT(9) -#define RKISP1_CIF_MI_DMA_READY BIT(11) - -/* MI_STATUS */ -#define RKISP1_CIF_MI_STATUS_MP_Y_FIFO_FULL BIT(0) -#define RKISP1_CIF_MI_STATUS_SP_Y_FIFO_FULL BIT(4) - -/* MI_DMA_CTRL */ -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_16 (0 << 0) -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_32 BIT(0) -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_LUM_64 (2 << 0) -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16 (0 << 2) -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32 BIT(2) -#define RKISP1_CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64 (2 << 2) -#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_PLANAR (0 << 4) -#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_SPLANAR BIT(4) -#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV400 (0 << 6) -#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV420 BIT(6) -#define RKISP1_CIF_MI_DMA_CTRL_READ_FMT_PACKED (2 << 4) -#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV422 (2 << 6) -#define RKISP1_CIF_MI_DMA_CTRL_FMT_YUV444 (3 << 6) -#define RKISP1_CIF_MI_DMA_CTRL_BYTE_SWAP BIT(8) -#define RKISP1_CIF_MI_DMA_CTRL_CONTINUOUS_ENA BIT(9) -#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_NO (0 << 12) -#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_8BIT BIT(12) -#define RKISP1_CIF_MI_DMA_CTRL_RGB_BAYER_16BIT (2 << 12) -/* MI_DMA_START */ -#define RKISP1_CIF_MI_DMA_START_ENABLE BIT(0) -/* MI_XTD_FORMAT_CTRL */ -#define RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP BIT(0) -#define RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP BIT(1) -#define RKISP1_CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP BIT(2) - -/* CCL */ -#define RKISP1_CIF_CCL_CIF_CLK_DIS BIT(2) -/* ICCL */ -#define RKISP1_CIF_ICCL_ISP_CLK BIT(0) -#define RKISP1_CIF_ICCL_CP_CLK BIT(1) -#define RKISP1_CIF_ICCL_RES_2 BIT(2) -#define RKISP1_CIF_ICCL_MRSZ_CLK BIT(3) -#define RKISP1_CIF_ICCL_SRSZ_CLK BIT(4) -#define RKISP1_CIF_ICCL_JPEG_CLK BIT(5) -#define RKISP1_CIF_ICCL_MI_CLK BIT(6) -#define RKISP1_CIF_ICCL_RES_7 BIT(7) -#define RKISP1_CIF_ICCL_IE_CLK BIT(8) -#define RKISP1_CIF_ICCL_SIMP_CLK BIT(9) -#define RKISP1_CIF_ICCL_SMIA_CLK BIT(10) -#define RKISP1_CIF_ICCL_MIPI_CLK BIT(11) -#define RKISP1_CIF_ICCL_DCROP_CLK BIT(12) -/* IRCL */ -#define RKISP1_CIF_IRCL_ISP_SW_RST BIT(0) -#define RKISP1_CIF_IRCL_CP_SW_RST BIT(1) -#define RKISP1_CIF_IRCL_YCS_SW_RST BIT(2) -#define RKISP1_CIF_IRCL_MRSZ_SW_RST BIT(3) -#define RKISP1_CIF_IRCL_SRSZ_SW_RST BIT(4) -#define RKISP1_CIF_IRCL_JPEG_SW_RST BIT(5) -#define RKISP1_CIF_IRCL_MI_SW_RST BIT(6) -#define RKISP1_CIF_IRCL_CIF_SW_RST BIT(7) -#define RKISP1_CIF_IRCL_IE_SW_RST BIT(8) -#define RKISP1_CIF_IRCL_SI_SW_RST BIT(9) -#define RKISP1_CIF_IRCL_MIPI_SW_RST BIT(11) - -/* C_PROC_CTR */ -#define RKISP1_CIF_C_PROC_CTR_ENABLE BIT(0) -#define RKISP1_CIF_C_PROC_YOUT_FULL BIT(1) -#define RKISP1_CIF_C_PROC_YIN_FULL BIT(2) -#define RKISP1_CIF_C_PROC_COUT_FULL BIT(3) -#define RKISP1_CIF_C_PROC_CTRL_RESERVED 0xFFFFFFFE -#define RKISP1_CIF_C_PROC_CONTRAST_RESERVED 0xFFFFFF00 -#define RKISP1_CIF_C_PROC_BRIGHTNESS_RESERVED 0xFFFFFF00 -#define RKISP1_CIF_C_PROC_HUE_RESERVED 0xFFFFFF00 -#define RKISP1_CIF_C_PROC_SATURATION_RESERVED 0xFFFFFF00 -#define RKISP1_CIF_C_PROC_MACC_RESERVED 0xE000E000 -#define RKISP1_CIF_C_PROC_TONE_RESERVED 0xF000 -/* DUAL_CROP_CTRL */ -#define RKISP1_CIF_DUAL_CROP_MP_MODE_BYPASS (0 << 0) -#define RKISP1_CIF_DUAL_CROP_MP_MODE_YUV BIT(0) -#define RKISP1_CIF_DUAL_CROP_MP_MODE_RAW (2 << 0) -#define RKISP1_CIF_DUAL_CROP_SP_MODE_BYPASS (0 << 2) -#define RKISP1_CIF_DUAL_CROP_SP_MODE_YUV BIT(2) -#define RKISP1_CIF_DUAL_CROP_SP_MODE_RAW (2 << 2) -#define RKISP1_CIF_DUAL_CROP_CFG_UPD_PERMANENT BIT(4) -#define RKISP1_CIF_DUAL_CROP_CFG_UPD BIT(5) -#define RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD BIT(6) - -/* IMG_EFF_CTRL */ -#define RKISP1_CIF_IMG_EFF_CTRL_ENABLE BIT(0) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE (0 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE BIT(1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA (2 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL (3 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS (4 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH (5 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SHARPEN (6 << 1) -#define RKISP1_CIF_IMG_EFF_CTRL_CFG_UPD BIT(4) -#define RKISP1_CIF_IMG_EFF_CTRL_YCBCR_FULL BIT(5) - -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT 0 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT 1 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT 2 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT 3 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT 4 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT 5 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT 6 -#define RKISP1_CIF_IMG_EFF_CTRL_MODE_MASK 0xE - -/* IMG_EFF_COLOR_SEL */ -#define RKISP1_CIF_IMG_EFF_COLOR_RGB 0 -#define RKISP1_CIF_IMG_EFF_COLOR_B BIT(0) -#define RKISP1_CIF_IMG_EFF_COLOR_G (2 << 0) -#define RKISP1_CIF_IMG_EFF_COLOR_GB (3 << 0) -#define RKISP1_CIF_IMG_EFF_COLOR_R (4 << 0) -#define RKISP1_CIF_IMG_EFF_COLOR_RB (5 << 0) -#define RKISP1_CIF_IMG_EFF_COLOR_RG (6 << 0) -#define RKISP1_CIF_IMG_EFF_COLOR_RGB2 (7 << 0) - -/* MIPI_CTRL */ -#define RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA BIT(0) -#define RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(a) (((a) & 0xF) << 8) -#define RKISP1_CIF_MIPI_CTRL_NUM_LANES(a) (((a) & 0x3) << 12) -#define RKISP1_CIF_MIPI_CTRL_ERR_SOT_HS_SKIP BIT(16) -#define RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP BIT(17) -#define RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA BIT(18) - -/* MIPI_DATA_SEL */ -#define RKISP1_CIF_MIPI_DATA_SEL_VC(a) (((a) & 0x3) << 6) -#define RKISP1_CIF_MIPI_DATA_SEL_DT(a) (((a) & 0x3F) << 0) -/* MIPI DATA_TYPE */ -#define RKISP1_CIF_CSI2_DT_YUV420_8b 0x18 -#define RKISP1_CIF_CSI2_DT_YUV420_10b 0x19 -#define RKISP1_CIF_CSI2_DT_YUV422_8b 0x1E -#define RKISP1_CIF_CSI2_DT_YUV422_10b 0x1F -#define RKISP1_CIF_CSI2_DT_RGB565 0x22 -#define RKISP1_CIF_CSI2_DT_RGB666 0x23 -#define RKISP1_CIF_CSI2_DT_RGB888 0x24 -#define RKISP1_CIF_CSI2_DT_RAW8 0x2A -#define RKISP1_CIF_CSI2_DT_RAW10 0x2B -#define RKISP1_CIF_CSI2_DT_RAW12 0x2C - -/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */ -#define RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(a) (((a) & 0xF) << 0) -#define RKISP1_CIF_MIPI_ERR_SOT(a) (((a) & 0xF) << 4) -#define RKISP1_CIF_MIPI_ERR_SOT_SYNC(a) (((a) & 0xF) << 8) -#define RKISP1_CIF_MIPI_ERR_EOT_SYNC(a) (((a) & 0xF) << 12) -#define RKISP1_CIF_MIPI_ERR_CTRL(a) (((a) & 0xF) << 16) -#define RKISP1_CIF_MIPI_ERR_PROTOCOL BIT(20) -#define RKISP1_CIF_MIPI_ERR_ECC1 BIT(21) -#define RKISP1_CIF_MIPI_ERR_ECC2 BIT(22) -#define RKISP1_CIF_MIPI_ERR_CS BIT(23) -#define RKISP1_CIF_MIPI_FRAME_END BIT(24) -#define RKISP1_CIF_MIPI_ADD_DATA_OVFLW BIT(25) -#define RKISP1_CIF_MIPI_ADD_DATA_WATER_MARK BIT(26) - -#define RKISP1_CIF_MIPI_ERR_CSI (RKISP1_CIF_MIPI_ERR_PROTOCOL | \ - RKISP1_CIF_MIPI_ERR_ECC1 | \ - RKISP1_CIF_MIPI_ERR_ECC2 | \ - RKISP1_CIF_MIPI_ERR_CS) - -#define RKISP1_CIF_MIPI_ERR_DPHY (RKISP1_CIF_MIPI_ERR_SOT(3) | \ - RKISP1_CIF_MIPI_ERR_SOT_SYNC(3) | \ - RKISP1_CIF_MIPI_ERR_EOT_SYNC(3) | \ - RKISP1_CIF_MIPI_ERR_CTRL(3)) - -/* SUPER_IMPOSE */ -#define RKISP1_CIF_SUPER_IMP_CTRL_NORMAL_MODE BIT(0) -#define RKISP1_CIF_SUPER_IMP_CTRL_REF_IMG_MEM BIT(1) -#define RKISP1_CIF_SUPER_IMP_CTRL_TRANSP_DIS BIT(2) - -/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */ -#define RKISP1_CIF_ISP_HIST_PROP_MODE_DIS (0 << 0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_RGB BIT(0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_RED (2 << 0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_GREEN (3 << 0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_BLUE (4 << 0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_LUM (5 << 0) -#define RKISP1_CIF_ISP_HIST_PROP_MODE_MASK 0x7 -#define RKISP1_CIF_ISP_HIST_PREDIV_SET(x) (((x) & 0x7F) << 3) -#define RKISP1_CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3) \ - (((v0) & 0x1F) | (((v1) & 0x1F) << 8) |\ - (((v2) & 0x1F) << 16) | \ - (((v3) & 0x1F) << 24)) - -#define RKISP1_CIF_ISP_HIST_WINDOW_OFFSET_RESERVED 0xFFFFF000 -#define RKISP1_CIF_ISP_HIST_WINDOW_SIZE_RESERVED 0xFFFFF800 -#define RKISP1_CIF_ISP_HIST_WEIGHT_RESERVED 0xE0E0E0E0 -#define RKISP1_CIF_ISP_MAX_HIST_PREDIVIDER 0x0000007F -#define RKISP1_CIF_ISP_HIST_ROW_NUM 5 -#define RKISP1_CIF_ISP_HIST_COLUMN_NUM 5 - -/* AUTO FOCUS MEASUREMENT: ISP_AFM_CTRL */ -#define RKISP1_ISP_AFM_CTRL_ENABLE BIT(0) - -/* SHUTTER CONTROL */ -#define RKISP1_CIF_ISP_SH_CTRL_SH_ENA BIT(0) -#define RKISP1_CIF_ISP_SH_CTRL_REP_EN BIT(1) -#define RKISP1_CIF_ISP_SH_CTRL_SRC_SH_TRIG BIT(2) -#define RKISP1_CIF_ISP_SH_CTRL_EDGE_POS BIT(3) -#define RKISP1_CIF_ISP_SH_CTRL_POL_LOW BIT(4) - -/* FLASH MODULE */ -/* ISP_FLASH_CMD */ -#define RKISP1_CIFFLASH_CMD_PRELIGHT_ON BIT(0) -#define RKISP1_CIFFLASH_CMD_FLASH_ON BIT(1) -#define RKISP1_CIFFLASH_CMD_PRE_FLASH_ON BIT(2) -/* ISP_FLASH_CONFIG */ -#define RKISP1_CIFFLASH_CONFIG_PRELIGHT_END BIT(0) -#define RKISP1_CIFFLASH_CONFIG_VSYNC_POS BIT(1) -#define RKISP1_CIFFLASH_CONFIG_PRELIGHT_LOW BIT(2) -#define RKISP1_CIFFLASH_CONFIG_SRC_FL_TRIG BIT(3) -#define RKISP1_CIFFLASH_CONFIG_DELAY(a) (((a) & 0xF) << 4) - -/* Demosaic: ISP_DEMOSAIC */ -#define RKISP1_CIF_ISP_DEMOSAIC_BYPASS BIT(10) -#define RKISP1_CIF_ISP_DEMOSAIC_TH(x) ((x) & 0xFF) - -/* AWB */ -/* ISP_AWB_PROP */ -#define RKISP1_CIF_ISP_AWB_YMAX_CMP_EN BIT(2) -#define RKISP1_CIF_ISP_AWB_YMAX_READ(x) (((x) >> 2) & 1) -#define RKISP1_CIF_ISP_AWB_MODE_RGB_EN ((1 << 31) | (0x2 << 0)) -#define RKISP1_CIF_ISP_AWB_MODE_YCBCR_EN ((0 << 31) | (0x2 << 0)) -#define RKISP1_CIF_ISP_AWB_MODE_MASK_NONE 0xFFFFFFFC -#define RKISP1_CIF_ISP_AWB_MODE_READ(x) ((x) & 3) -/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G */ -#define RKISP1_CIF_ISP_AWB_GAIN_R_SET(x) (((x) & 0x3FF) << 16) -#define RKISP1_CIF_ISP_AWB_GAIN_R_READ(x) (((x) >> 16) & 0x3FF) -#define RKISP1_CIF_ISP_AWB_GAIN_B_SET(x) ((x) & 0x3FFF) -#define RKISP1_CIF_ISP_AWB_GAIN_B_READ(x) ((x) & 0x3FFF) -/* ISP_AWB_REF */ -#define RKISP1_CIF_ISP_AWB_REF_CR_SET(x) (((x) & 0xFF) << 8) -#define RKISP1_CIF_ISP_AWB_REF_CR_READ(x) (((x) >> 8) & 0xFF) -#define RKISP1_CIF_ISP_AWB_REF_CB_READ(x) ((x) & 0xFF) -/* ISP_AWB_THRESH */ -#define RKISP1_CIF_ISP_AWB_MAX_CS_SET(x) (((x) & 0xFF) << 8) -#define RKISP1_CIF_ISP_AWB_MAX_CS_READ(x) (((x) >> 8) & 0xFF) -#define RKISP1_CIF_ISP_AWB_MIN_C_READ(x) ((x) & 0xFF) -#define RKISP1_CIF_ISP_AWB_MIN_Y_SET(x) (((x) & 0xFF) << 16) -#define RKISP1_CIF_ISP_AWB_MIN_Y_READ(x) (((x) >> 16) & 0xFF) -#define RKISP1_CIF_ISP_AWB_MAX_Y_SET(x) (((x) & 0xFF) << 24) -#define RKISP1_CIF_ISP_AWB_MAX_Y_READ(x) (((x) >> 24) & 0xFF) -/* ISP_AWB_MEAN */ -#define RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(x) ((x) & 0xFF) -#define RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(x) (((x) >> 8) & 0xFF) -#define RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(x) (((x) >> 16) & 0xFF) -/* ISP_AWB_WHITE_CNT */ -#define RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(x) ((x) & 0x3FFFFFF) - -#define RKISP1_CIF_ISP_AWB_GAINS_MAX_VAL 0x000003FF -#define RKISP1_CIF_ISP_AWB_WINDOW_OFFSET_MAX 0x00000FFF -#define RKISP1_CIF_ISP_AWB_WINDOW_MAX_SIZE 0x00001FFF -#define RKISP1_CIF_ISP_AWB_CBCR_MAX_REF 0x000000FF -#define RKISP1_CIF_ISP_AWB_THRES_MAX_YC 0x000000FF - -/* AE */ -/* ISP_EXP_CTRL */ -#define RKISP1_CIF_ISP_EXP_ENA BIT(0) -#define RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP BIT(1) -/* - *'1' luminance calculation according to Y=(R+G+B) x 0.332 (85/256) - *'0' luminance calculation according to Y=16+0.25R+0.5G+0.1094B - */ -#define RKISP1_CIF_ISP_EXP_CTRL_MEASMODE_1 BIT(31) - -/* ISP_EXP_H_SIZE */ -#define RKISP1_CIF_ISP_EXP_H_SIZE_SET(x) ((x) & 0x7FF) -#define RKISP1_CIF_ISP_EXP_HEIGHT_MASK 0x000007FF -/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */ -#define RKISP1_CIF_ISP_EXP_V_SIZE_SET(x) ((x) & 0x7FE) - -/* ISP_EXP_H_OFFSET */ -#define RKISP1_CIF_ISP_EXP_H_OFFSET_SET(x) ((x) & 0x1FFF) -#define RKISP1_CIF_ISP_EXP_MAX_HOFFS 2424 -/* ISP_EXP_V_OFFSET */ -#define RKISP1_CIF_ISP_EXP_V_OFFSET_SET(x) ((x) & 0x1FFF) -#define RKISP1_CIF_ISP_EXP_MAX_VOFFS 1806 - -#define RKISP1_CIF_ISP_EXP_ROW_NUM 5 -#define RKISP1_CIF_ISP_EXP_COLUMN_NUM 5 -#define RKISP1_CIF_ISP_EXP_NUM_LUMA_REGS \ - (RKISP1_CIF_ISP_EXP_ROW_NUM * RKISP1_CIF_ISP_EXP_COLUMN_NUM) -#define RKISP1_CIF_ISP_EXP_BLOCK_MAX_HSIZE 516 -#define RKISP1_CIF_ISP_EXP_BLOCK_MIN_HSIZE 35 -#define RKISP1_CIF_ISP_EXP_BLOCK_MAX_VSIZE 390 -#define RKISP1_CIF_ISP_EXP_BLOCK_MIN_VSIZE 28 -#define RKISP1_CIF_ISP_EXP_MAX_HSIZE \ - (RKISP1_CIF_ISP_EXP_BLOCK_MAX_HSIZE * RKISP1_CIF_ISP_EXP_COLUMN_NUM + 1) -#define RKISP1_CIF_ISP_EXP_MIN_HSIZE \ - (RKISP1_CIF_ISP_EXP_BLOCK_MIN_HSIZE * RKISP1_CIF_ISP_EXP_COLUMN_NUM + 1) -#define RKISP1_CIF_ISP_EXP_MAX_VSIZE \ - (RKISP1_CIF_ISP_EXP_BLOCK_MAX_VSIZE * RKISP1_CIF_ISP_EXP_ROW_NUM + 1) -#define RKISP1_CIF_ISP_EXP_MIN_VSIZE \ - (RKISP1_CIF_ISP_EXP_BLOCK_MIN_VSIZE * RKISP1_CIF_ISP_EXP_ROW_NUM + 1) - -/* LSC: ISP_LSC_CTRL */ -#define RKISP1_CIF_ISP_LSC_CTRL_ENA BIT(0) -#define RKISP1_CIF_ISP_LSC_SECT_SIZE_RESERVED 0xFC00FC00 -#define RKISP1_CIF_ISP_LSC_GRAD_RESERVED 0xF000F000 -#define RKISP1_CIF_ISP_LSC_SAMPLE_RESERVED 0xF000F000 -#define RKISP1_CIF_ISP_LSC_TABLE_DATA(v0, v1) \ - (((v0) & 0xFFF) | (((v1) & 0xFFF) << 12)) -#define RKISP1_CIF_ISP_LSC_SECT_SIZE(v0, v1) \ - (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16)) -#define RKISP1_CIF_ISP_LSC_GRAD_SIZE(v0, v1) \ - (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16)) - -/* LSC: ISP_LSC_TABLE_SEL */ -#define RKISP1_CIF_ISP_LSC_TABLE_0 0 -#define RKISP1_CIF_ISP_LSC_TABLE_1 1 - -/* LSC: ISP_LSC_STATUS */ -#define RKISP1_CIF_ISP_LSC_ACTIVE_TABLE BIT(1) -#define RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_0 0 -#define RKISP1_CIF_ISP_LSC_TABLE_ADDRESS_153 153 - -/* FLT */ -/* ISP_FILT_MODE */ -#define RKISP1_CIF_ISP_FLT_ENA BIT(0) - -/* - * 0: green filter static mode (active filter factor = FILT_FAC_MID) - * 1: dynamic noise reduction/sharpen Default - */ -#define RKISP1_CIF_ISP_FLT_MODE_DNR BIT(1) -#define RKISP1_CIF_ISP_FLT_MODE_MAX 1 -#define RKISP1_CIF_ISP_FLT_CHROMA_V_MODE(x) (((x) & 0x3) << 4) -#define RKISP1_CIF_ISP_FLT_CHROMA_H_MODE(x) (((x) & 0x3) << 6) -#define RKISP1_CIF_ISP_FLT_CHROMA_MODE_MAX 3 -#define RKISP1_CIF_ISP_FLT_GREEN_STAGE1(x) (((x) & 0xF) << 8) -#define RKISP1_CIF_ISP_FLT_GREEN_STAGE1_MAX 8 -#define RKISP1_CIF_ISP_FLT_THREAD_RESERVED 0xFFFFFC00 -#define RKISP1_CIF_ISP_FLT_FAC_RESERVED 0xFFFFFFC0 -#define RKISP1_CIF_ISP_FLT_LUM_WEIGHT_RESERVED 0xFFF80000 - -#define RKISP1_CIF_ISP_CTK_COEFF_RESERVED 0xFFFFF800 -#define RKISP1_CIF_ISP_XTALK_OFFSET_RESERVED 0xFFFFF000 - -/* GOC */ -#define RKISP1_CIF_ISP_GAMMA_OUT_MODE_EQU BIT(0) -#define RKISP1_CIF_ISP_GOC_MODE_MAX 1 -#define RKISP1_CIF_ISP_GOC_RESERVED 0xFFFFF800 -/* ISP_CTRL BIT 11*/ -#define RKISP1_CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x) (((x) >> 11) & 1) - -/* DPCC */ -/* ISP_DPCC_MODE */ -#define RKISP1_CIF_ISP_DPCC_ENA BIT(0) -#define RKISP1_CIF_ISP_DPCC_MODE_MAX 0x07 -#define RKISP1_CIF_ISP_DPCC_OUTPUTMODE_MAX 0x0F -#define RKISP1_CIF_ISP_DPCC_SETUSE_MAX 0x0F -#define RKISP1_CIF_ISP_DPCC_METHODS_SET_RESERVED 0xFFFFE000 -#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_RESERVED 0xFFFF0000 -#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED 0xFFFFC0C0 -#define RKISP1_CIF_ISP_DPCC_PG_FAC_RESERVED 0xFFFFC0C0 -#define RKISP1_CIF_ISP_DPCC_RND_THRESH_RESERVED 0xFFFF0000 -#define RKISP1_CIF_ISP_DPCC_RG_FAC_RESERVED 0xFFFFC0C0 -#define RKISP1_CIF_ISP_DPCC_RO_LIMIT_RESERVED 0xFFFFF000 -#define RKISP1_CIF_ISP_DPCC_RND_OFFS_RESERVED 0xFFFFF000 - -/* BLS */ -/* ISP_BLS_CTRL */ -#define RKISP1_CIF_ISP_BLS_ENA BIT(0) -#define RKISP1_CIF_ISP_BLS_MODE_MEASURED BIT(1) -#define RKISP1_CIF_ISP_BLS_MODE_FIXED 0 -#define RKISP1_CIF_ISP_BLS_WINDOW_1 BIT(2) -#define RKISP1_CIF_ISP_BLS_WINDOW_2 (2 << 2) - -/* GAMMA-IN */ -#define RKISP1_CIFISP_DEGAMMA_X_RESERVED \ - ((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\ - (1 << 15) | (1 << 11) | (1 << 7) | (1 << 3)) -#define RKISP1_CIFISP_DEGAMMA_Y_RESERVED 0xFFFFF000 - -/* AFM */ -#define RKISP1_CIF_ISP_AFM_ENA BIT(0) -#define RKISP1_CIF_ISP_AFM_THRES_RESERVED 0xFFFF0000 -#define RKISP1_CIF_ISP_AFM_VAR_SHIFT_RESERVED 0xFFF8FFF8 -#define RKISP1_CIF_ISP_AFM_WINDOW_X_RESERVED 0xE000 -#define RKISP1_CIF_ISP_AFM_WINDOW_Y_RESERVED 0xF000 -#define RKISP1_CIF_ISP_AFM_WINDOW_X_MIN 0x5 -#define RKISP1_CIF_ISP_AFM_WINDOW_Y_MIN 0x2 -#define RKISP1_CIF_ISP_AFM_WINDOW_X(x) (((x) & 0x1FFF) << 16) -#define RKISP1_CIF_ISP_AFM_WINDOW_Y(x) ((x) & 0x1FFF) - -/* DPF */ -#define RKISP1_CIF_ISP_DPF_MODE_EN BIT(0) -#define RKISP1_CIF_ISP_DPF_MODE_B_FLT_DIS BIT(1) -#define RKISP1_CIF_ISP_DPF_MODE_GB_FLT_DIS BIT(2) -#define RKISP1_CIF_ISP_DPF_MODE_GR_FLT_DIS BIT(3) -#define RKISP1_CIF_ISP_DPF_MODE_R_FLT_DIS BIT(4) -#define RKISP1_CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9 BIT(5) -#define RKISP1_CIF_ISP_DPF_MODE_NLL_SEGMENTATION BIT(6) -#define RKISP1_CIF_ISP_DPF_MODE_AWB_GAIN_COMP BIT(7) -#define RKISP1_CIF_ISP_DPF_MODE_LSC_GAIN_COMP BIT(8) -#define RKISP1_CIF_ISP_DPF_MODE_USE_NF_GAIN BIT(9) -#define RKISP1_CIF_ISP_DPF_NF_GAIN_RESERVED 0xFFFFF000 -#define RKISP1_CIF_ISP_DPF_SPATIAL_COEFF_MAX 0x1F -#define RKISP1_CIF_ISP_DPF_NLL_COEFF_N_MAX 0x3FF - -/* =================================================================== */ -/* CIF Registers */ -/* =================================================================== */ -#define RKISP1_CIF_CTRL_BASE 0x00000000 -#define RKISP1_CIF_CCL (RKISP1_CIF_CTRL_BASE + 0x00000000) -#define RKISP1_CIF_VI_ID (RKISP1_CIF_CTRL_BASE + 0x00000008) -#define RKISP1_CIF_ICCL (RKISP1_CIF_CTRL_BASE + 0x00000010) -#define RKISP1_CIF_IRCL (RKISP1_CIF_CTRL_BASE + 0x00000014) -#define RKISP1_CIF_VI_DPCL (RKISP1_CIF_CTRL_BASE + 0x00000018) - -#define RKISP1_CIF_IMG_EFF_BASE 0x00000200 -#define RKISP1_CIF_IMG_EFF_CTRL (RKISP1_CIF_IMG_EFF_BASE + 0x00000000) -#define RKISP1_CIF_IMG_EFF_COLOR_SEL (RKISP1_CIF_IMG_EFF_BASE + 0x00000004) -#define RKISP1_CIF_IMG_EFF_MAT_1 (RKISP1_CIF_IMG_EFF_BASE + 0x00000008) -#define RKISP1_CIF_IMG_EFF_MAT_2 (RKISP1_CIF_IMG_EFF_BASE + 0x0000000C) -#define RKISP1_CIF_IMG_EFF_MAT_3 (RKISP1_CIF_IMG_EFF_BASE + 0x00000010) -#define RKISP1_CIF_IMG_EFF_MAT_4 (RKISP1_CIF_IMG_EFF_BASE + 0x00000014) -#define RKISP1_CIF_IMG_EFF_MAT_5 (RKISP1_CIF_IMG_EFF_BASE + 0x00000018) -#define RKISP1_CIF_IMG_EFF_TINT (RKISP1_CIF_IMG_EFF_BASE + 0x0000001C) -#define RKISP1_CIF_IMG_EFF_CTRL_SHD (RKISP1_CIF_IMG_EFF_BASE + 0x00000020) -#define RKISP1_CIF_IMG_EFF_SHARPEN (RKISP1_CIF_IMG_EFF_BASE + 0x00000024) - -#define RKISP1_CIF_SUPER_IMP_BASE 0x00000300 -#define RKISP1_CIF_SUPER_IMP_CTRL (RKISP1_CIF_SUPER_IMP_BASE + 0x00000000) -#define RKISP1_CIF_SUPER_IMP_OFFSET_X (RKISP1_CIF_SUPER_IMP_BASE + 0x00000004) -#define RKISP1_CIF_SUPER_IMP_OFFSET_Y (RKISP1_CIF_SUPER_IMP_BASE + 0x00000008) -#define RKISP1_CIF_SUPER_IMP_COLOR_Y (RKISP1_CIF_SUPER_IMP_BASE + 0x0000000C) -#define RKISP1_CIF_SUPER_IMP_COLOR_CB (RKISP1_CIF_SUPER_IMP_BASE + 0x00000010) -#define RKISP1_CIF_SUPER_IMP_COLOR_CR (RKISP1_CIF_SUPER_IMP_BASE + 0x00000014) - -#define RKISP1_CIF_ISP_BASE 0x00000400 -#define RKISP1_CIF_ISP_CTRL (RKISP1_CIF_ISP_BASE + 0x00000000) -#define RKISP1_CIF_ISP_ACQ_PROP (RKISP1_CIF_ISP_BASE + 0x00000004) -#define RKISP1_CIF_ISP_ACQ_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000008) -#define RKISP1_CIF_ISP_ACQ_V_OFFS (RKISP1_CIF_ISP_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_ACQ_H_SIZE (RKISP1_CIF_ISP_BASE + 0x00000010) -#define RKISP1_CIF_ISP_ACQ_V_SIZE (RKISP1_CIF_ISP_BASE + 0x00000014) -#define RKISP1_CIF_ISP_ACQ_NR_FRAMES (RKISP1_CIF_ISP_BASE + 0x00000018) -#define RKISP1_CIF_ISP_GAMMA_DX_LO (RKISP1_CIF_ISP_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_GAMMA_DX_HI (RKISP1_CIF_ISP_BASE + 0x00000020) -#define RKISP1_CIF_ISP_GAMMA_R_Y0 (RKISP1_CIF_ISP_BASE + 0x00000024) -#define RKISP1_CIF_ISP_GAMMA_R_Y1 (RKISP1_CIF_ISP_BASE + 0x00000028) -#define RKISP1_CIF_ISP_GAMMA_R_Y2 (RKISP1_CIF_ISP_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_GAMMA_R_Y3 (RKISP1_CIF_ISP_BASE + 0x00000030) -#define RKISP1_CIF_ISP_GAMMA_R_Y4 (RKISP1_CIF_ISP_BASE + 0x00000034) -#define RKISP1_CIF_ISP_GAMMA_R_Y5 (RKISP1_CIF_ISP_BASE + 0x00000038) -#define RKISP1_CIF_ISP_GAMMA_R_Y6 (RKISP1_CIF_ISP_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_GAMMA_R_Y7 (RKISP1_CIF_ISP_BASE + 0x00000040) -#define RKISP1_CIF_ISP_GAMMA_R_Y8 (RKISP1_CIF_ISP_BASE + 0x00000044) -#define RKISP1_CIF_ISP_GAMMA_R_Y9 (RKISP1_CIF_ISP_BASE + 0x00000048) -#define RKISP1_CIF_ISP_GAMMA_R_Y10 (RKISP1_CIF_ISP_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_GAMMA_R_Y11 (RKISP1_CIF_ISP_BASE + 0x00000050) -#define RKISP1_CIF_ISP_GAMMA_R_Y12 (RKISP1_CIF_ISP_BASE + 0x00000054) -#define RKISP1_CIF_ISP_GAMMA_R_Y13 (RKISP1_CIF_ISP_BASE + 0x00000058) -#define RKISP1_CIF_ISP_GAMMA_R_Y14 (RKISP1_CIF_ISP_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_GAMMA_R_Y15 (RKISP1_CIF_ISP_BASE + 0x00000060) -#define RKISP1_CIF_ISP_GAMMA_R_Y16 (RKISP1_CIF_ISP_BASE + 0x00000064) -#define RKISP1_CIF_ISP_GAMMA_G_Y0 (RKISP1_CIF_ISP_BASE + 0x00000068) -#define RKISP1_CIF_ISP_GAMMA_G_Y1 (RKISP1_CIF_ISP_BASE + 0x0000006C) -#define RKISP1_CIF_ISP_GAMMA_G_Y2 (RKISP1_CIF_ISP_BASE + 0x00000070) -#define RKISP1_CIF_ISP_GAMMA_G_Y3 (RKISP1_CIF_ISP_BASE + 0x00000074) -#define RKISP1_CIF_ISP_GAMMA_G_Y4 (RKISP1_CIF_ISP_BASE + 0x00000078) -#define RKISP1_CIF_ISP_GAMMA_G_Y5 (RKISP1_CIF_ISP_BASE + 0x0000007C) -#define RKISP1_CIF_ISP_GAMMA_G_Y6 (RKISP1_CIF_ISP_BASE + 0x00000080) -#define RKISP1_CIF_ISP_GAMMA_G_Y7 (RKISP1_CIF_ISP_BASE + 0x00000084) -#define RKISP1_CIF_ISP_GAMMA_G_Y8 (RKISP1_CIF_ISP_BASE + 0x00000088) -#define RKISP1_CIF_ISP_GAMMA_G_Y9 (RKISP1_CIF_ISP_BASE + 0x0000008C) -#define RKISP1_CIF_ISP_GAMMA_G_Y10 (RKISP1_CIF_ISP_BASE + 0x00000090) -#define RKISP1_CIF_ISP_GAMMA_G_Y11 (RKISP1_CIF_ISP_BASE + 0x00000094) -#define RKISP1_CIF_ISP_GAMMA_G_Y12 (RKISP1_CIF_ISP_BASE + 0x00000098) -#define RKISP1_CIF_ISP_GAMMA_G_Y13 (RKISP1_CIF_ISP_BASE + 0x0000009C) -#define RKISP1_CIF_ISP_GAMMA_G_Y14 (RKISP1_CIF_ISP_BASE + 0x000000A0) -#define RKISP1_CIF_ISP_GAMMA_G_Y15 (RKISP1_CIF_ISP_BASE + 0x000000A4) -#define RKISP1_CIF_ISP_GAMMA_G_Y16 (RKISP1_CIF_ISP_BASE + 0x000000A8) -#define RKISP1_CIF_ISP_GAMMA_B_Y0 (RKISP1_CIF_ISP_BASE + 0x000000AC) -#define RKISP1_CIF_ISP_GAMMA_B_Y1 (RKISP1_CIF_ISP_BASE + 0x000000B0) -#define RKISP1_CIF_ISP_GAMMA_B_Y2 (RKISP1_CIF_ISP_BASE + 0x000000B4) -#define RKISP1_CIF_ISP_GAMMA_B_Y3 (RKISP1_CIF_ISP_BASE + 0x000000B8) -#define RKISP1_CIF_ISP_GAMMA_B_Y4 (RKISP1_CIF_ISP_BASE + 0x000000BC) -#define RKISP1_CIF_ISP_GAMMA_B_Y5 (RKISP1_CIF_ISP_BASE + 0x000000C0) -#define RKISP1_CIF_ISP_GAMMA_B_Y6 (RKISP1_CIF_ISP_BASE + 0x000000C4) -#define RKISP1_CIF_ISP_GAMMA_B_Y7 (RKISP1_CIF_ISP_BASE + 0x000000C8) -#define RKISP1_CIF_ISP_GAMMA_B_Y8 (RKISP1_CIF_ISP_BASE + 0x000000CC) -#define RKISP1_CIF_ISP_GAMMA_B_Y9 (RKISP1_CIF_ISP_BASE + 0x000000D0) -#define RKISP1_CIF_ISP_GAMMA_B_Y10 (RKISP1_CIF_ISP_BASE + 0x000000D4) -#define RKISP1_CIF_ISP_GAMMA_B_Y11 (RKISP1_CIF_ISP_BASE + 0x000000D8) -#define RKISP1_CIF_ISP_GAMMA_B_Y12 (RKISP1_CIF_ISP_BASE + 0x000000DC) -#define RKISP1_CIF_ISP_GAMMA_B_Y13 (RKISP1_CIF_ISP_BASE + 0x000000E0) -#define RKISP1_CIF_ISP_GAMMA_B_Y14 (RKISP1_CIF_ISP_BASE + 0x000000E4) -#define RKISP1_CIF_ISP_GAMMA_B_Y15 (RKISP1_CIF_ISP_BASE + 0x000000E8) -#define RKISP1_CIF_ISP_GAMMA_B_Y16 (RKISP1_CIF_ISP_BASE + 0x000000EC) -#define RKISP1_CIF_ISP_AWB_PROP (RKISP1_CIF_ISP_BASE + 0x00000110) -#define RKISP1_CIF_ISP_AWB_WND_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000114) -#define RKISP1_CIF_ISP_AWB_WND_V_OFFS (RKISP1_CIF_ISP_BASE + 0x00000118) -#define RKISP1_CIF_ISP_AWB_WND_H_SIZE (RKISP1_CIF_ISP_BASE + 0x0000011C) -#define RKISP1_CIF_ISP_AWB_WND_V_SIZE (RKISP1_CIF_ISP_BASE + 0x00000120) -#define RKISP1_CIF_ISP_AWB_FRAMES (RKISP1_CIF_ISP_BASE + 0x00000124) -#define RKISP1_CIF_ISP_AWB_REF (RKISP1_CIF_ISP_BASE + 0x00000128) -#define RKISP1_CIF_ISP_AWB_THRESH (RKISP1_CIF_ISP_BASE + 0x0000012C) -#define RKISP1_CIF_ISP_AWB_GAIN_G (RKISP1_CIF_ISP_BASE + 0x00000138) -#define RKISP1_CIF_ISP_AWB_GAIN_RB (RKISP1_CIF_ISP_BASE + 0x0000013C) -#define RKISP1_CIF_ISP_AWB_WHITE_CNT (RKISP1_CIF_ISP_BASE + 0x00000140) -#define RKISP1_CIF_ISP_AWB_MEAN (RKISP1_CIF_ISP_BASE + 0x00000144) -#define RKISP1_CIF_ISP_CC_COEFF_0 (RKISP1_CIF_ISP_BASE + 0x00000170) -#define RKISP1_CIF_ISP_CC_COEFF_1 (RKISP1_CIF_ISP_BASE + 0x00000174) -#define RKISP1_CIF_ISP_CC_COEFF_2 (RKISP1_CIF_ISP_BASE + 0x00000178) -#define RKISP1_CIF_ISP_CC_COEFF_3 (RKISP1_CIF_ISP_BASE + 0x0000017C) -#define RKISP1_CIF_ISP_CC_COEFF_4 (RKISP1_CIF_ISP_BASE + 0x00000180) -#define RKISP1_CIF_ISP_CC_COEFF_5 (RKISP1_CIF_ISP_BASE + 0x00000184) -#define RKISP1_CIF_ISP_CC_COEFF_6 (RKISP1_CIF_ISP_BASE + 0x00000188) -#define RKISP1_CIF_ISP_CC_COEFF_7 (RKISP1_CIF_ISP_BASE + 0x0000018C) -#define RKISP1_CIF_ISP_CC_COEFF_8 (RKISP1_CIF_ISP_BASE + 0x00000190) -#define RKISP1_CIF_ISP_OUT_H_OFFS (RKISP1_CIF_ISP_BASE + 0x00000194) -#define RKISP1_CIF_ISP_OUT_V_OFFS (RKISP1_CIF_ISP_BASE + 0x00000198) -#define RKISP1_CIF_ISP_OUT_H_SIZE (RKISP1_CIF_ISP_BASE + 0x0000019C) -#define RKISP1_CIF_ISP_OUT_V_SIZE (RKISP1_CIF_ISP_BASE + 0x000001A0) -#define RKISP1_CIF_ISP_DEMOSAIC (RKISP1_CIF_ISP_BASE + 0x000001A4) -#define RKISP1_CIF_ISP_FLAGS_SHD (RKISP1_CIF_ISP_BASE + 0x000001A8) -#define RKISP1_CIF_ISP_OUT_H_OFFS_SHD (RKISP1_CIF_ISP_BASE + 0x000001AC) -#define RKISP1_CIF_ISP_OUT_V_OFFS_SHD (RKISP1_CIF_ISP_BASE + 0x000001B0) -#define RKISP1_CIF_ISP_OUT_H_SIZE_SHD (RKISP1_CIF_ISP_BASE + 0x000001B4) -#define RKISP1_CIF_ISP_OUT_V_SIZE_SHD (RKISP1_CIF_ISP_BASE + 0x000001B8) -#define RKISP1_CIF_ISP_IMSC (RKISP1_CIF_ISP_BASE + 0x000001BC) -#define RKISP1_CIF_ISP_RIS (RKISP1_CIF_ISP_BASE + 0x000001C0) -#define RKISP1_CIF_ISP_MIS (RKISP1_CIF_ISP_BASE + 0x000001C4) -#define RKISP1_CIF_ISP_ICR (RKISP1_CIF_ISP_BASE + 0x000001C8) -#define RKISP1_CIF_ISP_ISR (RKISP1_CIF_ISP_BASE + 0x000001CC) -#define RKISP1_CIF_ISP_CT_COEFF_0 (RKISP1_CIF_ISP_BASE + 0x000001D0) -#define RKISP1_CIF_ISP_CT_COEFF_1 (RKISP1_CIF_ISP_BASE + 0x000001D4) -#define RKISP1_CIF_ISP_CT_COEFF_2 (RKISP1_CIF_ISP_BASE + 0x000001D8) -#define RKISP1_CIF_ISP_CT_COEFF_3 (RKISP1_CIF_ISP_BASE + 0x000001DC) -#define RKISP1_CIF_ISP_CT_COEFF_4 (RKISP1_CIF_ISP_BASE + 0x000001E0) -#define RKISP1_CIF_ISP_CT_COEFF_5 (RKISP1_CIF_ISP_BASE + 0x000001E4) -#define RKISP1_CIF_ISP_CT_COEFF_6 (RKISP1_CIF_ISP_BASE + 0x000001E8) -#define RKISP1_CIF_ISP_CT_COEFF_7 (RKISP1_CIF_ISP_BASE + 0x000001EC) -#define RKISP1_CIF_ISP_CT_COEFF_8 (RKISP1_CIF_ISP_BASE + 0x000001F0) -#define RKISP1_CIF_ISP_GAMMA_OUT_MODE (RKISP1_CIF_ISP_BASE + 0x000001F4) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_0 (RKISP1_CIF_ISP_BASE + 0x000001F8) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_1 (RKISP1_CIF_ISP_BASE + 0x000001FC) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_2 (RKISP1_CIF_ISP_BASE + 0x00000200) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_3 (RKISP1_CIF_ISP_BASE + 0x00000204) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_4 (RKISP1_CIF_ISP_BASE + 0x00000208) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_5 (RKISP1_CIF_ISP_BASE + 0x0000020C) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_6 (RKISP1_CIF_ISP_BASE + 0x00000210) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_7 (RKISP1_CIF_ISP_BASE + 0x00000214) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_8 (RKISP1_CIF_ISP_BASE + 0x00000218) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_9 (RKISP1_CIF_ISP_BASE + 0x0000021C) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_10 (RKISP1_CIF_ISP_BASE + 0x00000220) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_11 (RKISP1_CIF_ISP_BASE + 0x00000224) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_12 (RKISP1_CIF_ISP_BASE + 0x00000228) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_13 (RKISP1_CIF_ISP_BASE + 0x0000022C) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_14 (RKISP1_CIF_ISP_BASE + 0x00000230) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_15 (RKISP1_CIF_ISP_BASE + 0x00000234) -#define RKISP1_CIF_ISP_GAMMA_OUT_Y_16 (RKISP1_CIF_ISP_BASE + 0x00000238) -#define RKISP1_CIF_ISP_ERR (RKISP1_CIF_ISP_BASE + 0x0000023C) -#define RKISP1_CIF_ISP_ERR_CLR (RKISP1_CIF_ISP_BASE + 0x00000240) -#define RKISP1_CIF_ISP_FRAME_COUNT (RKISP1_CIF_ISP_BASE + 0x00000244) -#define RKISP1_CIF_ISP_CT_OFFSET_R (RKISP1_CIF_ISP_BASE + 0x00000248) -#define RKISP1_CIF_ISP_CT_OFFSET_G (RKISP1_CIF_ISP_BASE + 0x0000024C) -#define RKISP1_CIF_ISP_CT_OFFSET_B (RKISP1_CIF_ISP_BASE + 0x00000250) - -#define RKISP1_CIF_ISP_FLASH_BASE 0x00000660 -#define RKISP1_CIF_ISP_FLASH_CMD (RKISP1_CIF_ISP_FLASH_BASE + 0x00000000) -#define RKISP1_CIF_ISP_FLASH_CONFIG (RKISP1_CIF_ISP_FLASH_BASE + 0x00000004) -#define RKISP1_CIF_ISP_FLASH_PREDIV (RKISP1_CIF_ISP_FLASH_BASE + 0x00000008) -#define RKISP1_CIF_ISP_FLASH_DELAY (RKISP1_CIF_ISP_FLASH_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_FLASH_TIME (RKISP1_CIF_ISP_FLASH_BASE + 0x00000010) -#define RKISP1_CIF_ISP_FLASH_MAXP (RKISP1_CIF_ISP_FLASH_BASE + 0x00000014) - -#define RKISP1_CIF_ISP_SH_BASE 0x00000680 -#define RKISP1_CIF_ISP_SH_CTRL (RKISP1_CIF_ISP_SH_BASE + 0x00000000) -#define RKISP1_CIF_ISP_SH_PREDIV (RKISP1_CIF_ISP_SH_BASE + 0x00000004) -#define RKISP1_CIF_ISP_SH_DELAY (RKISP1_CIF_ISP_SH_BASE + 0x00000008) -#define RKISP1_CIF_ISP_SH_TIME (RKISP1_CIF_ISP_SH_BASE + 0x0000000C) - -#define RKISP1_CIF_C_PROC_BASE 0x00000800 -#define RKISP1_CIF_C_PROC_CTRL (RKISP1_CIF_C_PROC_BASE + 0x00000000) -#define RKISP1_CIF_C_PROC_CONTRAST (RKISP1_CIF_C_PROC_BASE + 0x00000004) -#define RKISP1_CIF_C_PROC_BRIGHTNESS (RKISP1_CIF_C_PROC_BASE + 0x00000008) -#define RKISP1_CIF_C_PROC_SATURATION (RKISP1_CIF_C_PROC_BASE + 0x0000000C) -#define RKISP1_CIF_C_PROC_HUE (RKISP1_CIF_C_PROC_BASE + 0x00000010) - -#define RKISP1_CIF_DUAL_CROP_BASE 0x00000880 -#define RKISP1_CIF_DUAL_CROP_CTRL (RKISP1_CIF_DUAL_CROP_BASE + 0x00000000) -#define RKISP1_CIF_DUAL_CROP_M_H_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000004) -#define RKISP1_CIF_DUAL_CROP_M_V_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000008) -#define RKISP1_CIF_DUAL_CROP_M_H_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x0000000C) -#define RKISP1_CIF_DUAL_CROP_M_V_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x00000010) -#define RKISP1_CIF_DUAL_CROP_S_H_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000014) -#define RKISP1_CIF_DUAL_CROP_S_V_OFFS (RKISP1_CIF_DUAL_CROP_BASE + 0x00000018) -#define RKISP1_CIF_DUAL_CROP_S_H_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x0000001C) -#define RKISP1_CIF_DUAL_CROP_S_V_SIZE (RKISP1_CIF_DUAL_CROP_BASE + 0x00000020) -#define RKISP1_CIF_DUAL_CROP_M_H_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000024) -#define RKISP1_CIF_DUAL_CROP_M_V_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000028) -#define RKISP1_CIF_DUAL_CROP_M_H_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x0000002C) -#define RKISP1_CIF_DUAL_CROP_M_V_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000030) -#define RKISP1_CIF_DUAL_CROP_S_H_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000034) -#define RKISP1_CIF_DUAL_CROP_S_V_OFFS_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000038) -#define RKISP1_CIF_DUAL_CROP_S_H_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x0000003C) -#define RKISP1_CIF_DUAL_CROP_S_V_SIZE_SHD (RKISP1_CIF_DUAL_CROP_BASE + 0x00000040) - -#define RKISP1_CIF_MRSZ_BASE 0x00000C00 -#define RKISP1_CIF_MRSZ_CTRL (RKISP1_CIF_MRSZ_BASE + 0x00000000) -#define RKISP1_CIF_MRSZ_SCALE_HY (RKISP1_CIF_MRSZ_BASE + 0x00000004) -#define RKISP1_CIF_MRSZ_SCALE_HCB (RKISP1_CIF_MRSZ_BASE + 0x00000008) -#define RKISP1_CIF_MRSZ_SCALE_HCR (RKISP1_CIF_MRSZ_BASE + 0x0000000C) -#define RKISP1_CIF_MRSZ_SCALE_VY (RKISP1_CIF_MRSZ_BASE + 0x00000010) -#define RKISP1_CIF_MRSZ_SCALE_VC (RKISP1_CIF_MRSZ_BASE + 0x00000014) -#define RKISP1_CIF_MRSZ_PHASE_HY (RKISP1_CIF_MRSZ_BASE + 0x00000018) -#define RKISP1_CIF_MRSZ_PHASE_HC (RKISP1_CIF_MRSZ_BASE + 0x0000001C) -#define RKISP1_CIF_MRSZ_PHASE_VY (RKISP1_CIF_MRSZ_BASE + 0x00000020) -#define RKISP1_CIF_MRSZ_PHASE_VC (RKISP1_CIF_MRSZ_BASE + 0x00000024) -#define RKISP1_CIF_MRSZ_SCALE_LUT_ADDR (RKISP1_CIF_MRSZ_BASE + 0x00000028) -#define RKISP1_CIF_MRSZ_SCALE_LUT (RKISP1_CIF_MRSZ_BASE + 0x0000002C) -#define RKISP1_CIF_MRSZ_CTRL_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000030) -#define RKISP1_CIF_MRSZ_SCALE_HY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000034) -#define RKISP1_CIF_MRSZ_SCALE_HCB_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000038) -#define RKISP1_CIF_MRSZ_SCALE_HCR_SHD (RKISP1_CIF_MRSZ_BASE + 0x0000003C) -#define RKISP1_CIF_MRSZ_SCALE_VY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000040) -#define RKISP1_CIF_MRSZ_SCALE_VC_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000044) -#define RKISP1_CIF_MRSZ_PHASE_HY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000048) -#define RKISP1_CIF_MRSZ_PHASE_HC_SHD (RKISP1_CIF_MRSZ_BASE + 0x0000004C) -#define RKISP1_CIF_MRSZ_PHASE_VY_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000050) -#define RKISP1_CIF_MRSZ_PHASE_VC_SHD (RKISP1_CIF_MRSZ_BASE + 0x00000054) - -#define RKISP1_CIF_SRSZ_BASE 0x00001000 -#define RKISP1_CIF_SRSZ_CTRL (RKISP1_CIF_SRSZ_BASE + 0x00000000) -#define RKISP1_CIF_SRSZ_SCALE_HY (RKISP1_CIF_SRSZ_BASE + 0x00000004) -#define RKISP1_CIF_SRSZ_SCALE_HCB (RKISP1_CIF_SRSZ_BASE + 0x00000008) -#define RKISP1_CIF_SRSZ_SCALE_HCR (RKISP1_CIF_SRSZ_BASE + 0x0000000C) -#define RKISP1_CIF_SRSZ_SCALE_VY (RKISP1_CIF_SRSZ_BASE + 0x00000010) -#define RKISP1_CIF_SRSZ_SCALE_VC (RKISP1_CIF_SRSZ_BASE + 0x00000014) -#define RKISP1_CIF_SRSZ_PHASE_HY (RKISP1_CIF_SRSZ_BASE + 0x00000018) -#define RKISP1_CIF_SRSZ_PHASE_HC (RKISP1_CIF_SRSZ_BASE + 0x0000001C) -#define RKISP1_CIF_SRSZ_PHASE_VY (RKISP1_CIF_SRSZ_BASE + 0x00000020) -#define RKISP1_CIF_SRSZ_PHASE_VC (RKISP1_CIF_SRSZ_BASE + 0x00000024) -#define RKISP1_CIF_SRSZ_SCALE_LUT_ADDR (RKISP1_CIF_SRSZ_BASE + 0x00000028) -#define RKISP1_CIF_SRSZ_SCALE_LUT (RKISP1_CIF_SRSZ_BASE + 0x0000002C) -#define RKISP1_CIF_SRSZ_CTRL_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000030) -#define RKISP1_CIF_SRSZ_SCALE_HY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000034) -#define RKISP1_CIF_SRSZ_SCALE_HCB_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000038) -#define RKISP1_CIF_SRSZ_SCALE_HCR_SHD (RKISP1_CIF_SRSZ_BASE + 0x0000003C) -#define RKISP1_CIF_SRSZ_SCALE_VY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000040) -#define RKISP1_CIF_SRSZ_SCALE_VC_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000044) -#define RKISP1_CIF_SRSZ_PHASE_HY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000048) -#define RKISP1_CIF_SRSZ_PHASE_HC_SHD (RKISP1_CIF_SRSZ_BASE + 0x0000004C) -#define RKISP1_CIF_SRSZ_PHASE_VY_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000050) -#define RKISP1_CIF_SRSZ_PHASE_VC_SHD (RKISP1_CIF_SRSZ_BASE + 0x00000054) - -#define RKISP1_CIF_MI_BASE 0x00001400 -#define RKISP1_CIF_MI_CTRL (RKISP1_CIF_MI_BASE + 0x00000000) -#define RKISP1_CIF_MI_INIT (RKISP1_CIF_MI_BASE + 0x00000004) -#define RKISP1_CIF_MI_MP_Y_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000008) -#define RKISP1_CIF_MI_MP_Y_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x0000000C) -#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000010) -#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000014) -#define RKISP1_CIF_MI_MP_Y_IRQ_OFFS_INIT (RKISP1_CIF_MI_BASE + 0x00000018) -#define RKISP1_CIF_MI_MP_CB_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000001C) -#define RKISP1_CIF_MI_MP_CB_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000020) -#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000024) -#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000028) -#define RKISP1_CIF_MI_MP_CR_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000002C) -#define RKISP1_CIF_MI_MP_CR_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000030) -#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000034) -#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000038) -#define RKISP1_CIF_MI_SP_Y_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x0000003C) -#define RKISP1_CIF_MI_SP_Y_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000040) -#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000044) -#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x00000048) -#define RKISP1_CIF_MI_SP_Y_LLENGTH (RKISP1_CIF_MI_BASE + 0x0000004C) -#define RKISP1_CIF_MI_SP_CB_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000050) -#define RKISP1_CIF_MI_SP_CB_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000054) -#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000058) -#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x0000005C) -#define RKISP1_CIF_MI_SP_CR_BASE_AD_INIT (RKISP1_CIF_MI_BASE + 0x00000060) -#define RKISP1_CIF_MI_SP_CR_SIZE_INIT (RKISP1_CIF_MI_BASE + 0x00000064) -#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT (RKISP1_CIF_MI_BASE + 0x00000068) -#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_START (RKISP1_CIF_MI_BASE + 0x0000006C) -#define RKISP1_CIF_MI_BYTE_CNT (RKISP1_CIF_MI_BASE + 0x00000070) -#define RKISP1_CIF_MI_CTRL_SHD (RKISP1_CIF_MI_BASE + 0x00000074) -#define RKISP1_CIF_MI_MP_Y_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000078) -#define RKISP1_CIF_MI_MP_Y_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x0000007C) -#define RKISP1_CIF_MI_MP_Y_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x00000080) -#define RKISP1_CIF_MI_MP_Y_IRQ_OFFS_SHD (RKISP1_CIF_MI_BASE + 0x00000084) -#define RKISP1_CIF_MI_MP_CB_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000088) -#define RKISP1_CIF_MI_MP_CB_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x0000008C) -#define RKISP1_CIF_MI_MP_CB_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x00000090) -#define RKISP1_CIF_MI_MP_CR_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x00000094) -#define RKISP1_CIF_MI_MP_CR_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x00000098) -#define RKISP1_CIF_MI_MP_CR_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x0000009C) -#define RKISP1_CIF_MI_SP_Y_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000A0) -#define RKISP1_CIF_MI_SP_Y_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000A4) -#define RKISP1_CIF_MI_SP_Y_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000A8) -#define RKISP1_CIF_MI_SP_CB_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000B0) -#define RKISP1_CIF_MI_SP_CB_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000B4) -#define RKISP1_CIF_MI_SP_CB_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000B8) -#define RKISP1_CIF_MI_SP_CR_BASE_AD_SHD (RKISP1_CIF_MI_BASE + 0x000000BC) -#define RKISP1_CIF_MI_SP_CR_SIZE_SHD (RKISP1_CIF_MI_BASE + 0x000000C0) -#define RKISP1_CIF_MI_SP_CR_OFFS_CNT_SHD (RKISP1_CIF_MI_BASE + 0x000000C4) -#define RKISP1_CIF_MI_DMA_Y_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000C8) -#define RKISP1_CIF_MI_DMA_Y_PIC_WIDTH (RKISP1_CIF_MI_BASE + 0x000000CC) -#define RKISP1_CIF_MI_DMA_Y_LLENGTH (RKISP1_CIF_MI_BASE + 0x000000D0) -#define RKISP1_CIF_MI_DMA_Y_PIC_SIZE (RKISP1_CIF_MI_BASE + 0x000000D4) -#define RKISP1_CIF_MI_DMA_CB_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000D8) -#define RKISP1_CIF_MI_DMA_CR_PIC_START_AD (RKISP1_CIF_MI_BASE + 0x000000E8) -#define RKISP1_CIF_MI_IMSC (RKISP1_CIF_MI_BASE + 0x000000F8) -#define RKISP1_CIF_MI_RIS (RKISP1_CIF_MI_BASE + 0x000000FC) -#define RKISP1_CIF_MI_MIS (RKISP1_CIF_MI_BASE + 0x00000100) -#define RKISP1_CIF_MI_ICR (RKISP1_CIF_MI_BASE + 0x00000104) -#define RKISP1_CIF_MI_ISR (RKISP1_CIF_MI_BASE + 0x00000108) -#define RKISP1_CIF_MI_STATUS (RKISP1_CIF_MI_BASE + 0x0000010C) -#define RKISP1_CIF_MI_STATUS_CLR (RKISP1_CIF_MI_BASE + 0x00000110) -#define RKISP1_CIF_MI_SP_Y_PIC_WIDTH (RKISP1_CIF_MI_BASE + 0x00000114) -#define RKISP1_CIF_MI_SP_Y_PIC_HEIGHT (RKISP1_CIF_MI_BASE + 0x00000118) -#define RKISP1_CIF_MI_SP_Y_PIC_SIZE (RKISP1_CIF_MI_BASE + 0x0000011C) -#define RKISP1_CIF_MI_DMA_CTRL (RKISP1_CIF_MI_BASE + 0x00000120) -#define RKISP1_CIF_MI_DMA_START (RKISP1_CIF_MI_BASE + 0x00000124) -#define RKISP1_CIF_MI_DMA_STATUS (RKISP1_CIF_MI_BASE + 0x00000128) -#define RKISP1_CIF_MI_PIXEL_COUNT (RKISP1_CIF_MI_BASE + 0x0000012C) -#define RKISP1_CIF_MI_MP_Y_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000130) -#define RKISP1_CIF_MI_MP_CB_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000134) -#define RKISP1_CIF_MI_MP_CR_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000138) -#define RKISP1_CIF_MI_SP_Y_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x0000013C) -#define RKISP1_CIF_MI_SP_CB_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000140) -#define RKISP1_CIF_MI_SP_CR_BASE_AD_INIT2 (RKISP1_CIF_MI_BASE + 0x00000144) -#define RKISP1_CIF_MI_XTD_FORMAT_CTRL (RKISP1_CIF_MI_BASE + 0x00000148) - -#define RKISP1_CIF_SMIA_BASE 0x00001A00 -#define RKISP1_CIF_SMIA_CTRL (RKISP1_CIF_SMIA_BASE + 0x00000000) -#define RKISP1_CIF_SMIA_STATUS (RKISP1_CIF_SMIA_BASE + 0x00000004) -#define RKISP1_CIF_SMIA_IMSC (RKISP1_CIF_SMIA_BASE + 0x00000008) -#define RKISP1_CIF_SMIA_RIS (RKISP1_CIF_SMIA_BASE + 0x0000000C) -#define RKISP1_CIF_SMIA_MIS (RKISP1_CIF_SMIA_BASE + 0x00000010) -#define RKISP1_CIF_SMIA_ICR (RKISP1_CIF_SMIA_BASE + 0x00000014) -#define RKISP1_CIF_SMIA_ISR (RKISP1_CIF_SMIA_BASE + 0x00000018) -#define RKISP1_CIF_SMIA_DATA_FORMAT_SEL (RKISP1_CIF_SMIA_BASE + 0x0000001C) -#define RKISP1_CIF_SMIA_SOF_EMB_DATA_LINES (RKISP1_CIF_SMIA_BASE + 0x00000020) -#define RKISP1_CIF_SMIA_EMB_HSTART (RKISP1_CIF_SMIA_BASE + 0x00000024) -#define RKISP1_CIF_SMIA_EMB_HSIZE (RKISP1_CIF_SMIA_BASE + 0x00000028) -#define RKISP1_CIF_SMIA_EMB_VSTART (RKISP1_CIF_SMIA_BASE + 0x0000002c) -#define RKISP1_CIF_SMIA_NUM_LINES (RKISP1_CIF_SMIA_BASE + 0x00000030) -#define RKISP1_CIF_SMIA_EMB_DATA_FIFO (RKISP1_CIF_SMIA_BASE + 0x00000034) -#define RKISP1_CIF_SMIA_EMB_DATA_WATERMARK (RKISP1_CIF_SMIA_BASE + 0x00000038) - -#define RKISP1_CIF_MIPI_BASE 0x00001C00 -#define RKISP1_CIF_MIPI_CTRL (RKISP1_CIF_MIPI_BASE + 0x00000000) -#define RKISP1_CIF_MIPI_STATUS (RKISP1_CIF_MIPI_BASE + 0x00000004) -#define RKISP1_CIF_MIPI_IMSC (RKISP1_CIF_MIPI_BASE + 0x00000008) -#define RKISP1_CIF_MIPI_RIS (RKISP1_CIF_MIPI_BASE + 0x0000000C) -#define RKISP1_CIF_MIPI_MIS (RKISP1_CIF_MIPI_BASE + 0x00000010) -#define RKISP1_CIF_MIPI_ICR (RKISP1_CIF_MIPI_BASE + 0x00000014) -#define RKISP1_CIF_MIPI_ISR (RKISP1_CIF_MIPI_BASE + 0x00000018) -#define RKISP1_CIF_MIPI_CUR_DATA_ID (RKISP1_CIF_MIPI_BASE + 0x0000001C) -#define RKISP1_CIF_MIPI_IMG_DATA_SEL (RKISP1_CIF_MIPI_BASE + 0x00000020) -#define RKISP1_CIF_MIPI_ADD_DATA_SEL_1 (RKISP1_CIF_MIPI_BASE + 0x00000024) -#define RKISP1_CIF_MIPI_ADD_DATA_SEL_2 (RKISP1_CIF_MIPI_BASE + 0x00000028) -#define RKISP1_CIF_MIPI_ADD_DATA_SEL_3 (RKISP1_CIF_MIPI_BASE + 0x0000002C) -#define RKISP1_CIF_MIPI_ADD_DATA_SEL_4 (RKISP1_CIF_MIPI_BASE + 0x00000030) -#define RKISP1_CIF_MIPI_ADD_DATA_FIFO (RKISP1_CIF_MIPI_BASE + 0x00000034) -#define RKISP1_CIF_MIPI_FIFO_FILL_LEVEL (RKISP1_CIF_MIPI_BASE + 0x00000038) -#define RKISP1_CIF_MIPI_COMPRESSED_MODE (RKISP1_CIF_MIPI_BASE + 0x0000003C) -#define RKISP1_CIF_MIPI_FRAME (RKISP1_CIF_MIPI_BASE + 0x00000040) -#define RKISP1_CIF_MIPI_GEN_SHORT_DT (RKISP1_CIF_MIPI_BASE + 0x00000044) -#define RKISP1_CIF_MIPI_GEN_SHORT_8_9 (RKISP1_CIF_MIPI_BASE + 0x00000048) -#define RKISP1_CIF_MIPI_GEN_SHORT_A_B (RKISP1_CIF_MIPI_BASE + 0x0000004C) -#define RKISP1_CIF_MIPI_GEN_SHORT_C_D (RKISP1_CIF_MIPI_BASE + 0x00000050) -#define RKISP1_CIF_MIPI_GEN_SHORT_E_F (RKISP1_CIF_MIPI_BASE + 0x00000054) - -#define RKISP1_CIF_ISP_AFM_BASE 0x00002000 -#define RKISP1_CIF_ISP_AFM_CTRL (RKISP1_CIF_ISP_AFM_BASE + 0x00000000) -#define RKISP1_CIF_ISP_AFM_LT_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000004) -#define RKISP1_CIF_ISP_AFM_RB_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000008) -#define RKISP1_CIF_ISP_AFM_LT_B (RKISP1_CIF_ISP_AFM_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_AFM_RB_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000010) -#define RKISP1_CIF_ISP_AFM_LT_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000014) -#define RKISP1_CIF_ISP_AFM_RB_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000018) -#define RKISP1_CIF_ISP_AFM_THRES (RKISP1_CIF_ISP_AFM_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_AFM_VAR_SHIFT (RKISP1_CIF_ISP_AFM_BASE + 0x00000020) -#define RKISP1_CIF_ISP_AFM_SUM_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000024) -#define RKISP1_CIF_ISP_AFM_SUM_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000028) -#define RKISP1_CIF_ISP_AFM_SUM_C (RKISP1_CIF_ISP_AFM_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_AFM_LUM_A (RKISP1_CIF_ISP_AFM_BASE + 0x00000030) -#define RKISP1_CIF_ISP_AFM_LUM_B (RKISP1_CIF_ISP_AFM_BASE + 0x00000034) -#define RKISP1_CIF_ISP_AFM_LUM_C (RKISP1_CIF_ISP_AFM_BASE + 0x00000038) - -#define RKISP1_CIF_ISP_LSC_BASE 0x00002200 -#define RKISP1_CIF_ISP_LSC_CTRL (RKISP1_CIF_ISP_LSC_BASE + 0x00000000) -#define RKISP1_CIF_ISP_LSC_R_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000004) -#define RKISP1_CIF_ISP_LSC_GR_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000008) -#define RKISP1_CIF_ISP_LSC_B_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_LSC_GB_TABLE_ADDR (RKISP1_CIF_ISP_LSC_BASE + 0x00000010) -#define RKISP1_CIF_ISP_LSC_R_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000014) -#define RKISP1_CIF_ISP_LSC_GR_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000018) -#define RKISP1_CIF_ISP_LSC_B_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_LSC_GB_TABLE_DATA (RKISP1_CIF_ISP_LSC_BASE + 0x00000020) -#define RKISP1_CIF_ISP_LSC_XGRAD_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000024) -#define RKISP1_CIF_ISP_LSC_XGRAD_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000028) -#define RKISP1_CIF_ISP_LSC_XGRAD_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_LSC_XGRAD_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000030) -#define RKISP1_CIF_ISP_LSC_YGRAD_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000034) -#define RKISP1_CIF_ISP_LSC_YGRAD_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000038) -#define RKISP1_CIF_ISP_LSC_YGRAD_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_LSC_YGRAD_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000040) -#define RKISP1_CIF_ISP_LSC_XSIZE_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000044) -#define RKISP1_CIF_ISP_LSC_XSIZE_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000048) -#define RKISP1_CIF_ISP_LSC_XSIZE_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_LSC_XSIZE_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000050) -#define RKISP1_CIF_ISP_LSC_YSIZE_01 (RKISP1_CIF_ISP_LSC_BASE + 0x00000054) -#define RKISP1_CIF_ISP_LSC_YSIZE_23 (RKISP1_CIF_ISP_LSC_BASE + 0x00000058) -#define RKISP1_CIF_ISP_LSC_YSIZE_45 (RKISP1_CIF_ISP_LSC_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_LSC_YSIZE_67 (RKISP1_CIF_ISP_LSC_BASE + 0x00000060) -#define RKISP1_CIF_ISP_LSC_TABLE_SEL (RKISP1_CIF_ISP_LSC_BASE + 0x00000064) -#define RKISP1_CIF_ISP_LSC_STATUS (RKISP1_CIF_ISP_LSC_BASE + 0x00000068) - -#define RKISP1_CIF_ISP_IS_BASE 0x00002300 -#define RKISP1_CIF_ISP_IS_CTRL (RKISP1_CIF_ISP_IS_BASE + 0x00000000) -#define RKISP1_CIF_ISP_IS_RECENTER (RKISP1_CIF_ISP_IS_BASE + 0x00000004) -#define RKISP1_CIF_ISP_IS_H_OFFS (RKISP1_CIF_ISP_IS_BASE + 0x00000008) -#define RKISP1_CIF_ISP_IS_V_OFFS (RKISP1_CIF_ISP_IS_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_IS_H_SIZE (RKISP1_CIF_ISP_IS_BASE + 0x00000010) -#define RKISP1_CIF_ISP_IS_V_SIZE (RKISP1_CIF_ISP_IS_BASE + 0x00000014) -#define RKISP1_CIF_ISP_IS_MAX_DX (RKISP1_CIF_ISP_IS_BASE + 0x00000018) -#define RKISP1_CIF_ISP_IS_MAX_DY (RKISP1_CIF_ISP_IS_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_IS_DISPLACE (RKISP1_CIF_ISP_IS_BASE + 0x00000020) -#define RKISP1_CIF_ISP_IS_H_OFFS_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000024) -#define RKISP1_CIF_ISP_IS_V_OFFS_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000028) -#define RKISP1_CIF_ISP_IS_H_SIZE_SHD (RKISP1_CIF_ISP_IS_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_IS_V_SIZE_SHD (RKISP1_CIF_ISP_IS_BASE + 0x00000030) - -#define RKISP1_CIF_ISP_HIST_BASE 0x00002400 - -#define RKISP1_CIF_ISP_HIST_PROP (RKISP1_CIF_ISP_HIST_BASE + 0x00000000) -#define RKISP1_CIF_ISP_HIST_H_OFFS (RKISP1_CIF_ISP_HIST_BASE + 0x00000004) -#define RKISP1_CIF_ISP_HIST_V_OFFS (RKISP1_CIF_ISP_HIST_BASE + 0x00000008) -#define RKISP1_CIF_ISP_HIST_H_SIZE (RKISP1_CIF_ISP_HIST_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_HIST_V_SIZE (RKISP1_CIF_ISP_HIST_BASE + 0x00000010) -#define RKISP1_CIF_ISP_HIST_BIN_0 (RKISP1_CIF_ISP_HIST_BASE + 0x00000014) -#define RKISP1_CIF_ISP_HIST_BIN_1 (RKISP1_CIF_ISP_HIST_BASE + 0x00000018) -#define RKISP1_CIF_ISP_HIST_BIN_2 (RKISP1_CIF_ISP_HIST_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_HIST_BIN_3 (RKISP1_CIF_ISP_HIST_BASE + 0x00000020) -#define RKISP1_CIF_ISP_HIST_BIN_4 (RKISP1_CIF_ISP_HIST_BASE + 0x00000024) -#define RKISP1_CIF_ISP_HIST_BIN_5 (RKISP1_CIF_ISP_HIST_BASE + 0x00000028) -#define RKISP1_CIF_ISP_HIST_BIN_6 (RKISP1_CIF_ISP_HIST_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_HIST_BIN_7 (RKISP1_CIF_ISP_HIST_BASE + 0x00000030) -#define RKISP1_CIF_ISP_HIST_BIN_8 (RKISP1_CIF_ISP_HIST_BASE + 0x00000034) -#define RKISP1_CIF_ISP_HIST_BIN_9 (RKISP1_CIF_ISP_HIST_BASE + 0x00000038) -#define RKISP1_CIF_ISP_HIST_BIN_10 (RKISP1_CIF_ISP_HIST_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_HIST_BIN_11 (RKISP1_CIF_ISP_HIST_BASE + 0x00000040) -#define RKISP1_CIF_ISP_HIST_BIN_12 (RKISP1_CIF_ISP_HIST_BASE + 0x00000044) -#define RKISP1_CIF_ISP_HIST_BIN_13 (RKISP1_CIF_ISP_HIST_BASE + 0x00000048) -#define RKISP1_CIF_ISP_HIST_BIN_14 (RKISP1_CIF_ISP_HIST_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_HIST_BIN_15 (RKISP1_CIF_ISP_HIST_BASE + 0x00000050) -#define RKISP1_CIF_ISP_HIST_WEIGHT_00TO30 (RKISP1_CIF_ISP_HIST_BASE + 0x00000054) -#define RKISP1_CIF_ISP_HIST_WEIGHT_40TO21 (RKISP1_CIF_ISP_HIST_BASE + 0x00000058) -#define RKISP1_CIF_ISP_HIST_WEIGHT_31TO12 (RKISP1_CIF_ISP_HIST_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_HIST_WEIGHT_22TO03 (RKISP1_CIF_ISP_HIST_BASE + 0x00000060) -#define RKISP1_CIF_ISP_HIST_WEIGHT_13TO43 (RKISP1_CIF_ISP_HIST_BASE + 0x00000064) -#define RKISP1_CIF_ISP_HIST_WEIGHT_04TO34 (RKISP1_CIF_ISP_HIST_BASE + 0x00000068) -#define RKISP1_CIF_ISP_HIST_WEIGHT_44 (RKISP1_CIF_ISP_HIST_BASE + 0x0000006C) - -#define RKISP1_CIF_ISP_FILT_BASE 0x00002500 -#define RKISP1_CIF_ISP_FILT_MODE (RKISP1_CIF_ISP_FILT_BASE + 0x00000000) -#define RKISP1_CIF_ISP_FILT_THRESH_BL0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000028) -#define RKISP1_CIF_ISP_FILT_THRESH_BL1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000002c) -#define RKISP1_CIF_ISP_FILT_THRESH_SH0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000030) -#define RKISP1_CIF_ISP_FILT_THRESH_SH1 (RKISP1_CIF_ISP_FILT_BASE + 0x00000034) -#define RKISP1_CIF_ISP_FILT_LUM_WEIGHT (RKISP1_CIF_ISP_FILT_BASE + 0x00000038) -#define RKISP1_CIF_ISP_FILT_FAC_SH1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000003c) -#define RKISP1_CIF_ISP_FILT_FAC_SH0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000040) -#define RKISP1_CIF_ISP_FILT_FAC_MID (RKISP1_CIF_ISP_FILT_BASE + 0x00000044) -#define RKISP1_CIF_ISP_FILT_FAC_BL0 (RKISP1_CIF_ISP_FILT_BASE + 0x00000048) -#define RKISP1_CIF_ISP_FILT_FAC_BL1 (RKISP1_CIF_ISP_FILT_BASE + 0x0000004C) - -#define RKISP1_CIF_ISP_CAC_BASE 0x00002580 -#define RKISP1_CIF_ISP_CAC_CTRL (RKISP1_CIF_ISP_CAC_BASE + 0x00000000) -#define RKISP1_CIF_ISP_CAC_COUNT_START (RKISP1_CIF_ISP_CAC_BASE + 0x00000004) -#define RKISP1_CIF_ISP_CAC_A (RKISP1_CIF_ISP_CAC_BASE + 0x00000008) -#define RKISP1_CIF_ISP_CAC_B (RKISP1_CIF_ISP_CAC_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_CAC_C (RKISP1_CIF_ISP_CAC_BASE + 0x00000010) -#define RKISP1_CIF_ISP_X_NORM (RKISP1_CIF_ISP_CAC_BASE + 0x00000014) -#define RKISP1_CIF_ISP_Y_NORM (RKISP1_CIF_ISP_CAC_BASE + 0x00000018) - -#define RKISP1_CIF_ISP_EXP_BASE 0x00002600 -#define RKISP1_CIF_ISP_EXP_CTRL (RKISP1_CIF_ISP_EXP_BASE + 0x00000000) -#define RKISP1_CIF_ISP_EXP_H_OFFSET (RKISP1_CIF_ISP_EXP_BASE + 0x00000004) -#define RKISP1_CIF_ISP_EXP_V_OFFSET (RKISP1_CIF_ISP_EXP_BASE + 0x00000008) -#define RKISP1_CIF_ISP_EXP_H_SIZE (RKISP1_CIF_ISP_EXP_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_EXP_V_SIZE (RKISP1_CIF_ISP_EXP_BASE + 0x00000010) -#define RKISP1_CIF_ISP_EXP_MEAN_00 (RKISP1_CIF_ISP_EXP_BASE + 0x00000014) -#define RKISP1_CIF_ISP_EXP_MEAN_10 (RKISP1_CIF_ISP_EXP_BASE + 0x00000018) -#define RKISP1_CIF_ISP_EXP_MEAN_20 (RKISP1_CIF_ISP_EXP_BASE + 0x0000001c) -#define RKISP1_CIF_ISP_EXP_MEAN_30 (RKISP1_CIF_ISP_EXP_BASE + 0x00000020) -#define RKISP1_CIF_ISP_EXP_MEAN_40 (RKISP1_CIF_ISP_EXP_BASE + 0x00000024) -#define RKISP1_CIF_ISP_EXP_MEAN_01 (RKISP1_CIF_ISP_EXP_BASE + 0x00000028) -#define RKISP1_CIF_ISP_EXP_MEAN_11 (RKISP1_CIF_ISP_EXP_BASE + 0x0000002c) -#define RKISP1_CIF_ISP_EXP_MEAN_21 (RKISP1_CIF_ISP_EXP_BASE + 0x00000030) -#define RKISP1_CIF_ISP_EXP_MEAN_31 (RKISP1_CIF_ISP_EXP_BASE + 0x00000034) -#define RKISP1_CIF_ISP_EXP_MEAN_41 (RKISP1_CIF_ISP_EXP_BASE + 0x00000038) -#define RKISP1_CIF_ISP_EXP_MEAN_02 (RKISP1_CIF_ISP_EXP_BASE + 0x0000003c) -#define RKISP1_CIF_ISP_EXP_MEAN_12 (RKISP1_CIF_ISP_EXP_BASE + 0x00000040) -#define RKISP1_CIF_ISP_EXP_MEAN_22 (RKISP1_CIF_ISP_EXP_BASE + 0x00000044) -#define RKISP1_CIF_ISP_EXP_MEAN_32 (RKISP1_CIF_ISP_EXP_BASE + 0x00000048) -#define RKISP1_CIF_ISP_EXP_MEAN_42 (RKISP1_CIF_ISP_EXP_BASE + 0x0000004c) -#define RKISP1_CIF_ISP_EXP_MEAN_03 (RKISP1_CIF_ISP_EXP_BASE + 0x00000050) -#define RKISP1_CIF_ISP_EXP_MEAN_13 (RKISP1_CIF_ISP_EXP_BASE + 0x00000054) -#define RKISP1_CIF_ISP_EXP_MEAN_23 (RKISP1_CIF_ISP_EXP_BASE + 0x00000058) -#define RKISP1_CIF_ISP_EXP_MEAN_33 (RKISP1_CIF_ISP_EXP_BASE + 0x0000005c) -#define RKISP1_CIF_ISP_EXP_MEAN_43 (RKISP1_CIF_ISP_EXP_BASE + 0x00000060) -#define RKISP1_CIF_ISP_EXP_MEAN_04 (RKISP1_CIF_ISP_EXP_BASE + 0x00000064) -#define RKISP1_CIF_ISP_EXP_MEAN_14 (RKISP1_CIF_ISP_EXP_BASE + 0x00000068) -#define RKISP1_CIF_ISP_EXP_MEAN_24 (RKISP1_CIF_ISP_EXP_BASE + 0x0000006c) -#define RKISP1_CIF_ISP_EXP_MEAN_34 (RKISP1_CIF_ISP_EXP_BASE + 0x00000070) -#define RKISP1_CIF_ISP_EXP_MEAN_44 (RKISP1_CIF_ISP_EXP_BASE + 0x00000074) - -#define RKISP1_CIF_ISP_BLS_BASE 0x00002700 -#define RKISP1_CIF_ISP_BLS_CTRL (RKISP1_CIF_ISP_BLS_BASE + 0x00000000) -#define RKISP1_CIF_ISP_BLS_SAMPLES (RKISP1_CIF_ISP_BLS_BASE + 0x00000004) -#define RKISP1_CIF_ISP_BLS_H1_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000008) -#define RKISP1_CIF_ISP_BLS_H1_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x0000000c) -#define RKISP1_CIF_ISP_BLS_V1_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000010) -#define RKISP1_CIF_ISP_BLS_V1_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x00000014) -#define RKISP1_CIF_ISP_BLS_H2_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000018) -#define RKISP1_CIF_ISP_BLS_H2_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x0000001c) -#define RKISP1_CIF_ISP_BLS_V2_START (RKISP1_CIF_ISP_BLS_BASE + 0x00000020) -#define RKISP1_CIF_ISP_BLS_V2_STOP (RKISP1_CIF_ISP_BLS_BASE + 0x00000024) -#define RKISP1_CIF_ISP_BLS_A_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000028) -#define RKISP1_CIF_ISP_BLS_B_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x0000002c) -#define RKISP1_CIF_ISP_BLS_C_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000030) -#define RKISP1_CIF_ISP_BLS_D_FIXED (RKISP1_CIF_ISP_BLS_BASE + 0x00000034) -#define RKISP1_CIF_ISP_BLS_A_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000038) -#define RKISP1_CIF_ISP_BLS_B_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x0000003c) -#define RKISP1_CIF_ISP_BLS_C_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000040) -#define RKISP1_CIF_ISP_BLS_D_MEASURED (RKISP1_CIF_ISP_BLS_BASE + 0x00000044) - -#define RKISP1_CIF_ISP_DPF_BASE 0x00002800 -#define RKISP1_CIF_ISP_DPF_MODE (RKISP1_CIF_ISP_DPF_BASE + 0x00000000) -#define RKISP1_CIF_ISP_DPF_STRENGTH_R (RKISP1_CIF_ISP_DPF_BASE + 0x00000004) -#define RKISP1_CIF_ISP_DPF_STRENGTH_G (RKISP1_CIF_ISP_DPF_BASE + 0x00000008) -#define RKISP1_CIF_ISP_DPF_STRENGTH_B (RKISP1_CIF_ISP_DPF_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_DPF_S_WEIGHT_G_1_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000010) -#define RKISP1_CIF_ISP_DPF_S_WEIGHT_G_5_6 (RKISP1_CIF_ISP_DPF_BASE + 0x00000014) -#define RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_1_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000018) -#define RKISP1_CIF_ISP_DPF_S_WEIGHT_RB_5_6 (RKISP1_CIF_ISP_DPF_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_0 (RKISP1_CIF_ISP_DPF_BASE + 0x00000020) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_1 (RKISP1_CIF_ISP_DPF_BASE + 0x00000024) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_2 (RKISP1_CIF_ISP_DPF_BASE + 0x00000028) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_3 (RKISP1_CIF_ISP_DPF_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_4 (RKISP1_CIF_ISP_DPF_BASE + 0x00000030) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_5 (RKISP1_CIF_ISP_DPF_BASE + 0x00000034) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_6 (RKISP1_CIF_ISP_DPF_BASE + 0x00000038) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_7 (RKISP1_CIF_ISP_DPF_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_8 (RKISP1_CIF_ISP_DPF_BASE + 0x00000040) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_9 (RKISP1_CIF_ISP_DPF_BASE + 0x00000044) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_10 (RKISP1_CIF_ISP_DPF_BASE + 0x00000048) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_11 (RKISP1_CIF_ISP_DPF_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_12 (RKISP1_CIF_ISP_DPF_BASE + 0x00000050) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_13 (RKISP1_CIF_ISP_DPF_BASE + 0x00000054) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_14 (RKISP1_CIF_ISP_DPF_BASE + 0x00000058) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_15 (RKISP1_CIF_ISP_DPF_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_DPF_NULL_COEFF_16 (RKISP1_CIF_ISP_DPF_BASE + 0x00000060) -#define RKISP1_CIF_ISP_DPF_NF_GAIN_R (RKISP1_CIF_ISP_DPF_BASE + 0x00000064) -#define RKISP1_CIF_ISP_DPF_NF_GAIN_GR (RKISP1_CIF_ISP_DPF_BASE + 0x00000068) -#define RKISP1_CIF_ISP_DPF_NF_GAIN_GB (RKISP1_CIF_ISP_DPF_BASE + 0x0000006C) -#define RKISP1_CIF_ISP_DPF_NF_GAIN_B (RKISP1_CIF_ISP_DPF_BASE + 0x00000070) - -#define RKISP1_CIF_ISP_DPCC_BASE 0x00002900 -#define RKISP1_CIF_ISP_DPCC_MODE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000000) -#define RKISP1_CIF_ISP_DPCC_OUTPUT_MODE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000004) -#define RKISP1_CIF_ISP_DPCC_SET_USE (RKISP1_CIF_ISP_DPCC_BASE + 0x00000008) -#define RKISP1_CIF_ISP_DPCC_METHODS_SET_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_DPCC_METHODS_SET_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000010) -#define RKISP1_CIF_ISP_DPCC_METHODS_SET_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000014) -#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000018) -#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_DPCC_PG_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000020) -#define RKISP1_CIF_ISP_DPCC_RND_THRESH_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000024) -#define RKISP1_CIF_ISP_DPCC_RG_FAC_1 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000028) -#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000030) -#define RKISP1_CIF_ISP_DPCC_PG_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000034) -#define RKISP1_CIF_ISP_DPCC_RND_THRESH_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000038) -#define RKISP1_CIF_ISP_DPCC_RG_FAC_2 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_DPCC_LINE_THRESH_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000040) -#define RKISP1_CIF_ISP_DPCC_LINE_MAD_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000044) -#define RKISP1_CIF_ISP_DPCC_PG_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000048) -#define RKISP1_CIF_ISP_DPCC_RND_THRESH_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_DPCC_RG_FAC_3 (RKISP1_CIF_ISP_DPCC_BASE + 0x00000050) -#define RKISP1_CIF_ISP_DPCC_RO_LIMITS (RKISP1_CIF_ISP_DPCC_BASE + 0x00000054) -#define RKISP1_CIF_ISP_DPCC_RND_OFFS (RKISP1_CIF_ISP_DPCC_BASE + 0x00000058) -#define RKISP1_CIF_ISP_DPCC_BPT_CTRL (RKISP1_CIF_ISP_DPCC_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_DPCC_BPT_NUMBER (RKISP1_CIF_ISP_DPCC_BASE + 0x00000060) -#define RKISP1_CIF_ISP_DPCC_BPT_ADDR (RKISP1_CIF_ISP_DPCC_BASE + 0x00000064) -#define RKISP1_CIF_ISP_DPCC_BPT_DATA (RKISP1_CIF_ISP_DPCC_BASE + 0x00000068) - -#define RKISP1_CIF_ISP_WDR_BASE 0x00002A00 -#define RKISP1_CIF_ISP_WDR_CTRL (RKISP1_CIF_ISP_WDR_BASE + 0x00000000) -#define RKISP1_CIF_ISP_WDR_TONECURVE_1 (RKISP1_CIF_ISP_WDR_BASE + 0x00000004) -#define RKISP1_CIF_ISP_WDR_TONECURVE_2 (RKISP1_CIF_ISP_WDR_BASE + 0x00000008) -#define RKISP1_CIF_ISP_WDR_TONECURVE_3 (RKISP1_CIF_ISP_WDR_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_4 (RKISP1_CIF_ISP_WDR_BASE + 0x00000010) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_0 (RKISP1_CIF_ISP_WDR_BASE + 0x00000014) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_1 (RKISP1_CIF_ISP_WDR_BASE + 0x00000018) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_2 (RKISP1_CIF_ISP_WDR_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_3 (RKISP1_CIF_ISP_WDR_BASE + 0x00000020) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_4 (RKISP1_CIF_ISP_WDR_BASE + 0x00000024) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_5 (RKISP1_CIF_ISP_WDR_BASE + 0x00000028) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_6 (RKISP1_CIF_ISP_WDR_BASE + 0x0000002C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_7 (RKISP1_CIF_ISP_WDR_BASE + 0x00000030) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_8 (RKISP1_CIF_ISP_WDR_BASE + 0x00000034) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_9 (RKISP1_CIF_ISP_WDR_BASE + 0x00000038) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_10 (RKISP1_CIF_ISP_WDR_BASE + 0x0000003C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_11 (RKISP1_CIF_ISP_WDR_BASE + 0x00000040) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_12 (RKISP1_CIF_ISP_WDR_BASE + 0x00000044) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_13 (RKISP1_CIF_ISP_WDR_BASE + 0x00000048) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_14 (RKISP1_CIF_ISP_WDR_BASE + 0x0000004C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_15 (RKISP1_CIF_ISP_WDR_BASE + 0x00000050) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_16 (RKISP1_CIF_ISP_WDR_BASE + 0x00000054) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_17 (RKISP1_CIF_ISP_WDR_BASE + 0x00000058) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_18 (RKISP1_CIF_ISP_WDR_BASE + 0x0000005C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_19 (RKISP1_CIF_ISP_WDR_BASE + 0x00000060) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_20 (RKISP1_CIF_ISP_WDR_BASE + 0x00000064) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_21 (RKISP1_CIF_ISP_WDR_BASE + 0x00000068) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_22 (RKISP1_CIF_ISP_WDR_BASE + 0x0000006C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_23 (RKISP1_CIF_ISP_WDR_BASE + 0x00000070) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_24 (RKISP1_CIF_ISP_WDR_BASE + 0x00000074) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_25 (RKISP1_CIF_ISP_WDR_BASE + 0x00000078) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_26 (RKISP1_CIF_ISP_WDR_BASE + 0x0000007C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_27 (RKISP1_CIF_ISP_WDR_BASE + 0x00000080) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_28 (RKISP1_CIF_ISP_WDR_BASE + 0x00000084) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_29 (RKISP1_CIF_ISP_WDR_BASE + 0x00000088) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_30 (RKISP1_CIF_ISP_WDR_BASE + 0x0000008C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_31 (RKISP1_CIF_ISP_WDR_BASE + 0x00000090) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_32 (RKISP1_CIF_ISP_WDR_BASE + 0x00000094) -#define RKISP1_CIF_ISP_WDR_OFFSET (RKISP1_CIF_ISP_WDR_BASE + 0x00000098) -#define RKISP1_CIF_ISP_WDR_DELTAMIN (RKISP1_CIF_ISP_WDR_BASE + 0x0000009C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_1_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_2_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_3_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000A8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_4_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000AC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_0_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_1_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_2_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000B8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_3_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000BC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_4_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_5_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_6_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000C8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_7_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000CC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_8_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_9_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_10_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000D8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_11_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000DC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_12_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_13_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_14_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000E8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_15_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000EC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_16_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F0) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_17_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F4) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_18_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000F8) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_19_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x000000FC) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_20_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000100) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_21_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000104) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_22_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000108) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_23_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000010C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_24_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000110) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_25_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000114) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_26_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000118) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_27_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000011C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_28_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000120) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_29_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000124) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_30_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000128) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_31_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x0000012C) -#define RKISP1_CIF_ISP_WDR_TONECURVE_YM_32_SHD (RKISP1_CIF_ISP_WDR_BASE + 0x00000130) - -#define RKISP1_CIF_ISP_VSM_BASE 0x00002F00 -#define RKISP1_CIF_ISP_VSM_MODE (RKISP1_CIF_ISP_VSM_BASE + 0x00000000) -#define RKISP1_CIF_ISP_VSM_H_OFFS (RKISP1_CIF_ISP_VSM_BASE + 0x00000004) -#define RKISP1_CIF_ISP_VSM_V_OFFS (RKISP1_CIF_ISP_VSM_BASE + 0x00000008) -#define RKISP1_CIF_ISP_VSM_H_SIZE (RKISP1_CIF_ISP_VSM_BASE + 0x0000000C) -#define RKISP1_CIF_ISP_VSM_V_SIZE (RKISP1_CIF_ISP_VSM_BASE + 0x00000010) -#define RKISP1_CIF_ISP_VSM_H_SEGMENTS (RKISP1_CIF_ISP_VSM_BASE + 0x00000014) -#define RKISP1_CIF_ISP_VSM_V_SEGMENTS (RKISP1_CIF_ISP_VSM_BASE + 0x00000018) -#define RKISP1_CIF_ISP_VSM_DELTA_H (RKISP1_CIF_ISP_VSM_BASE + 0x0000001C) -#define RKISP1_CIF_ISP_VSM_DELTA_V (RKISP1_CIF_ISP_VSM_BASE + 0x00000020) - -#endif /* _RKISP1_REGS_H */ diff --git a/drivers/staging/media/rkisp1/rkisp1-resizer.c b/drivers/staging/media/rkisp1/rkisp1-resizer.c deleted file mode 100644 index 7ca5b47c5bf5..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-resizer.c +++ /dev/null @@ -1,846 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - V4l resizer device - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include "rkisp1-common.h" - -#define RKISP1_RSZ_SP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_selfpath" -#define RKISP1_RSZ_MP_DEV_NAME RKISP1_DRIVER_NAME "_resizer_mainpath" - -#define RKISP1_DEF_FMT MEDIA_BUS_FMT_YUYV8_2X8 -#define RKISP1_DEF_PIXEL_ENC V4L2_PIXEL_ENC_YUV - -struct rkisp1_rsz_yuv_mbus_info { - u32 mbus_code; - u32 hdiv; - u32 vdiv; -}; - -static const struct rkisp1_rsz_yuv_mbus_info rkisp1_rsz_yuv_src_formats[] = { - { - .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, /* YUV422 */ - .hdiv = 2, - .vdiv = 1, - }, - { - .mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8, /* YUV420 */ - .hdiv = 2, - .vdiv = 2, - }, -}; - -static const struct rkisp1_rsz_yuv_mbus_info *rkisp1_rsz_get_yuv_mbus_info(u32 mbus_code) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rkisp1_rsz_yuv_src_formats); i++) { - if (rkisp1_rsz_yuv_src_formats[i].mbus_code == mbus_code) - return &rkisp1_rsz_yuv_src_formats[i]; - } - - return NULL; -} - -enum rkisp1_shadow_regs_when { - RKISP1_SHADOW_REGS_SYNC, - RKISP1_SHADOW_REGS_ASYNC, -}; - -struct rkisp1_rsz_config { - /* constrains */ - const int max_rsz_width; - const int max_rsz_height; - const int min_rsz_width; - const int min_rsz_height; - /* registers */ - struct { - u32 ctrl; - u32 ctrl_shd; - u32 scale_hy; - u32 scale_hcr; - u32 scale_hcb; - u32 scale_vy; - u32 scale_vc; - u32 scale_lut; - u32 scale_lut_addr; - u32 scale_hy_shd; - u32 scale_hcr_shd; - u32 scale_hcb_shd; - u32 scale_vy_shd; - u32 scale_vc_shd; - u32 phase_hy; - u32 phase_hc; - u32 phase_vy; - u32 phase_vc; - u32 phase_hy_shd; - u32 phase_hc_shd; - u32 phase_vy_shd; - u32 phase_vc_shd; - } rsz; - struct { - u32 ctrl; - u32 yuvmode_mask; - u32 rawmode_mask; - u32 h_offset; - u32 v_offset; - u32 h_size; - u32 v_size; - } dual_crop; -}; - -static const struct rkisp1_rsz_config rkisp1_rsz_config_mp = { - /* constraints */ - .max_rsz_width = RKISP1_RSZ_MP_SRC_MAX_WIDTH, - .max_rsz_height = RKISP1_RSZ_MP_SRC_MAX_HEIGHT, - .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH, - .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT, - /* registers */ - .rsz = { - .ctrl = RKISP1_CIF_MRSZ_CTRL, - .scale_hy = RKISP1_CIF_MRSZ_SCALE_HY, - .scale_hcr = RKISP1_CIF_MRSZ_SCALE_HCR, - .scale_hcb = RKISP1_CIF_MRSZ_SCALE_HCB, - .scale_vy = RKISP1_CIF_MRSZ_SCALE_VY, - .scale_vc = RKISP1_CIF_MRSZ_SCALE_VC, - .scale_lut = RKISP1_CIF_MRSZ_SCALE_LUT, - .scale_lut_addr = RKISP1_CIF_MRSZ_SCALE_LUT_ADDR, - .scale_hy_shd = RKISP1_CIF_MRSZ_SCALE_HY_SHD, - .scale_hcr_shd = RKISP1_CIF_MRSZ_SCALE_HCR_SHD, - .scale_hcb_shd = RKISP1_CIF_MRSZ_SCALE_HCB_SHD, - .scale_vy_shd = RKISP1_CIF_MRSZ_SCALE_VY_SHD, - .scale_vc_shd = RKISP1_CIF_MRSZ_SCALE_VC_SHD, - .phase_hy = RKISP1_CIF_MRSZ_PHASE_HY, - .phase_hc = RKISP1_CIF_MRSZ_PHASE_HC, - .phase_vy = RKISP1_CIF_MRSZ_PHASE_VY, - .phase_vc = RKISP1_CIF_MRSZ_PHASE_VC, - .ctrl_shd = RKISP1_CIF_MRSZ_CTRL_SHD, - .phase_hy_shd = RKISP1_CIF_MRSZ_PHASE_HY_SHD, - .phase_hc_shd = RKISP1_CIF_MRSZ_PHASE_HC_SHD, - .phase_vy_shd = RKISP1_CIF_MRSZ_PHASE_VY_SHD, - .phase_vc_shd = RKISP1_CIF_MRSZ_PHASE_VC_SHD, - }, - .dual_crop = { - .ctrl = RKISP1_CIF_DUAL_CROP_CTRL, - .yuvmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_YUV, - .rawmode_mask = RKISP1_CIF_DUAL_CROP_MP_MODE_RAW, - .h_offset = RKISP1_CIF_DUAL_CROP_M_H_OFFS, - .v_offset = RKISP1_CIF_DUAL_CROP_M_V_OFFS, - .h_size = RKISP1_CIF_DUAL_CROP_M_H_SIZE, - .v_size = RKISP1_CIF_DUAL_CROP_M_V_SIZE, - }, -}; - -static const struct rkisp1_rsz_config rkisp1_rsz_config_sp = { - /* constraints */ - .max_rsz_width = RKISP1_RSZ_SP_SRC_MAX_WIDTH, - .max_rsz_height = RKISP1_RSZ_SP_SRC_MAX_HEIGHT, - .min_rsz_width = RKISP1_RSZ_SRC_MIN_WIDTH, - .min_rsz_height = RKISP1_RSZ_SRC_MIN_HEIGHT, - /* registers */ - .rsz = { - .ctrl = RKISP1_CIF_SRSZ_CTRL, - .scale_hy = RKISP1_CIF_SRSZ_SCALE_HY, - .scale_hcr = RKISP1_CIF_SRSZ_SCALE_HCR, - .scale_hcb = RKISP1_CIF_SRSZ_SCALE_HCB, - .scale_vy = RKISP1_CIF_SRSZ_SCALE_VY, - .scale_vc = RKISP1_CIF_SRSZ_SCALE_VC, - .scale_lut = RKISP1_CIF_SRSZ_SCALE_LUT, - .scale_lut_addr = RKISP1_CIF_SRSZ_SCALE_LUT_ADDR, - .scale_hy_shd = RKISP1_CIF_SRSZ_SCALE_HY_SHD, - .scale_hcr_shd = RKISP1_CIF_SRSZ_SCALE_HCR_SHD, - .scale_hcb_shd = RKISP1_CIF_SRSZ_SCALE_HCB_SHD, - .scale_vy_shd = RKISP1_CIF_SRSZ_SCALE_VY_SHD, - .scale_vc_shd = RKISP1_CIF_SRSZ_SCALE_VC_SHD, - .phase_hy = RKISP1_CIF_SRSZ_PHASE_HY, - .phase_hc = RKISP1_CIF_SRSZ_PHASE_HC, - .phase_vy = RKISP1_CIF_SRSZ_PHASE_VY, - .phase_vc = RKISP1_CIF_SRSZ_PHASE_VC, - .ctrl_shd = RKISP1_CIF_SRSZ_CTRL_SHD, - .phase_hy_shd = RKISP1_CIF_SRSZ_PHASE_HY_SHD, - .phase_hc_shd = RKISP1_CIF_SRSZ_PHASE_HC_SHD, - .phase_vy_shd = RKISP1_CIF_SRSZ_PHASE_VY_SHD, - .phase_vc_shd = RKISP1_CIF_SRSZ_PHASE_VC_SHD, - }, - .dual_crop = { - .ctrl = RKISP1_CIF_DUAL_CROP_CTRL, - .yuvmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_YUV, - .rawmode_mask = RKISP1_CIF_DUAL_CROP_SP_MODE_RAW, - .h_offset = RKISP1_CIF_DUAL_CROP_S_H_OFFS, - .v_offset = RKISP1_CIF_DUAL_CROP_S_V_OFFS, - .h_size = RKISP1_CIF_DUAL_CROP_S_H_SIZE, - .v_size = RKISP1_CIF_DUAL_CROP_S_V_SIZE, - }, -}; - -static struct v4l2_mbus_framefmt * -rkisp1_rsz_get_pad_fmt(struct rkisp1_resizer *rsz, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&rsz->sd, cfg, pad); - else - return v4l2_subdev_get_try_format(&rsz->sd, rsz->pad_cfg, pad); -} - -static struct v4l2_rect * -rkisp1_rsz_get_pad_crop(struct rkisp1_resizer *rsz, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, u32 which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_crop(&rsz->sd, cfg, pad); - else - return v4l2_subdev_get_try_crop(&rsz->sd, rsz->pad_cfg, pad); -} - -/* ---------------------------------------------------------------------------- - * Dual crop hw configs - */ - -static void rkisp1_dcrop_disable(struct rkisp1_resizer *rsz, - enum rkisp1_shadow_regs_when when) -{ - u32 dc_ctrl = rkisp1_read(rsz->rkisp1, rsz->config->dual_crop.ctrl); - u32 mask = ~(rsz->config->dual_crop.yuvmode_mask | - rsz->config->dual_crop.rawmode_mask); - - dc_ctrl &= mask; - if (when == RKISP1_SHADOW_REGS_ASYNC) - dc_ctrl |= RKISP1_CIF_DUAL_CROP_GEN_CFG_UPD; - else - dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; - rkisp1_write(rsz->rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); -} - -/* configure dual-crop unit */ -static void rkisp1_dcrop_config(struct rkisp1_resizer *rsz) -{ - struct rkisp1_device *rkisp1 = rsz->rkisp1; - struct v4l2_mbus_framefmt *sink_fmt; - struct v4l2_rect *sink_crop; - u32 dc_ctrl; - - sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, - V4L2_SUBDEV_FORMAT_ACTIVE); - sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, - V4L2_SUBDEV_FORMAT_ACTIVE); - - if (sink_crop->width == sink_fmt->width && - sink_crop->height == sink_fmt->height && - sink_crop->left == 0 && sink_crop->top == 0) { - rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_SYNC); - dev_dbg(rkisp1->dev, "capture %d crop disabled\n", rsz->id); - return; - } - - dc_ctrl = rkisp1_read(rkisp1, rsz->config->dual_crop.ctrl); - rkisp1_write(rkisp1, sink_crop->left, rsz->config->dual_crop.h_offset); - rkisp1_write(rkisp1, sink_crop->top, rsz->config->dual_crop.v_offset); - rkisp1_write(rkisp1, sink_crop->width, rsz->config->dual_crop.h_size); - rkisp1_write(rkisp1, sink_crop->height, rsz->config->dual_crop.v_size); - dc_ctrl |= rsz->config->dual_crop.yuvmode_mask; - dc_ctrl |= RKISP1_CIF_DUAL_CROP_CFG_UPD; - rkisp1_write(rkisp1, dc_ctrl, rsz->config->dual_crop.ctrl); - - dev_dbg(rkisp1->dev, "stream %d crop: %dx%d -> %dx%d\n", rsz->id, - sink_fmt->width, sink_fmt->height, - sink_crop->width, sink_crop->height); -} - -/* ---------------------------------------------------------------------------- - * Resizer hw configs - */ - -static void rkisp1_rsz_dump_regs(struct rkisp1_resizer *rsz) -{ - dev_dbg(rsz->rkisp1->dev, - "RSZ_CTRL 0x%08x/0x%08x\n" - "RSZ_SCALE_HY %d/%d\n" - "RSZ_SCALE_HCB %d/%d\n" - "RSZ_SCALE_HCR %d/%d\n" - "RSZ_SCALE_VY %d/%d\n" - "RSZ_SCALE_VC %d/%d\n" - "RSZ_PHASE_HY %d/%d\n" - "RSZ_PHASE_HC %d/%d\n" - "RSZ_PHASE_VY %d/%d\n" - "RSZ_PHASE_VC %d/%d\n", - rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hy_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcb_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_hcr_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vy_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.scale_vc_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hy_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_hc_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vy_shd), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc), - rkisp1_read(rsz->rkisp1, rsz->config->rsz.phase_vc_shd)); -} - -static void rkisp1_rsz_update_shadow(struct rkisp1_resizer *rsz, - enum rkisp1_shadow_regs_when when) -{ - u32 ctrl_cfg = rkisp1_read(rsz->rkisp1, rsz->config->rsz.ctrl); - - if (when == RKISP1_SHADOW_REGS_ASYNC) - ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD_AUTO; - else - ctrl_cfg |= RKISP1_CIF_RSZ_CTRL_CFG_UPD; - - rkisp1_write(rsz->rkisp1, ctrl_cfg, rsz->config->rsz.ctrl); -} - -static u32 rkisp1_rsz_calc_ratio(u32 len_sink, u32 len_src) -{ - if (len_sink < len_src) - return ((len_sink - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / - (len_src - 1); - - return ((len_src - 1) * RKISP1_CIF_RSZ_SCALER_FACTOR) / - (len_sink - 1) + 1; -} - -static void rkisp1_rsz_disable(struct rkisp1_resizer *rsz, - enum rkisp1_shadow_regs_when when) -{ - rkisp1_write(rsz->rkisp1, 0, rsz->config->rsz.ctrl); - - if (when == RKISP1_SHADOW_REGS_SYNC) - rkisp1_rsz_update_shadow(rsz, when); -} - -static void rkisp1_rsz_config_regs(struct rkisp1_resizer *rsz, - struct v4l2_rect *sink_y, - struct v4l2_rect *sink_c, - struct v4l2_rect *src_y, - struct v4l2_rect *src_c, - enum rkisp1_shadow_regs_when when) -{ - struct rkisp1_device *rkisp1 = rsz->rkisp1; - u32 ratio, rsz_ctrl = 0; - unsigned int i; - - /* No phase offset */ - rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hy); - rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_hc); - rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vy); - rkisp1_write(rkisp1, 0, rsz->config->rsz.phase_vc); - - /* Linear interpolation */ - for (i = 0; i < 64; i++) { - rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut_addr); - rkisp1_write(rkisp1, i, rsz->config->rsz.scale_lut); - } - - if (sink_y->width != src_y->width) { - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_ENABLE; - if (sink_y->width < src_y->width) - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HY_UP; - ratio = rkisp1_rsz_calc_ratio(sink_y->width, src_y->width); - rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hy); - } - - if (sink_c->width != src_c->width) { - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_ENABLE; - if (sink_c->width < src_c->width) - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_HC_UP; - ratio = rkisp1_rsz_calc_ratio(sink_c->width, src_c->width); - rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcb); - rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_hcr); - } - - if (sink_y->height != src_y->height) { - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_ENABLE; - if (sink_y->height < src_y->height) - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VY_UP; - ratio = rkisp1_rsz_calc_ratio(sink_y->height, src_y->height); - rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vy); - } - - if (sink_c->height != src_c->height) { - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_ENABLE; - if (sink_c->height < src_c->height) - rsz_ctrl |= RKISP1_CIF_RSZ_CTRL_SCALE_VC_UP; - ratio = rkisp1_rsz_calc_ratio(sink_c->height, src_c->height); - rkisp1_write(rkisp1, ratio, rsz->config->rsz.scale_vc); - } - - rkisp1_write(rkisp1, rsz_ctrl, rsz->config->rsz.ctrl); - - rkisp1_rsz_update_shadow(rsz, when); -} - -static void rkisp1_rsz_config(struct rkisp1_resizer *rsz, - enum rkisp1_shadow_regs_when when) -{ - const struct rkisp1_rsz_yuv_mbus_info *sink_yuv_info, *src_yuv_info; - struct v4l2_rect sink_y, sink_c, src_y, src_c; - struct v4l2_mbus_framefmt *src_fmt, *sink_fmt; - struct v4l2_rect *sink_crop; - - sink_crop = rkisp1_rsz_get_pad_crop(rsz, NULL, RKISP1_RSZ_PAD_SINK, - V4L2_SUBDEV_FORMAT_ACTIVE); - src_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SRC, - V4L2_SUBDEV_FORMAT_ACTIVE); - src_yuv_info = rkisp1_rsz_get_yuv_mbus_info(src_fmt->code); - sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, NULL, RKISP1_RSZ_PAD_SINK, - V4L2_SUBDEV_FORMAT_ACTIVE); - sink_yuv_info = rkisp1_rsz_get_yuv_mbus_info(sink_fmt->code); - - /* - * The resizer only works on yuv formats, - * so return if it is bayer format. - */ - if (rsz->pixel_enc == V4L2_PIXEL_ENC_BAYER) { - rkisp1_rsz_disable(rsz, when); - return; - } - - sink_y.width = sink_crop->width; - sink_y.height = sink_crop->height; - src_y.width = src_fmt->width; - src_y.height = src_fmt->height; - - sink_c.width = sink_y.width / sink_yuv_info->hdiv; - sink_c.height = sink_y.height / sink_yuv_info->vdiv; - - /* - * The resizer is used not only to change the dimensions of the frame - * but also to change the scale for YUV formats, - * (4:2:2 -> 4:2:0 for example). So the width/height of the CbCr - * streams should be set according to the media bus format in the src pad. - */ - src_c.width = src_y.width / src_yuv_info->hdiv; - src_c.height = src_y.height / src_yuv_info->vdiv; - - if (sink_c.width == src_c.width && sink_c.height == src_c.height) { - rkisp1_rsz_disable(rsz, when); - return; - } - - dev_dbg(rsz->rkisp1->dev, "stream %d rsz/scale: %dx%d -> %dx%d\n", - rsz->id, sink_crop->width, sink_crop->height, - src_fmt->width, src_fmt->height); - dev_dbg(rsz->rkisp1->dev, "chroma scaling %dx%d -> %dx%d\n", - sink_c.width, sink_c.height, src_c.width, src_c.height); - - /* set values in the hw */ - rkisp1_rsz_config_regs(rsz, &sink_y, &sink_c, &src_y, &src_c, when); - - rkisp1_rsz_dump_regs(rsz); -} - -/* ---------------------------------------------------------------------------- - * Subdev pad operations - */ - -static int rkisp1_rsz_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - struct v4l2_subdev_pad_config dummy_cfg; - u32 pad = code->pad; - int ret; - - if (code->pad == RKISP1_RSZ_PAD_SRC) { - /* supported mbus codes on the src are the same as in the capture */ - struct rkisp1_capture *cap = &rsz->rkisp1->capture_devs[rsz->id]; - - return rkisp1_cap_enum_mbus_codes(cap, code); - } - - /* - * The selfpath capture doesn't support bayer formats. Therefore the selfpath resizer - * should support only YUV422 on the sink pad - */ - if (rsz->id == RKISP1_SELFPATH) { - if (code->index > 0) - return -EINVAL; - code->code = MEDIA_BUS_FMT_YUYV8_2X8; - return 0; - } - - /* supported mbus codes on the sink pad are the same as isp src pad */ - code->pad = RKISP1_ISP_PAD_SOURCE_VIDEO; - ret = v4l2_subdev_call(&rsz->rkisp1->isp.sd, pad, enum_mbus_code, - &dummy_cfg, code); - - /* restore pad */ - code->pad = pad; - code->flags = 0; - return ret; -} - -static int rkisp1_rsz_init_config(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg) -{ - struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; - struct v4l2_rect *sink_crop; - - sink_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SRC); - sink_fmt->width = RKISP1_DEFAULT_WIDTH; - sink_fmt->height = RKISP1_DEFAULT_HEIGHT; - sink_fmt->field = V4L2_FIELD_NONE; - sink_fmt->code = RKISP1_DEF_FMT; - - sink_crop = v4l2_subdev_get_try_crop(sd, cfg, RKISP1_RSZ_PAD_SINK); - sink_crop->width = RKISP1_DEFAULT_WIDTH; - sink_crop->height = RKISP1_DEFAULT_HEIGHT; - sink_crop->left = 0; - sink_crop->top = 0; - - src_fmt = v4l2_subdev_get_try_format(sd, cfg, RKISP1_RSZ_PAD_SINK); - *src_fmt = *sink_fmt; - - /* NOTE: there is no crop in the source pad, only in the sink */ - - return 0; -} - -static void rkisp1_rsz_set_src_fmt(struct rkisp1_resizer *rsz, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_mbus_framefmt *format, - unsigned int which) -{ - const struct rkisp1_isp_mbus_info *mbus_info; - struct v4l2_mbus_framefmt *src_fmt; - - src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which); - mbus_info = rkisp1_isp_mbus_info_get(src_fmt->code); - - /* for YUV formats, userspace can change the mbus code on the src pad if it is supported */ - if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV && - rkisp1_rsz_get_yuv_mbus_info(format->code)) - src_fmt->code = format->code; - - src_fmt->width = clamp_t(u32, format->width, - rsz->config->min_rsz_width, - rsz->config->max_rsz_width); - src_fmt->height = clamp_t(u32, format->height, - rsz->config->min_rsz_height, - rsz->config->max_rsz_height); - - *format = *src_fmt; -} - -static void rkisp1_rsz_set_sink_crop(struct rkisp1_resizer *rsz, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_rect *r, - unsigned int which) -{ - const struct rkisp1_isp_mbus_info *mbus_info; - struct v4l2_mbus_framefmt *sink_fmt; - struct v4l2_rect *sink_crop; - - sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which); - sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, - which); - - /* Not crop for MP bayer raw data */ - mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); - - if (rsz->id == RKISP1_MAINPATH && - mbus_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { - sink_crop->left = 0; - sink_crop->top = 0; - sink_crop->width = sink_fmt->width; - sink_crop->height = sink_fmt->height; - - *r = *sink_crop; - return; - } - - sink_crop->left = ALIGN(r->left, 2); - sink_crop->width = ALIGN(r->width, 2); - sink_crop->top = r->top; - sink_crop->height = r->height; - rkisp1_sd_adjust_crop(sink_crop, sink_fmt); - - *r = *sink_crop; -} - -static void rkisp1_rsz_set_sink_fmt(struct rkisp1_resizer *rsz, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_mbus_framefmt *format, - unsigned int which) -{ - const struct rkisp1_isp_mbus_info *mbus_info; - struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; - struct v4l2_rect *sink_crop; - - sink_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, which); - src_fmt = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SRC, which); - sink_crop = rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, - which); - if (rsz->id == RKISP1_SELFPATH) - sink_fmt->code = MEDIA_BUS_FMT_YUYV8_2X8; - else - sink_fmt->code = format->code; - - mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); - if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) { - sink_fmt->code = RKISP1_DEF_FMT; - mbus_info = rkisp1_isp_mbus_info_get(sink_fmt->code); - } - if (which == V4L2_SUBDEV_FORMAT_ACTIVE) - rsz->pixel_enc = mbus_info->pixel_enc; - - /* Propagete to source pad */ - src_fmt->code = sink_fmt->code; - - sink_fmt->width = clamp_t(u32, format->width, - RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); - sink_fmt->height = clamp_t(u32, format->height, - RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); - - *format = *sink_fmt; - - /* Update sink crop */ - rkisp1_rsz_set_sink_crop(rsz, cfg, sink_crop, which); -} - -static int rkisp1_rsz_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - - mutex_lock(&rsz->ops_lock); - fmt->format = *rkisp1_rsz_get_pad_fmt(rsz, cfg, fmt->pad, fmt->which); - mutex_unlock(&rsz->ops_lock); - return 0; -} - -static int rkisp1_rsz_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - - mutex_lock(&rsz->ops_lock); - if (fmt->pad == RKISP1_RSZ_PAD_SINK) - rkisp1_rsz_set_sink_fmt(rsz, cfg, &fmt->format, fmt->which); - else - rkisp1_rsz_set_src_fmt(rsz, cfg, &fmt->format, fmt->which); - - mutex_unlock(&rsz->ops_lock); - return 0; -} - -static int rkisp1_rsz_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - struct v4l2_mbus_framefmt *mf_sink; - int ret = 0; - - if (sel->pad == RKISP1_RSZ_PAD_SRC) - return -EINVAL; - - mutex_lock(&rsz->ops_lock); - switch (sel->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - mf_sink = rkisp1_rsz_get_pad_fmt(rsz, cfg, RKISP1_RSZ_PAD_SINK, - sel->which); - sel->r.height = mf_sink->height; - sel->r.width = mf_sink->width; - sel->r.left = 0; - sel->r.top = 0; - break; - case V4L2_SEL_TGT_CROP: - sel->r = *rkisp1_rsz_get_pad_crop(rsz, cfg, RKISP1_RSZ_PAD_SINK, - sel->which); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&rsz->ops_lock); - return ret; -} - -static int rkisp1_rsz_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - - if (sel->target != V4L2_SEL_TGT_CROP || sel->pad == RKISP1_RSZ_PAD_SRC) - return -EINVAL; - - dev_dbg(rsz->rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, - sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); - - mutex_lock(&rsz->ops_lock); - rkisp1_rsz_set_sink_crop(rsz, cfg, &sel->r, sel->which); - mutex_unlock(&rsz->ops_lock); - - return 0; -} - -static const struct media_entity_operations rkisp1_rsz_media_ops = { - .link_validate = v4l2_subdev_link_validate, -}; - -static const struct v4l2_subdev_pad_ops rkisp1_rsz_pad_ops = { - .enum_mbus_code = rkisp1_rsz_enum_mbus_code, - .get_selection = rkisp1_rsz_get_selection, - .set_selection = rkisp1_rsz_set_selection, - .init_cfg = rkisp1_rsz_init_config, - .get_fmt = rkisp1_rsz_get_fmt, - .set_fmt = rkisp1_rsz_set_fmt, - .link_validate = v4l2_subdev_link_validate_default, -}; - -/* ---------------------------------------------------------------------------- - * Stream operations - */ - -static int rkisp1_rsz_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct rkisp1_resizer *rsz = - container_of(sd, struct rkisp1_resizer, sd); - struct rkisp1_device *rkisp1 = rsz->rkisp1; - struct rkisp1_capture *other = &rkisp1->capture_devs[rsz->id ^ 1]; - enum rkisp1_shadow_regs_when when = RKISP1_SHADOW_REGS_SYNC; - - if (!enable) { - rkisp1_dcrop_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); - rkisp1_rsz_disable(rsz, RKISP1_SHADOW_REGS_ASYNC); - return 0; - } - - if (other->is_streaming) - when = RKISP1_SHADOW_REGS_ASYNC; - - mutex_lock(&rsz->ops_lock); - rkisp1_rsz_config(rsz, when); - rkisp1_dcrop_config(rsz); - - mutex_unlock(&rsz->ops_lock); - return 0; -} - -static const struct v4l2_subdev_video_ops rkisp1_rsz_video_ops = { - .s_stream = rkisp1_rsz_s_stream, -}; - -static const struct v4l2_subdev_ops rkisp1_rsz_ops = { - .video = &rkisp1_rsz_video_ops, - .pad = &rkisp1_rsz_pad_ops, -}; - -static void rkisp1_rsz_unregister(struct rkisp1_resizer *rsz) -{ - v4l2_device_unregister_subdev(&rsz->sd); - media_entity_cleanup(&rsz->sd.entity); -} - -static int rkisp1_rsz_register(struct rkisp1_resizer *rsz) -{ - static const char * const dev_names[] = { - RKISP1_RSZ_MP_DEV_NAME, - RKISP1_RSZ_SP_DEV_NAME - }; - struct media_pad *pads = rsz->pads; - struct v4l2_subdev *sd = &rsz->sd; - int ret; - - if (rsz->id == RKISP1_SELFPATH) - rsz->config = &rkisp1_rsz_config_sp; - else - rsz->config = &rkisp1_rsz_config_mp; - - v4l2_subdev_init(sd, &rkisp1_rsz_ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - sd->entity.ops = &rkisp1_rsz_media_ops; - sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER; - sd->owner = THIS_MODULE; - strscpy(sd->name, dev_names[rsz->id], sizeof(sd->name)); - - pads[RKISP1_RSZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK | - MEDIA_PAD_FL_MUST_CONNECT; - pads[RKISP1_RSZ_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE | - MEDIA_PAD_FL_MUST_CONNECT; - - rsz->pixel_enc = RKISP1_DEF_PIXEL_ENC; - - mutex_init(&rsz->ops_lock); - ret = media_entity_pads_init(&sd->entity, RKISP1_RSZ_PAD_MAX, pads); - if (ret) - return ret; - - ret = v4l2_device_register_subdev(&rsz->rkisp1->v4l2_dev, sd); - if (ret) { - dev_err(sd->dev, "Failed to register resizer subdev\n"); - goto err_cleanup_media_entity; - } - - rkisp1_rsz_init_config(sd, rsz->pad_cfg); - return 0; - -err_cleanup_media_entity: - media_entity_cleanup(&sd->entity); - - return ret; -} - -int rkisp1_resizer_devs_register(struct rkisp1_device *rkisp1) -{ - struct rkisp1_resizer *rsz; - unsigned int i, j; - int ret; - - for (i = 0; i < ARRAY_SIZE(rkisp1->resizer_devs); i++) { - rsz = &rkisp1->resizer_devs[i]; - rsz->rkisp1 = rkisp1; - rsz->id = i; - ret = rkisp1_rsz_register(rsz); - if (ret) - goto err_unreg_resizer_devs; - } - - return 0; - -err_unreg_resizer_devs: - for (j = 0; j < i; j++) { - rsz = &rkisp1->resizer_devs[j]; - rkisp1_rsz_unregister(rsz); - } - - return ret; -} - -void rkisp1_resizer_devs_unregister(struct rkisp1_device *rkisp1) -{ - struct rkisp1_resizer *mp = &rkisp1->resizer_devs[RKISP1_MAINPATH]; - struct rkisp1_resizer *sp = &rkisp1->resizer_devs[RKISP1_SELFPATH]; - - rkisp1_rsz_unregister(mp); - rkisp1_rsz_unregister(sp); -} diff --git a/drivers/staging/media/rkisp1/rkisp1-stats.c b/drivers/staging/media/rkisp1/rkisp1-stats.c deleted file mode 100644 index 3ddab8fa8f2d..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-stats.c +++ /dev/null @@ -1,415 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - Stats subdevice - * - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include -#include -#include -#include -#include /* for ISP statistics */ - -#include "rkisp1-common.h" - -#define RKISP1_STATS_DEV_NAME RKISP1_DRIVER_NAME "_stats" - -#define RKISP1_ISP_STATS_REQ_BUFS_MIN 2 -#define RKISP1_ISP_STATS_REQ_BUFS_MAX 8 - -static int rkisp1_stats_enum_fmt_meta_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct video_device *video = video_devdata(file); - struct rkisp1_stats *stats = video_get_drvdata(video); - - if (f->index > 0 || f->type != video->queue->type) - return -EINVAL; - - f->pixelformat = stats->vdev_fmt.fmt.meta.dataformat; - return 0; -} - -static int rkisp1_stats_g_fmt_meta_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct video_device *video = video_devdata(file); - struct rkisp1_stats *stats = video_get_drvdata(video); - struct v4l2_meta_format *meta = &f->fmt.meta; - - if (f->type != video->queue->type) - return -EINVAL; - - memset(meta, 0, sizeof(*meta)); - meta->dataformat = stats->vdev_fmt.fmt.meta.dataformat; - meta->buffersize = stats->vdev_fmt.fmt.meta.buffersize; - - return 0; -} - -static int rkisp1_stats_querycap(struct file *file, - void *priv, struct v4l2_capability *cap) -{ - struct video_device *vdev = video_devdata(file); - - strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); - strscpy(cap->card, vdev->name, sizeof(cap->card)); - strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); - - return 0; -} - -/* ISP video device IOCTLs */ -static const struct v4l2_ioctl_ops rkisp1_stats_ioctl = { - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_enum_fmt_meta_cap = rkisp1_stats_enum_fmt_meta_cap, - .vidioc_g_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, - .vidioc_s_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, - .vidioc_try_fmt_meta_cap = rkisp1_stats_g_fmt_meta_cap, - .vidioc_querycap = rkisp1_stats_querycap, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct v4l2_file_operations rkisp1_stats_fops = { - .mmap = vb2_fop_mmap, - .unlocked_ioctl = video_ioctl2, - .poll = vb2_fop_poll, - .open = v4l2_fh_open, - .release = vb2_fop_release -}; - -static int rkisp1_stats_vb2_queue_setup(struct vb2_queue *vq, - unsigned int *num_buffers, - unsigned int *num_planes, - unsigned int sizes[], - struct device *alloc_devs[]) -{ - *num_planes = 1; - - *num_buffers = clamp_t(u32, *num_buffers, RKISP1_ISP_STATS_REQ_BUFS_MIN, - RKISP1_ISP_STATS_REQ_BUFS_MAX); - - sizes[0] = sizeof(struct rkisp1_stat_buffer); - - return 0; -} - -static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkisp1_buffer *stats_buf = - container_of(vbuf, struct rkisp1_buffer, vb); - struct vb2_queue *vq = vb->vb2_queue; - struct rkisp1_stats *stats_dev = vq->drv_priv; - - stats_buf->vaddr = vb2_plane_vaddr(vb, 0); - - spin_lock_irq(&stats_dev->lock); - list_add_tail(&stats_buf->queue, &stats_dev->stat); - spin_unlock_irq(&stats_dev->lock); -} - -static int rkisp1_stats_vb2_buf_prepare(struct vb2_buffer *vb) -{ - if (vb2_plane_size(vb, 0) < sizeof(struct rkisp1_stat_buffer)) - return -EINVAL; - - vb2_set_plane_payload(vb, 0, sizeof(struct rkisp1_stat_buffer)); - - return 0; -} - -static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq) -{ - struct rkisp1_stats *stats = vq->drv_priv; - struct rkisp1_buffer *buf; - unsigned int i; - - spin_lock_irq(&stats->lock); - for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) { - if (list_empty(&stats->stat)) - break; - buf = list_first_entry(&stats->stat, - struct rkisp1_buffer, queue); - list_del(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - spin_unlock_irq(&stats->lock); -} - -static const struct vb2_ops rkisp1_stats_vb2_ops = { - .queue_setup = rkisp1_stats_vb2_queue_setup, - .buf_queue = rkisp1_stats_vb2_buf_queue, - .buf_prepare = rkisp1_stats_vb2_buf_prepare, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .stop_streaming = rkisp1_stats_vb2_stop_streaming, -}; - -static int -rkisp1_stats_init_vb2_queue(struct vb2_queue *q, struct rkisp1_stats *stats) -{ - struct rkisp1_vdev_node *node; - - node = container_of(q, struct rkisp1_vdev_node, buf_queue); - - q->type = V4L2_BUF_TYPE_META_CAPTURE; - q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; - q->drv_priv = stats; - q->ops = &rkisp1_stats_vb2_ops; - q->mem_ops = &vb2_vmalloc_memops; - q->buf_struct_size = sizeof(struct rkisp1_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; - - return vb2_queue_init(q); -} - -static void rkisp1_stats_get_awb_meas(struct rkisp1_stats *stats, - struct rkisp1_stat_buffer *pbuf) -{ - /* Protect against concurrent access from ISR? */ - struct rkisp1_device *rkisp1 = stats->rkisp1; - u32 reg_val; - - pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AWB; - reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_WHITE_CNT); - pbuf->params.awb.awb_mean[0].cnt = - RKISP1_CIF_ISP_AWB_GET_PIXEL_CNT(reg_val); - reg_val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AWB_MEAN); - - pbuf->params.awb.awb_mean[0].mean_cr_or_r = - RKISP1_CIF_ISP_AWB_GET_MEAN_CR_R(reg_val); - pbuf->params.awb.awb_mean[0].mean_cb_or_b = - RKISP1_CIF_ISP_AWB_GET_MEAN_CB_B(reg_val); - pbuf->params.awb.awb_mean[0].mean_y_or_g = - RKISP1_CIF_ISP_AWB_GET_MEAN_Y_G(reg_val); -} - -static void rkisp1_stats_get_aec_meas(struct rkisp1_stats *stats, - struct rkisp1_stat_buffer *pbuf) -{ - struct rkisp1_device *rkisp1 = stats->rkisp1; - unsigned int i; - - pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AUTOEXP; - for (i = 0; i < RKISP1_CIF_ISP_AE_MEAN_MAX; i++) - pbuf->params.ae.exp_mean[i] = - (u8)rkisp1_read(rkisp1, - RKISP1_CIF_ISP_EXP_MEAN_00 + i * 4); -} - -static void rkisp1_stats_get_afc_meas(struct rkisp1_stats *stats, - struct rkisp1_stat_buffer *pbuf) -{ - struct rkisp1_device *rkisp1 = stats->rkisp1; - struct rkisp1_cif_isp_af_stat *af; - - pbuf->meas_type |= RKISP1_CIF_ISP_STAT_AFM; - - af = &pbuf->params.af; - af->window[0].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_A); - af->window[0].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_A); - af->window[1].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_B); - af->window[1].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_B); - af->window[2].sum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_SUM_C); - af->window[2].lum = rkisp1_read(rkisp1, RKISP1_CIF_ISP_AFM_LUM_C); -} - -static void rkisp1_stats_get_hst_meas(struct rkisp1_stats *stats, - struct rkisp1_stat_buffer *pbuf) -{ - struct rkisp1_device *rkisp1 = stats->rkisp1; - unsigned int i; - - pbuf->meas_type |= RKISP1_CIF_ISP_STAT_HIST; - for (i = 0; i < RKISP1_CIF_ISP_HIST_BIN_N_MAX; i++) - pbuf->params.hist.hist_bins[i] = - (u8)rkisp1_read(rkisp1, - RKISP1_CIF_ISP_HIST_BIN_0 + i * 4); -} - -static void rkisp1_stats_get_bls_meas(struct rkisp1_stats *stats, - struct rkisp1_stat_buffer *pbuf) -{ - struct rkisp1_device *rkisp1 = stats->rkisp1; - const struct rkisp1_isp_mbus_info *in_fmt = rkisp1->isp.sink_fmt; - struct rkisp1_cif_isp_bls_meas_val *bls_val; - - bls_val = &pbuf->params.ae.bls_val; - if (in_fmt->bayer_pat == RKISP1_RAW_BGGR) { - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_GBRG) { - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_GRBG) { - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } else if (in_fmt->bayer_pat == RKISP1_RAW_RGGB) { - bls_val->meas_r = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_A_MEASURED); - bls_val->meas_gr = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_B_MEASURED); - bls_val->meas_gb = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_C_MEASURED); - bls_val->meas_b = - rkisp1_read(rkisp1, RKISP1_CIF_ISP_BLS_D_MEASURED); - } -} - -static void -rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris) -{ - struct rkisp1_stat_buffer *cur_stat_buf; - struct rkisp1_buffer *cur_buf = NULL; - unsigned int frame_sequence = stats->rkisp1->isp.frame_sequence; - u64 timestamp = ktime_get_ns(); - - /* get one empty buffer */ - if (!list_empty(&stats->stat)) { - cur_buf = list_first_entry(&stats->stat, - struct rkisp1_buffer, queue); - list_del(&cur_buf->queue); - } - - if (!cur_buf) - return; - - cur_stat_buf = - (struct rkisp1_stat_buffer *)(cur_buf->vaddr); - - if (isp_ris & RKISP1_CIF_ISP_AWB_DONE) - rkisp1_stats_get_awb_meas(stats, cur_stat_buf); - - if (isp_ris & RKISP1_CIF_ISP_AFM_FIN) - rkisp1_stats_get_afc_meas(stats, cur_stat_buf); - - if (isp_ris & RKISP1_CIF_ISP_EXP_END) { - rkisp1_stats_get_aec_meas(stats, cur_stat_buf); - rkisp1_stats_get_bls_meas(stats, cur_stat_buf); - } - - if (isp_ris & RKISP1_CIF_ISP_HIST_MEASURE_RDY) - rkisp1_stats_get_hst_meas(stats, cur_stat_buf); - - vb2_set_plane_payload(&cur_buf->vb.vb2_buf, 0, - sizeof(struct rkisp1_stat_buffer)); - cur_buf->vb.sequence = frame_sequence; - cur_buf->vb.vb2_buf.timestamp = timestamp; - vb2_buffer_done(&cur_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); -} - -void rkisp1_stats_isr(struct rkisp1_stats *stats, u32 isp_ris) -{ - struct rkisp1_device *rkisp1 = stats->rkisp1; - unsigned int isp_mis_tmp = 0; - - spin_lock(&stats->lock); - - rkisp1_write(rkisp1, RKISP1_STATS_MEAS_MASK, RKISP1_CIF_ISP_ICR); - - isp_mis_tmp = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); - if (isp_mis_tmp & RKISP1_STATS_MEAS_MASK) - rkisp1->debug.stats_error++; - - if (isp_ris & RKISP1_STATS_MEAS_MASK) - rkisp1_stats_send_measurement(stats, isp_ris); - - spin_unlock(&stats->lock); -} - -static void rkisp1_init_stats(struct rkisp1_stats *stats) -{ - stats->vdev_fmt.fmt.meta.dataformat = - V4L2_META_FMT_RK_ISP1_STAT_3A; - stats->vdev_fmt.fmt.meta.buffersize = - sizeof(struct rkisp1_stat_buffer); -} - -int rkisp1_stats_register(struct rkisp1_device *rkisp1) -{ - struct rkisp1_stats *stats = &rkisp1->stats; - struct rkisp1_vdev_node *node = &stats->vnode; - struct video_device *vdev = &node->vdev; - int ret; - - stats->rkisp1 = rkisp1; - mutex_init(&node->vlock); - INIT_LIST_HEAD(&stats->stat); - spin_lock_init(&stats->lock); - - strscpy(vdev->name, RKISP1_STATS_DEV_NAME, sizeof(vdev->name)); - - video_set_drvdata(vdev, stats); - vdev->ioctl_ops = &rkisp1_stats_ioctl; - vdev->fops = &rkisp1_stats_fops; - vdev->release = video_device_release_empty; - vdev->lock = &node->vlock; - vdev->v4l2_dev = &rkisp1->v4l2_dev; - vdev->queue = &node->buf_queue; - vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; - vdev->vfl_dir = VFL_DIR_RX; - rkisp1_stats_init_vb2_queue(vdev->queue, stats); - rkisp1_init_stats(stats); - video_set_drvdata(vdev, stats); - - node->pad.flags = MEDIA_PAD_FL_SINK; - ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); - if (ret) - goto err_mutex_destroy; - - ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); - if (ret) { - dev_err(&vdev->dev, - "failed to register %s, ret=%d\n", vdev->name, ret); - goto err_cleanup_media_entity; - } - - return 0; - -err_cleanup_media_entity: - media_entity_cleanup(&vdev->entity); -err_mutex_destroy: - mutex_destroy(&node->vlock); - return ret; -} - -void rkisp1_stats_unregister(struct rkisp1_device *rkisp1) -{ - struct rkisp1_stats *stats = &rkisp1->stats; - struct rkisp1_vdev_node *node = &stats->vnode; - struct video_device *vdev = &node->vdev; - - vb2_video_unregister_device(vdev); - media_entity_cleanup(&vdev->entity); - mutex_destroy(&node->vlock); -} diff --git a/drivers/staging/media/rkisp1/uapi/rkisp1-config.h b/drivers/staging/media/rkisp1/uapi/rkisp1-config.h deleted file mode 100644 index 6e449e784260..000000000000 --- a/drivers/staging/media/rkisp1/uapi/rkisp1-config.h +++ /dev/null @@ -1,884 +0,0 @@ -/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR MIT) */ -/* - * Rockchip ISP1 userspace API - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#ifndef _UAPI_RKISP1_CONFIG_H -#define _UAPI_RKISP1_CONFIG_H - -#include - -/* Defect Pixel Cluster Detection */ -#define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0) -/* Black Level Subtraction */ -#define RKISP1_CIF_ISP_MODULE_BLS (1U << 1) -/* Sensor De-gamma */ -#define RKISP1_CIF_ISP_MODULE_SDG (1U << 2) -/* Histogram */ -#define RKISP1_CIF_ISP_MODULE_HST (1U << 3) -/* Lens Shade Control */ -#define RKISP1_CIF_ISP_MODULE_LSC (1U << 4) -/* Auto White Balance Gain */ -#define RKISP1_CIF_ISP_MODULE_AWB_GAIN (1U << 5) -/* Filter */ -#define RKISP1_CIF_ISP_MODULE_FLT (1U << 6) -/* Bayer Demosaic */ -#define RKISP1_CIF_ISP_MODULE_BDM (1U << 7) -/* Cross Talk */ -#define RKISP1_CIF_ISP_MODULE_CTK (1U << 8) -/* Gamma Out Curve */ -#define RKISP1_CIF_ISP_MODULE_GOC (1U << 9) -/* Color Processing */ -#define RKISP1_CIF_ISP_MODULE_CPROC (1U << 10) -/* Auto Focus Control */ -#define RKISP1_CIF_ISP_MODULE_AFC (1U << 11) -/* Auto White Balancing */ -#define RKISP1_CIF_ISP_MODULE_AWB (1U << 12) -/* Image Effect */ -#define RKISP1_CIF_ISP_MODULE_IE (1U << 13) -/* Auto Exposure Control */ -#define RKISP1_CIF_ISP_MODULE_AEC (1U << 14) -/* Wide Dynamic Range */ -#define RKISP1_CIF_ISP_MODULE_WDR (1U << 15) -/* Denoise Pre-Filter */ -#define RKISP1_CIF_ISP_MODULE_DPF (1U << 16) -/* Denoise Pre-Filter Strength */ -#define RKISP1_CIF_ISP_MODULE_DPF_STRENGTH (1U << 17) - -#define RKISP1_CIF_ISP_CTK_COEFF_MAX 0x100 -#define RKISP1_CIF_ISP_CTK_OFFSET_MAX 0x800 - -#define RKISP1_CIF_ISP_AE_MEAN_MAX 25 -#define RKISP1_CIF_ISP_HIST_BIN_N_MAX 16 -#define RKISP1_CIF_ISP_AFM_MAX_WINDOWS 3 -#define RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE 17 - -#define RKISP1_CIF_ISP_BDM_MAX_TH 0xff - -/* - * Black level compensation - */ -/* maximum value for horizontal start address */ -#define RKISP1_CIF_ISP_BLS_START_H_MAX 0x00000fff -/* maximum value for horizontal stop address */ -#define RKISP1_CIF_ISP_BLS_STOP_H_MAX 0x00000fff -/* maximum value for vertical start address */ -#define RKISP1_CIF_ISP_BLS_START_V_MAX 0x00000fff -/* maximum value for vertical stop address */ -#define RKISP1_CIF_ISP_BLS_STOP_V_MAX 0x00000fff -/* maximum is 2^18 = 262144*/ -#define RKISP1_CIF_ISP_BLS_SAMPLES_MAX 0x00000012 -/* maximum value for fixed black level */ -#define RKISP1_CIF_ISP_BLS_FIX_SUB_MAX 0x00000fff -/* minimum value for fixed black level */ -#define RKISP1_CIF_ISP_BLS_FIX_SUB_MIN 0xfffff000 -/* 13 bit range (signed)*/ -#define RKISP1_CIF_ISP_BLS_FIX_MASK 0x00001fff - -/* - * Automatic white balance measurements - */ -#define RKISP1_CIF_ISP_AWB_MAX_GRID 1 -#define RKISP1_CIF_ISP_AWB_MAX_FRAMES 7 - -/* - * Gamma out - */ -/* Maximum number of color samples supported */ -#define RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES 17 - -/* - * Lens shade correction - */ -#define RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE 8 - -/* - * The following matches the tuning process, - * not the max capabilities of the chip. - */ -#define RKISP1_CIF_ISP_LSC_SAMPLES_MAX 17 - -/* - * Histogram calculation - */ -/* Last 3 values unused. */ -#define RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28 - -/* - * Defect Pixel Cluster Correction - */ -#define RKISP1_CIF_ISP_DPCC_METHODS_MAX 3 - -/* - * Denoising pre filter - */ -#define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS 17 -#define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS 6 - -/* - * Measurement types - */ -#define RKISP1_CIF_ISP_STAT_AWB (1U << 0) -#define RKISP1_CIF_ISP_STAT_AUTOEXP (1U << 1) -#define RKISP1_CIF_ISP_STAT_AFM (1U << 2) -#define RKISP1_CIF_ISP_STAT_HIST (1U << 3) - -enum rkisp1_cif_isp_histogram_mode { - RKISP1_CIF_ISP_HISTOGRAM_MODE_DISABLE, - RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED, - RKISP1_CIF_ISP_HISTOGRAM_MODE_R_HISTOGRAM, - RKISP1_CIF_ISP_HISTOGRAM_MODE_G_HISTOGRAM, - RKISP1_CIF_ISP_HISTOGRAM_MODE_B_HISTOGRAM, - RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM -}; - -enum rkisp1_cif_isp_awb_mode_type { - RKISP1_CIF_ISP_AWB_MODE_MANUAL, - RKISP1_CIF_ISP_AWB_MODE_RGB, - RKISP1_CIF_ISP_AWB_MODE_YCBCR -}; - -enum rkisp1_cif_isp_flt_mode { - RKISP1_CIF_ISP_FLT_STATIC_MODE, - RKISP1_CIF_ISP_FLT_DYNAMIC_MODE -}; - -/** - * enum rkisp1_cif_isp_exp_ctrl_autostop - stop modes - * @RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0: continuous measurement - * @RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_1: stop measuring after a complete frame - */ -enum rkisp1_cif_isp_exp_ctrl_autostop { - RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0 = 0, - RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_1 = 1, -}; - -/** - * enum rkisp1_cif_isp_exp_meas_mode - Exposure measure mode - * @RKISP1_CIF_ISP_EXP_MEASURING_MODE_0: Y = 16 + 0.25R + 0.5G + 0.1094B - * @RKISP1_CIF_ISP_EXP_MEASURING_MODE_1: Y = (R + G + B) x (85/256) - */ -enum rkisp1_cif_isp_exp_meas_mode { - RKISP1_CIF_ISP_EXP_MEASURING_MODE_0, - RKISP1_CIF_ISP_EXP_MEASURING_MODE_1, -}; - -/*---------- PART1: Input Parameters ------------*/ - -/** - * struct rkisp1_cif_isp_window - measurement window. - * - * Measurements are calculated per window inside the frame. - * This struct represents a window for a measurement. - * - * @h_offs: the horizontal offset of the window from the left of the frame in pixels. - * @v_offs: the vertical offset of the window from the top of the frame in pixels. - * @h_size: the horizontal size of the window in pixels - * @v_size: the vertical size of the window in pixels. - */ -struct rkisp1_cif_isp_window { - __u16 h_offs; - __u16 v_offs; - __u16 h_size; - __u16 v_size; -}; - -/** - * struct rkisp1_cif_isp_bls_fixed_val - BLS fixed subtraction values - * - * The values will be subtracted from the sensor - * values. Therefore a negative value means addition instead of subtraction! - * - * @r: Fixed (signed!) subtraction value for Bayer pattern R - * @gr: Fixed (signed!) subtraction value for Bayer pattern Gr - * @gb: Fixed (signed!) subtraction value for Bayer pattern Gb - * @b: Fixed (signed!) subtraction value for Bayer pattern B - */ -struct rkisp1_cif_isp_bls_fixed_val { - __s16 r; - __s16 gr; - __s16 gb; - __s16 b; -}; - -/** - * struct rkisp1_cif_isp_bls_config - Configuration used by black level subtraction - * - * @enable_auto: Automatic mode activated means that the measured values - * are subtracted. Otherwise the fixed subtraction - * values will be subtracted. - * @en_windows: enabled window - * @bls_window1: Measurement window 1 size - * @bls_window2: Measurement window 2 size - * @bls_samples: Set amount of measured pixels for each Bayer position - * (A, B,C and D) to 2^bls_samples. - * @fixed_val: Fixed subtraction values - */ -struct rkisp1_cif_isp_bls_config { - __u8 enable_auto; - __u8 en_windows; - struct rkisp1_cif_isp_window bls_window1; - struct rkisp1_cif_isp_window bls_window2; - __u8 bls_samples; - struct rkisp1_cif_isp_bls_fixed_val fixed_val; -}; - -/** - * struct rkisp1_cif_isp_dpcc_methods_config - Methods Configuration used by DPCC - * - * Methods Configuration used by Defect Pixel Cluster Correction - * - * @method: Method enable bits - * @line_thresh: Line threshold - * @line_mad_fac: Line MAD factor - * @pg_fac: Peak gradient factor - * @rnd_thresh: Rank Neighbor Difference threshold - * @rg_fac: Rank gradient factor - */ -struct rkisp1_cif_isp_dpcc_methods_config { - __u32 method; - __u32 line_thresh; - __u32 line_mad_fac; - __u32 pg_fac; - __u32 rnd_thresh; - __u32 rg_fac; -}; - -/** - * struct rkisp1_cif_isp_dpcc_config - Configuration used by DPCC - * - * Configuration used by Defect Pixel Cluster Correction - * - * @mode: dpcc output mode - * @output_mode: whether use hard coded methods - * @set_use: stage1 methods set - * @methods: methods config - * @ro_limits: rank order limits - * @rnd_offs: differential rank offsets for rank neighbor difference - */ -struct rkisp1_cif_isp_dpcc_config { - __u32 mode; - __u32 output_mode; - __u32 set_use; - struct rkisp1_cif_isp_dpcc_methods_config methods[RKISP1_CIF_ISP_DPCC_METHODS_MAX]; - __u32 ro_limits; - __u32 rnd_offs; -}; - -/** - * struct rkisp1_cif_isp_gamma_corr_curve - gamma curve point definition y-axis (output). - * - * The reset values define a linear curve which has the same effect as bypass. Reset values are: - * gamma_y[0] = 0x0000, gamma_y[1] = 0x0100, ... gamma_y[15] = 0x0f00, gamma_y[16] = 0xfff - * - * @gamma_y: the values for the y-axis of gamma curve points. Each value is 12 bit. - */ -struct rkisp1_cif_isp_gamma_corr_curve { - __u16 gamma_y[RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE]; -}; - -/** - * struct rkisp1_cif_isp_gamma_curve_x_axis_pnts - De-Gamma Curve definition x increments - * (sampling points). gamma_dx0 is for the lower samples (1-8), gamma_dx1 is for the - * higher samples (9-16). The reset values for both fields is 0x44444444. This means - * that each sample is 4 units away from the previous one on the x-axis. - * - * @gamma_dx0: gamma curve sample points definitions. Bits 0:2 for sample 1. Bit 3 unused. - * Bits 4:6 for sample 2. bit 7 unused ... Bits 28:30 for sample 8. Bit 31 unused - * @gamma_dx1: gamma curve sample points definitions. Bits 0:2 for sample 9. Bit 3 unused. - * Bits 4:6 for sample 10. bit 7 unused ... Bits 28:30 for sample 16. Bit 31 unused - */ -struct rkisp1_cif_isp_gamma_curve_x_axis_pnts { - __u32 gamma_dx0; - __u32 gamma_dx1; -}; - -/** - * struct rkisp1_cif_isp_sdg_config - Configuration used by sensor degamma - * - * @curve_r: gamma curve point definition axis for red - * @curve_g: gamma curve point definition axis for green - * @curve_b: gamma curve point definition axis for blue - * @xa_pnts: x axis increments - */ -struct rkisp1_cif_isp_sdg_config { - struct rkisp1_cif_isp_gamma_corr_curve curve_r; - struct rkisp1_cif_isp_gamma_corr_curve curve_g; - struct rkisp1_cif_isp_gamma_corr_curve curve_b; - struct rkisp1_cif_isp_gamma_curve_x_axis_pnts xa_pnts; -}; - -/** - * struct rkisp1_cif_isp_lsc_config - Configuration used by Lens shading correction - * - * @r_data_tbl: sample table red - * @gr_data_tbl: sample table green (red) - * @gb_data_tbl: sample table green (blue) - * @b_data_tbl: sample table blue - * @x_grad_tbl: gradient table x - * @y_grad_tbl: gradient table y - * @x_size_tbl: size table x - * @y_size_tbl: size table y - * @config_width: not used at the moment - * @config_height: not used at the moment - */ -struct rkisp1_cif_isp_lsc_config { - __u16 r_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; - __u16 gr_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; - __u16 gb_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; - __u16 b_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; - - __u16 x_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; - __u16 y_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; - - __u16 x_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; - __u16 y_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; - __u16 config_width; - __u16 config_height; -}; - -/** - * struct rkisp1_cif_isp_ie_config - Configuration used by image effects - * - * @effect: values from 'enum v4l2_colorfx'. Possible values are: V4L2_COLORFX_SEPIA, - * V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_AQUA, V4L2_COLORFX_EMBOSS, - * V4L2_COLORFX_SKETCH, V4L2_COLORFX_BW, V4L2_COLORFX_NEGATIVE - * @color_sel: bits 0:2 - colors bitmask (001 - blue, 010 - green, 100 - red). - * bits 8:15 - Threshold value of the RGB colors for the color selection effect. - * @eff_mat_1: 3x3 Matrix Coefficients for Emboss Effect 1 - * @eff_mat_2: 3x3 Matrix Coefficients for Emboss Effect 2 - * @eff_mat_3: 3x3 Matrix Coefficients for Emboss 3/Sketch 1 - * @eff_mat_4: 3x3 Matrix Coefficients for Sketch Effect 2 - * @eff_mat_5: 3x3 Matrix Coefficients for Sketch Effect 3 - * @eff_tint: Chrominance increment values of tint (used for sepia effect) - */ -struct rkisp1_cif_isp_ie_config { - __u16 effect; - __u16 color_sel; - __u16 eff_mat_1; - __u16 eff_mat_2; - __u16 eff_mat_3; - __u16 eff_mat_4; - __u16 eff_mat_5; - __u16 eff_tint; -}; - -/** - * struct rkisp1_cif_isp_cproc_config - Configuration used by Color Processing - * - * @c_out_range: Chrominance pixel clipping range at output. - * (0 for limit, 1 for full) - * @y_in_range: Luminance pixel clipping range at output. - * @y_out_range: Luminance pixel clipping range at output. - * @contrast: 00~ff, 0.0~1.992 - * @brightness: 80~7F, -128~+127 - * @sat: saturation, 00~FF, 0.0~1.992 - * @hue: 80~7F, -90~+87.188 - */ -struct rkisp1_cif_isp_cproc_config { - __u8 c_out_range; - __u8 y_in_range; - __u8 y_out_range; - __u8 contrast; - __u8 brightness; - __u8 sat; - __u8 hue; -}; - -/** - * struct rkisp1_cif_isp_awb_meas_config - Configuration used by auto white balance - * - * @awb_mode: the awb meas mode. From enum rkisp1_cif_isp_awb_mode_type. - * @awb_wnd: white balance measurement window (in pixels) - * @max_y: only pixels values < max_y contribute to awb measurement, set to 0 - * to disable this feature - * @min_y: only pixels values > min_y contribute to awb measurement - * @max_csum: Chrominance sum maximum value, only consider pixels with Cb+Cr, - * smaller than threshold for awb measurements - * @min_c: Chrominance minimum value, only consider pixels with Cb/Cr - * each greater than threshold value for awb measurements - * @frames: number of frames - 1 used for mean value calculation - * (ucFrames=0 means 1 Frame) - * @awb_ref_cr: reference Cr value for AWB regulation, target for AWB - * @awb_ref_cb: reference Cb value for AWB regulation, target for AWB - * @enable_ymax_cmp: enable Y_MAX compare (Not valid in RGB measurement mode.) - */ -struct rkisp1_cif_isp_awb_meas_config { - /* - * Note: currently the h and v offsets are mapped to grid offsets - */ - struct rkisp1_cif_isp_window awb_wnd; - __u32 awb_mode; - __u8 max_y; - __u8 min_y; - __u8 max_csum; - __u8 min_c; - __u8 frames; - __u8 awb_ref_cr; - __u8 awb_ref_cb; - __u8 enable_ymax_cmp; -}; - -/** - * struct rkisp1_cif_isp_awb_gain_config - Configuration used by auto white balance gain - * - * All fields in this struct are 10 bit, where: - * 0x100h = 1, unsigned integer value, range 0 to 4 with 8 bit fractional part. - * - * out_data_x = ( AWB_GAIN_X * in_data + 128) >> 8 - * - * @gain_red: gain value for red component. - * @gain_green_r: gain value for green component in red line. - * @gain_blue: gain value for blue component. - * @gain_green_b: gain value for green component in blue line. - */ -struct rkisp1_cif_isp_awb_gain_config { - __u16 gain_red; - __u16 gain_green_r; - __u16 gain_blue; - __u16 gain_green_b; -}; - -/** - * struct rkisp1_cif_isp_flt_config - Configuration used by ISP filtering - * - * All 4 threshold fields (thresh_*) are 10 bits. - * All 6 factor fields (fac_*) are 6 bits. - * - * @mode: ISP_FILT_MODE register fields (from enum rkisp1_cif_isp_flt_mode) - * @grn_stage1: Green filter stage 1 select (range 0x0...0x8) - * @chr_h_mode: Chroma filter horizontal mode - * @chr_v_mode: Chroma filter vertical mode - * @thresh_bl0: If thresh_bl1 < sum_grad < thresh_bl0 then fac_bl0 is selected (blurring th) - * @thresh_bl1: If sum_grad < thresh_bl1 then fac_bl1 is selected (blurring th) - * @thresh_sh0: If thresh_sh0 < sum_grad < thresh_sh1 then thresh_sh0 is selected (sharpening th) - * @thresh_sh1: If thresh_sh1 < sum_grad then thresh_sh1 is selected (sharpening th) - * @lum_weight: Parameters for luminance weight function. - * @fac_sh1: filter factor for sharp1 level - * @fac_sh0: filter factor for sharp0 level - * @fac_mid: filter factor for mid level and for static filter mode - * @fac_bl0: filter factor for blur 0 level - * @fac_bl1: filter factor for blur 1 level (max blur) - */ -struct rkisp1_cif_isp_flt_config { - __u32 mode; - __u8 grn_stage1; - __u8 chr_h_mode; - __u8 chr_v_mode; - __u32 thresh_bl0; - __u32 thresh_bl1; - __u32 thresh_sh0; - __u32 thresh_sh1; - __u32 lum_weight; - __u32 fac_sh1; - __u32 fac_sh0; - __u32 fac_mid; - __u32 fac_bl0; - __u32 fac_bl1; -}; - -/** - * struct rkisp1_cif_isp_bdm_config - Configuration used by Bayer DeMosaic - * - * @demosaic_th: threshold for bayer demosaicing texture detection - */ -struct rkisp1_cif_isp_bdm_config { - __u8 demosaic_th; -}; - -/** - * struct rkisp1_cif_isp_ctk_config - Configuration used by Cross Talk correction - * - * @coeff: color correction matrix. Values are 11-bit signed fixed-point numbers with 4 bit integer - * and 7 bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF). 0 is - * represented by 0x000 and a coefficient value of 1 as 0x080. - * @ct_offset: Red, Green, Blue offsets for the crosstalk correction matrix - */ -struct rkisp1_cif_isp_ctk_config { - __u16 coeff[3][3]; - __u16 ct_offset[3]; -}; - -enum rkisp1_cif_isp_goc_mode { - RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC, - RKISP1_CIF_ISP_GOC_MODE_EQUIDISTANT -}; - -/** - * struct rkisp1_cif_isp_goc_config - Configuration used by Gamma Out correction - * - * @mode: goc mode (from enum rkisp1_cif_isp_goc_mode) - * @gamma_y: gamma out curve y-axis for all color components - */ -struct rkisp1_cif_isp_goc_config { - __u32 mode; - __u16 gamma_y[RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES]; -}; - -/** - * struct rkisp1_cif_isp_hst_config - Configuration used by Histogram - * - * @mode: histogram mode (from enum rkisp1_cif_isp_histogram_mode) - * @histogram_predivider: process every stepsize pixel, all other pixels are - * skipped - * @meas_window: coordinates of the measure window - * @hist_weight: weighting factor for sub-windows - */ -struct rkisp1_cif_isp_hst_config { - __u32 mode; - __u8 histogram_predivider; - struct rkisp1_cif_isp_window meas_window; - __u8 hist_weight[RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE]; -}; - -/** - * struct rkisp1_cif_isp_aec_config - Configuration used by Auto Exposure Control - * - * @mode: Exposure measure mode (from enum rkisp1_cif_isp_exp_meas_mode) - * @autostop: stop mode (from enum rkisp1_cif_isp_exp_ctrl_autostop) - * @meas_window: coordinates of the measure window - */ -struct rkisp1_cif_isp_aec_config { - __u32 mode; - __u32 autostop; - struct rkisp1_cif_isp_window meas_window; -}; - -/** - * struct rkisp1_cif_isp_afc_config - Configuration used by Auto Focus Control - * - * @num_afm_win: max RKISP1_CIF_ISP_AFM_MAX_WINDOWS - * @afm_win: coordinates of the meas window - * @thres: threshold used for minimizing the influence of noise - * @var_shift: the number of bits for the shift operation at the end of the - * calculation chain. - */ -struct rkisp1_cif_isp_afc_config { - __u8 num_afm_win; - struct rkisp1_cif_isp_window afm_win[RKISP1_CIF_ISP_AFM_MAX_WINDOWS]; - __u32 thres; - __u32 var_shift; -}; - -/** - * enum rkisp1_cif_isp_dpf_gain_usage - dpf gain usage - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED: don't use any gains in preprocessing stage - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS: use only the noise function gains from - * registers DPF_NF_GAIN_R, ... - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS: use only the gains from LSC module - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS: use the noise function gains and the - * gains from LSC module - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS: use only the gains from AWB module - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS: use the gains from AWB and LSC module - * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_MAX: upper border (only for an internal evaluation) - */ -enum rkisp1_cif_isp_dpf_gain_usage { - RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS, - RKISP1_CIF_ISP_DPF_GAIN_USAGE_MAX -}; - -/** - * enum rkisp1_cif_isp_dpf_rb_filtersize - Red and blue filter sizes - * @RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9: red and blue filter kernel size 13x9 - * (means 7x5 active pixel) - * @RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9: red and blue filter kernel size 9x9 - * (means 5x5 active pixel) - */ -enum rkisp1_cif_isp_dpf_rb_filtersize { - RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9, - RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9, -}; - -/** - * enum rkisp1_cif_isp_dpf_nll_scale_mode - dpf noise level scale mode - * @RKISP1_CIF_ISP_NLL_SCALE_LINEAR: use a linear scaling - * @RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC: use a logarithmic scaling - */ -enum rkisp1_cif_isp_dpf_nll_scale_mode { - RKISP1_CIF_ISP_NLL_SCALE_LINEAR, - RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC, -}; - -/** - * struct rkisp1_cif_isp_dpf_nll - Noise level lookup - * - * @coeff: Noise level Lookup coefficient - * @scale_mode: dpf noise level scale mode (from enum rkisp1_cif_isp_dpf_nll_scale_mode) - */ -struct rkisp1_cif_isp_dpf_nll { - __u16 coeff[RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS]; - __u32 scale_mode; -}; - -/** - * struct rkisp1_cif_isp_dpf_rb_flt - Red blue filter config - * - * @fltsize: The filter size for the red and blue pixels - * (from enum rkisp1_cif_isp_dpf_rb_filtersize) - * @spatial_coeff: Spatial weights - * @r_enable: enable filter processing for red pixels - * @b_enable: enable filter processing for blue pixels - */ -struct rkisp1_cif_isp_dpf_rb_flt { - __u32 fltsize; - __u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS]; - __u8 r_enable; - __u8 b_enable; -}; - -/** - * struct rkisp1_cif_isp_dpf_g_flt - Green filter Configuration - * - * @spatial_coeff: Spatial weights - * @gr_enable: enable filter processing for green pixels in green/red lines - * @gb_enable: enable filter processing for green pixels in green/blue lines - */ -struct rkisp1_cif_isp_dpf_g_flt { - __u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS]; - __u8 gr_enable; - __u8 gb_enable; -}; - -/** - * struct rkisp1_cif_isp_dpf_gain - Noise function Configuration - * - * @mode: dpf gain usage (from enum rkisp1_cif_isp_dpf_gain_usage) - * @nf_r_gain: Noise function Gain that replaces the AWB gain for red pixels - * @nf_b_gain: Noise function Gain that replaces the AWB gain for blue pixels - * @nf_gr_gain: Noise function Gain that replaces the AWB gain - * for green pixels in a red line - * @nf_gb_gain: Noise function Gain that replaces the AWB gain - * for green pixels in a blue line - */ -struct rkisp1_cif_isp_dpf_gain { - __u32 mode; - __u16 nf_r_gain; - __u16 nf_b_gain; - __u16 nf_gr_gain; - __u16 nf_gb_gain; -}; - -/** - * struct rkisp1_cif_isp_dpf_config - Configuration used by De-noising pre-filter - * - * @gain: noise function gain - * @g_flt: green filter config - * @rb_flt: red blue filter config - * @nll: noise level lookup - */ -struct rkisp1_cif_isp_dpf_config { - struct rkisp1_cif_isp_dpf_gain gain; - struct rkisp1_cif_isp_dpf_g_flt g_flt; - struct rkisp1_cif_isp_dpf_rb_flt rb_flt; - struct rkisp1_cif_isp_dpf_nll nll; -}; - -/** - * struct rkisp1_cif_isp_dpf_strength_config - strength of the filter - * - * @r: filter strength of the RED filter - * @g: filter strength of the GREEN filter - * @b: filter strength of the BLUE filter - */ -struct rkisp1_cif_isp_dpf_strength_config { - __u8 r; - __u8 g; - __u8 b; -}; - -/** - * struct rkisp1_cif_isp_isp_other_cfg - Parameters for some blocks in rockchip isp1 - * - * @dpcc_config: Defect Pixel Cluster Correction config - * @bls_config: Black Level Subtraction config - * @sdg_config: sensor degamma config - * @lsc_config: Lens Shade config - * @awb_gain_config: Auto White balance gain config - * @flt_config: filter config - * @bdm_config: demosaic config - * @ctk_config: cross talk config - * @goc_config: gamma out config - * @bls_config: black level subtraction config - * @dpf_config: De-noising pre-filter config - * @dpf_strength_config: dpf strength config - * @cproc_config: color process config - * @ie_config: image effects config - */ -struct rkisp1_cif_isp_isp_other_cfg { - struct rkisp1_cif_isp_dpcc_config dpcc_config; - struct rkisp1_cif_isp_bls_config bls_config; - struct rkisp1_cif_isp_sdg_config sdg_config; - struct rkisp1_cif_isp_lsc_config lsc_config; - struct rkisp1_cif_isp_awb_gain_config awb_gain_config; - struct rkisp1_cif_isp_flt_config flt_config; - struct rkisp1_cif_isp_bdm_config bdm_config; - struct rkisp1_cif_isp_ctk_config ctk_config; - struct rkisp1_cif_isp_goc_config goc_config; - struct rkisp1_cif_isp_dpf_config dpf_config; - struct rkisp1_cif_isp_dpf_strength_config dpf_strength_config; - struct rkisp1_cif_isp_cproc_config cproc_config; - struct rkisp1_cif_isp_ie_config ie_config; -}; - -/** - * struct rkisp1_cif_isp_isp_meas_cfg - Rockchip ISP1 Measure Parameters - * - * @awb_meas_config: auto white balance config - * @hst_config: histogram config - * @aec_config: auto exposure config - * @afc_config: auto focus config - */ -struct rkisp1_cif_isp_isp_meas_cfg { - struct rkisp1_cif_isp_awb_meas_config awb_meas_config; - struct rkisp1_cif_isp_hst_config hst_config; - struct rkisp1_cif_isp_aec_config aec_config; - struct rkisp1_cif_isp_afc_config afc_config; -}; - -/** - * struct rkisp1_params_cfg - Rockchip ISP1 Input Parameters Meta Data - * - * @module_en_update: mask the enable bits of which module should be updated - * @module_ens: mask the enable value of each module, only update the module - * which correspond bit was set in module_en_update - * @module_cfg_update: mask the config bits of which module should be updated - * @meas: measurement config - * @others: other config - */ -struct rkisp1_params_cfg { - __u32 module_en_update; - __u32 module_ens; - __u32 module_cfg_update; - - struct rkisp1_cif_isp_isp_meas_cfg meas; - struct rkisp1_cif_isp_isp_other_cfg others; -}; - -/*---------- PART2: Measurement Statistics ------------*/ - -/** - * struct rkisp1_cif_isp_awb_meas - AWB measured values - * - * @cnt: White pixel count, number of "white pixels" found during last - * measurement - * @mean_y_or_g: Mean value of Y within window and frames, - * Green if RGB is selected. - * @mean_cb_or_b: Mean value of Cb within window and frames, - * Blue if RGB is selected. - * @mean_cr_or_r: Mean value of Cr within window and frames, - * Red if RGB is selected. - */ -struct rkisp1_cif_isp_awb_meas { - __u32 cnt; - __u8 mean_y_or_g; - __u8 mean_cb_or_b; - __u8 mean_cr_or_r; -}; - -/** - * struct rkisp1_cif_isp_awb_stat - statistics automatic white balance data - * - * @awb_mean: Mean measured data - */ -struct rkisp1_cif_isp_awb_stat { - struct rkisp1_cif_isp_awb_meas awb_mean[RKISP1_CIF_ISP_AWB_MAX_GRID]; -}; - -/** - * struct rkisp1_cif_isp_bls_meas_val - BLS measured values - * - * @meas_r: Mean measured value for Bayer pattern R - * @meas_gr: Mean measured value for Bayer pattern Gr - * @meas_gb: Mean measured value for Bayer pattern Gb - * @meas_b: Mean measured value for Bayer pattern B - */ -struct rkisp1_cif_isp_bls_meas_val { - __u16 meas_r; - __u16 meas_gr; - __u16 meas_gb; - __u16 meas_b; -}; - -/** - * struct rkisp1_cif_isp_ae_stat - statistics auto exposure data - * - * @exp_mean: Mean luminance value of block xx - * @bls_val: BLS measured values - * - * Image is divided into 5x5 blocks. - */ -struct rkisp1_cif_isp_ae_stat { - __u8 exp_mean[RKISP1_CIF_ISP_AE_MEAN_MAX]; - struct rkisp1_cif_isp_bls_meas_val bls_val; -}; - -/** - * struct rkisp1_cif_isp_af_meas_val - AF measured values - * - * @sum: sharpness value - * @lum: luminance value - */ -struct rkisp1_cif_isp_af_meas_val { - __u32 sum; - __u32 lum; -}; - -/** - * struct rkisp1_cif_isp_af_stat - statistics auto focus data - * - * @window: AF measured value of window x - * - * The module measures the sharpness in 3 windows of selectable size via - * register settings(ISP_AFM_*_A/B/C) - */ -struct rkisp1_cif_isp_af_stat { - struct rkisp1_cif_isp_af_meas_val window[RKISP1_CIF_ISP_AFM_MAX_WINDOWS]; -}; - -/** - * struct rkisp1_cif_isp_hist_stat - statistics histogram data - * - * @hist_bins: measured bin counters - * - * Measurement window divided into 25 sub-windows, set - * with ISP_HIST_XXX - */ -struct rkisp1_cif_isp_hist_stat { - __u16 hist_bins[RKISP1_CIF_ISP_HIST_BIN_N_MAX]; -}; - -/** - * struct rkisp1_cif_isp_stat - Rockchip ISP1 Statistics Data - * - * @awb: statistics data for automatic white balance - * @ae: statistics data for auto exposure - * @af: statistics data for auto focus - * @hist: statistics histogram data - */ -struct rkisp1_cif_isp_stat { - struct rkisp1_cif_isp_awb_stat awb; - struct rkisp1_cif_isp_ae_stat ae; - struct rkisp1_cif_isp_af_stat af; - struct rkisp1_cif_isp_hist_stat hist; -}; - -/** - * struct rkisp1_stat_buffer - Rockchip ISP1 Statistics Meta Data - * - * @meas_type: measurement types (RKISP1_CIF_ISP_STAT_* definitions) - * @frame_id: frame ID for sync - * @params: statistics data - */ -struct rkisp1_stat_buffer { - __u32 meas_type; - __u32 frame_id; - struct rkisp1_cif_isp_stat params; -}; - -#endif /* _UAPI_RKISP1_CONFIG_H */ diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h new file mode 100644 index 000000000000..6e449e784260 --- /dev/null +++ b/include/uapi/linux/rkisp1-config.h @@ -0,0 +1,884 @@ +/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR MIT) */ +/* + * Rockchip ISP1 userspace API + * Copyright (C) 2017 Rockchip Electronics Co., Ltd. + */ + +#ifndef _UAPI_RKISP1_CONFIG_H +#define _UAPI_RKISP1_CONFIG_H + +#include + +/* Defect Pixel Cluster Detection */ +#define RKISP1_CIF_ISP_MODULE_DPCC (1U << 0) +/* Black Level Subtraction */ +#define RKISP1_CIF_ISP_MODULE_BLS (1U << 1) +/* Sensor De-gamma */ +#define RKISP1_CIF_ISP_MODULE_SDG (1U << 2) +/* Histogram */ +#define RKISP1_CIF_ISP_MODULE_HST (1U << 3) +/* Lens Shade Control */ +#define RKISP1_CIF_ISP_MODULE_LSC (1U << 4) +/* Auto White Balance Gain */ +#define RKISP1_CIF_ISP_MODULE_AWB_GAIN (1U << 5) +/* Filter */ +#define RKISP1_CIF_ISP_MODULE_FLT (1U << 6) +/* Bayer Demosaic */ +#define RKISP1_CIF_ISP_MODULE_BDM (1U << 7) +/* Cross Talk */ +#define RKISP1_CIF_ISP_MODULE_CTK (1U << 8) +/* Gamma Out Curve */ +#define RKISP1_CIF_ISP_MODULE_GOC (1U << 9) +/* Color Processing */ +#define RKISP1_CIF_ISP_MODULE_CPROC (1U << 10) +/* Auto Focus Control */ +#define RKISP1_CIF_ISP_MODULE_AFC (1U << 11) +/* Auto White Balancing */ +#define RKISP1_CIF_ISP_MODULE_AWB (1U << 12) +/* Image Effect */ +#define RKISP1_CIF_ISP_MODULE_IE (1U << 13) +/* Auto Exposure Control */ +#define RKISP1_CIF_ISP_MODULE_AEC (1U << 14) +/* Wide Dynamic Range */ +#define RKISP1_CIF_ISP_MODULE_WDR (1U << 15) +/* Denoise Pre-Filter */ +#define RKISP1_CIF_ISP_MODULE_DPF (1U << 16) +/* Denoise Pre-Filter Strength */ +#define RKISP1_CIF_ISP_MODULE_DPF_STRENGTH (1U << 17) + +#define RKISP1_CIF_ISP_CTK_COEFF_MAX 0x100 +#define RKISP1_CIF_ISP_CTK_OFFSET_MAX 0x800 + +#define RKISP1_CIF_ISP_AE_MEAN_MAX 25 +#define RKISP1_CIF_ISP_HIST_BIN_N_MAX 16 +#define RKISP1_CIF_ISP_AFM_MAX_WINDOWS 3 +#define RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE 17 + +#define RKISP1_CIF_ISP_BDM_MAX_TH 0xff + +/* + * Black level compensation + */ +/* maximum value for horizontal start address */ +#define RKISP1_CIF_ISP_BLS_START_H_MAX 0x00000fff +/* maximum value for horizontal stop address */ +#define RKISP1_CIF_ISP_BLS_STOP_H_MAX 0x00000fff +/* maximum value for vertical start address */ +#define RKISP1_CIF_ISP_BLS_START_V_MAX 0x00000fff +/* maximum value for vertical stop address */ +#define RKISP1_CIF_ISP_BLS_STOP_V_MAX 0x00000fff +/* maximum is 2^18 = 262144*/ +#define RKISP1_CIF_ISP_BLS_SAMPLES_MAX 0x00000012 +/* maximum value for fixed black level */ +#define RKISP1_CIF_ISP_BLS_FIX_SUB_MAX 0x00000fff +/* minimum value for fixed black level */ +#define RKISP1_CIF_ISP_BLS_FIX_SUB_MIN 0xfffff000 +/* 13 bit range (signed)*/ +#define RKISP1_CIF_ISP_BLS_FIX_MASK 0x00001fff + +/* + * Automatic white balance measurements + */ +#define RKISP1_CIF_ISP_AWB_MAX_GRID 1 +#define RKISP1_CIF_ISP_AWB_MAX_FRAMES 7 + +/* + * Gamma out + */ +/* Maximum number of color samples supported */ +#define RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES 17 + +/* + * Lens shade correction + */ +#define RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE 8 + +/* + * The following matches the tuning process, + * not the max capabilities of the chip. + */ +#define RKISP1_CIF_ISP_LSC_SAMPLES_MAX 17 + +/* + * Histogram calculation + */ +/* Last 3 values unused. */ +#define RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 28 + +/* + * Defect Pixel Cluster Correction + */ +#define RKISP1_CIF_ISP_DPCC_METHODS_MAX 3 + +/* + * Denoising pre filter + */ +#define RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS 17 +#define RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS 6 + +/* + * Measurement types + */ +#define RKISP1_CIF_ISP_STAT_AWB (1U << 0) +#define RKISP1_CIF_ISP_STAT_AUTOEXP (1U << 1) +#define RKISP1_CIF_ISP_STAT_AFM (1U << 2) +#define RKISP1_CIF_ISP_STAT_HIST (1U << 3) + +enum rkisp1_cif_isp_histogram_mode { + RKISP1_CIF_ISP_HISTOGRAM_MODE_DISABLE, + RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED, + RKISP1_CIF_ISP_HISTOGRAM_MODE_R_HISTOGRAM, + RKISP1_CIF_ISP_HISTOGRAM_MODE_G_HISTOGRAM, + RKISP1_CIF_ISP_HISTOGRAM_MODE_B_HISTOGRAM, + RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM +}; + +enum rkisp1_cif_isp_awb_mode_type { + RKISP1_CIF_ISP_AWB_MODE_MANUAL, + RKISP1_CIF_ISP_AWB_MODE_RGB, + RKISP1_CIF_ISP_AWB_MODE_YCBCR +}; + +enum rkisp1_cif_isp_flt_mode { + RKISP1_CIF_ISP_FLT_STATIC_MODE, + RKISP1_CIF_ISP_FLT_DYNAMIC_MODE +}; + +/** + * enum rkisp1_cif_isp_exp_ctrl_autostop - stop modes + * @RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0: continuous measurement + * @RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_1: stop measuring after a complete frame + */ +enum rkisp1_cif_isp_exp_ctrl_autostop { + RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_0 = 0, + RKISP1_CIF_ISP_EXP_CTRL_AUTOSTOP_1 = 1, +}; + +/** + * enum rkisp1_cif_isp_exp_meas_mode - Exposure measure mode + * @RKISP1_CIF_ISP_EXP_MEASURING_MODE_0: Y = 16 + 0.25R + 0.5G + 0.1094B + * @RKISP1_CIF_ISP_EXP_MEASURING_MODE_1: Y = (R + G + B) x (85/256) + */ +enum rkisp1_cif_isp_exp_meas_mode { + RKISP1_CIF_ISP_EXP_MEASURING_MODE_0, + RKISP1_CIF_ISP_EXP_MEASURING_MODE_1, +}; + +/*---------- PART1: Input Parameters ------------*/ + +/** + * struct rkisp1_cif_isp_window - measurement window. + * + * Measurements are calculated per window inside the frame. + * This struct represents a window for a measurement. + * + * @h_offs: the horizontal offset of the window from the left of the frame in pixels. + * @v_offs: the vertical offset of the window from the top of the frame in pixels. + * @h_size: the horizontal size of the window in pixels + * @v_size: the vertical size of the window in pixels. + */ +struct rkisp1_cif_isp_window { + __u16 h_offs; + __u16 v_offs; + __u16 h_size; + __u16 v_size; +}; + +/** + * struct rkisp1_cif_isp_bls_fixed_val - BLS fixed subtraction values + * + * The values will be subtracted from the sensor + * values. Therefore a negative value means addition instead of subtraction! + * + * @r: Fixed (signed!) subtraction value for Bayer pattern R + * @gr: Fixed (signed!) subtraction value for Bayer pattern Gr + * @gb: Fixed (signed!) subtraction value for Bayer pattern Gb + * @b: Fixed (signed!) subtraction value for Bayer pattern B + */ +struct rkisp1_cif_isp_bls_fixed_val { + __s16 r; + __s16 gr; + __s16 gb; + __s16 b; +}; + +/** + * struct rkisp1_cif_isp_bls_config - Configuration used by black level subtraction + * + * @enable_auto: Automatic mode activated means that the measured values + * are subtracted. Otherwise the fixed subtraction + * values will be subtracted. + * @en_windows: enabled window + * @bls_window1: Measurement window 1 size + * @bls_window2: Measurement window 2 size + * @bls_samples: Set amount of measured pixels for each Bayer position + * (A, B,C and D) to 2^bls_samples. + * @fixed_val: Fixed subtraction values + */ +struct rkisp1_cif_isp_bls_config { + __u8 enable_auto; + __u8 en_windows; + struct rkisp1_cif_isp_window bls_window1; + struct rkisp1_cif_isp_window bls_window2; + __u8 bls_samples; + struct rkisp1_cif_isp_bls_fixed_val fixed_val; +}; + +/** + * struct rkisp1_cif_isp_dpcc_methods_config - Methods Configuration used by DPCC + * + * Methods Configuration used by Defect Pixel Cluster Correction + * + * @method: Method enable bits + * @line_thresh: Line threshold + * @line_mad_fac: Line MAD factor + * @pg_fac: Peak gradient factor + * @rnd_thresh: Rank Neighbor Difference threshold + * @rg_fac: Rank gradient factor + */ +struct rkisp1_cif_isp_dpcc_methods_config { + __u32 method; + __u32 line_thresh; + __u32 line_mad_fac; + __u32 pg_fac; + __u32 rnd_thresh; + __u32 rg_fac; +}; + +/** + * struct rkisp1_cif_isp_dpcc_config - Configuration used by DPCC + * + * Configuration used by Defect Pixel Cluster Correction + * + * @mode: dpcc output mode + * @output_mode: whether use hard coded methods + * @set_use: stage1 methods set + * @methods: methods config + * @ro_limits: rank order limits + * @rnd_offs: differential rank offsets for rank neighbor difference + */ +struct rkisp1_cif_isp_dpcc_config { + __u32 mode; + __u32 output_mode; + __u32 set_use; + struct rkisp1_cif_isp_dpcc_methods_config methods[RKISP1_CIF_ISP_DPCC_METHODS_MAX]; + __u32 ro_limits; + __u32 rnd_offs; +}; + +/** + * struct rkisp1_cif_isp_gamma_corr_curve - gamma curve point definition y-axis (output). + * + * The reset values define a linear curve which has the same effect as bypass. Reset values are: + * gamma_y[0] = 0x0000, gamma_y[1] = 0x0100, ... gamma_y[15] = 0x0f00, gamma_y[16] = 0xfff + * + * @gamma_y: the values for the y-axis of gamma curve points. Each value is 12 bit. + */ +struct rkisp1_cif_isp_gamma_corr_curve { + __u16 gamma_y[RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE]; +}; + +/** + * struct rkisp1_cif_isp_gamma_curve_x_axis_pnts - De-Gamma Curve definition x increments + * (sampling points). gamma_dx0 is for the lower samples (1-8), gamma_dx1 is for the + * higher samples (9-16). The reset values for both fields is 0x44444444. This means + * that each sample is 4 units away from the previous one on the x-axis. + * + * @gamma_dx0: gamma curve sample points definitions. Bits 0:2 for sample 1. Bit 3 unused. + * Bits 4:6 for sample 2. bit 7 unused ... Bits 28:30 for sample 8. Bit 31 unused + * @gamma_dx1: gamma curve sample points definitions. Bits 0:2 for sample 9. Bit 3 unused. + * Bits 4:6 for sample 10. bit 7 unused ... Bits 28:30 for sample 16. Bit 31 unused + */ +struct rkisp1_cif_isp_gamma_curve_x_axis_pnts { + __u32 gamma_dx0; + __u32 gamma_dx1; +}; + +/** + * struct rkisp1_cif_isp_sdg_config - Configuration used by sensor degamma + * + * @curve_r: gamma curve point definition axis for red + * @curve_g: gamma curve point definition axis for green + * @curve_b: gamma curve point definition axis for blue + * @xa_pnts: x axis increments + */ +struct rkisp1_cif_isp_sdg_config { + struct rkisp1_cif_isp_gamma_corr_curve curve_r; + struct rkisp1_cif_isp_gamma_corr_curve curve_g; + struct rkisp1_cif_isp_gamma_corr_curve curve_b; + struct rkisp1_cif_isp_gamma_curve_x_axis_pnts xa_pnts; +}; + +/** + * struct rkisp1_cif_isp_lsc_config - Configuration used by Lens shading correction + * + * @r_data_tbl: sample table red + * @gr_data_tbl: sample table green (red) + * @gb_data_tbl: sample table green (blue) + * @b_data_tbl: sample table blue + * @x_grad_tbl: gradient table x + * @y_grad_tbl: gradient table y + * @x_size_tbl: size table x + * @y_size_tbl: size table y + * @config_width: not used at the moment + * @config_height: not used at the moment + */ +struct rkisp1_cif_isp_lsc_config { + __u16 r_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; + __u16 gr_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; + __u16 gb_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; + __u16 b_data_tbl[RKISP1_CIF_ISP_LSC_SAMPLES_MAX][RKISP1_CIF_ISP_LSC_SAMPLES_MAX]; + + __u16 x_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; + __u16 y_grad_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; + + __u16 x_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; + __u16 y_size_tbl[RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE]; + __u16 config_width; + __u16 config_height; +}; + +/** + * struct rkisp1_cif_isp_ie_config - Configuration used by image effects + * + * @effect: values from 'enum v4l2_colorfx'. Possible values are: V4L2_COLORFX_SEPIA, + * V4L2_COLORFX_SET_CBCR, V4L2_COLORFX_AQUA, V4L2_COLORFX_EMBOSS, + * V4L2_COLORFX_SKETCH, V4L2_COLORFX_BW, V4L2_COLORFX_NEGATIVE + * @color_sel: bits 0:2 - colors bitmask (001 - blue, 010 - green, 100 - red). + * bits 8:15 - Threshold value of the RGB colors for the color selection effect. + * @eff_mat_1: 3x3 Matrix Coefficients for Emboss Effect 1 + * @eff_mat_2: 3x3 Matrix Coefficients for Emboss Effect 2 + * @eff_mat_3: 3x3 Matrix Coefficients for Emboss 3/Sketch 1 + * @eff_mat_4: 3x3 Matrix Coefficients for Sketch Effect 2 + * @eff_mat_5: 3x3 Matrix Coefficients for Sketch Effect 3 + * @eff_tint: Chrominance increment values of tint (used for sepia effect) + */ +struct rkisp1_cif_isp_ie_config { + __u16 effect; + __u16 color_sel; + __u16 eff_mat_1; + __u16 eff_mat_2; + __u16 eff_mat_3; + __u16 eff_mat_4; + __u16 eff_mat_5; + __u16 eff_tint; +}; + +/** + * struct rkisp1_cif_isp_cproc_config - Configuration used by Color Processing + * + * @c_out_range: Chrominance pixel clipping range at output. + * (0 for limit, 1 for full) + * @y_in_range: Luminance pixel clipping range at output. + * @y_out_range: Luminance pixel clipping range at output. + * @contrast: 00~ff, 0.0~1.992 + * @brightness: 80~7F, -128~+127 + * @sat: saturation, 00~FF, 0.0~1.992 + * @hue: 80~7F, -90~+87.188 + */ +struct rkisp1_cif_isp_cproc_config { + __u8 c_out_range; + __u8 y_in_range; + __u8 y_out_range; + __u8 contrast; + __u8 brightness; + __u8 sat; + __u8 hue; +}; + +/** + * struct rkisp1_cif_isp_awb_meas_config - Configuration used by auto white balance + * + * @awb_mode: the awb meas mode. From enum rkisp1_cif_isp_awb_mode_type. + * @awb_wnd: white balance measurement window (in pixels) + * @max_y: only pixels values < max_y contribute to awb measurement, set to 0 + * to disable this feature + * @min_y: only pixels values > min_y contribute to awb measurement + * @max_csum: Chrominance sum maximum value, only consider pixels with Cb+Cr, + * smaller than threshold for awb measurements + * @min_c: Chrominance minimum value, only consider pixels with Cb/Cr + * each greater than threshold value for awb measurements + * @frames: number of frames - 1 used for mean value calculation + * (ucFrames=0 means 1 Frame) + * @awb_ref_cr: reference Cr value for AWB regulation, target for AWB + * @awb_ref_cb: reference Cb value for AWB regulation, target for AWB + * @enable_ymax_cmp: enable Y_MAX compare (Not valid in RGB measurement mode.) + */ +struct rkisp1_cif_isp_awb_meas_config { + /* + * Note: currently the h and v offsets are mapped to grid offsets + */ + struct rkisp1_cif_isp_window awb_wnd; + __u32 awb_mode; + __u8 max_y; + __u8 min_y; + __u8 max_csum; + __u8 min_c; + __u8 frames; + __u8 awb_ref_cr; + __u8 awb_ref_cb; + __u8 enable_ymax_cmp; +}; + +/** + * struct rkisp1_cif_isp_awb_gain_config - Configuration used by auto white balance gain + * + * All fields in this struct are 10 bit, where: + * 0x100h = 1, unsigned integer value, range 0 to 4 with 8 bit fractional part. + * + * out_data_x = ( AWB_GAIN_X * in_data + 128) >> 8 + * + * @gain_red: gain value for red component. + * @gain_green_r: gain value for green component in red line. + * @gain_blue: gain value for blue component. + * @gain_green_b: gain value for green component in blue line. + */ +struct rkisp1_cif_isp_awb_gain_config { + __u16 gain_red; + __u16 gain_green_r; + __u16 gain_blue; + __u16 gain_green_b; +}; + +/** + * struct rkisp1_cif_isp_flt_config - Configuration used by ISP filtering + * + * All 4 threshold fields (thresh_*) are 10 bits. + * All 6 factor fields (fac_*) are 6 bits. + * + * @mode: ISP_FILT_MODE register fields (from enum rkisp1_cif_isp_flt_mode) + * @grn_stage1: Green filter stage 1 select (range 0x0...0x8) + * @chr_h_mode: Chroma filter horizontal mode + * @chr_v_mode: Chroma filter vertical mode + * @thresh_bl0: If thresh_bl1 < sum_grad < thresh_bl0 then fac_bl0 is selected (blurring th) + * @thresh_bl1: If sum_grad < thresh_bl1 then fac_bl1 is selected (blurring th) + * @thresh_sh0: If thresh_sh0 < sum_grad < thresh_sh1 then thresh_sh0 is selected (sharpening th) + * @thresh_sh1: If thresh_sh1 < sum_grad then thresh_sh1 is selected (sharpening th) + * @lum_weight: Parameters for luminance weight function. + * @fac_sh1: filter factor for sharp1 level + * @fac_sh0: filter factor for sharp0 level + * @fac_mid: filter factor for mid level and for static filter mode + * @fac_bl0: filter factor for blur 0 level + * @fac_bl1: filter factor for blur 1 level (max blur) + */ +struct rkisp1_cif_isp_flt_config { + __u32 mode; + __u8 grn_stage1; + __u8 chr_h_mode; + __u8 chr_v_mode; + __u32 thresh_bl0; + __u32 thresh_bl1; + __u32 thresh_sh0; + __u32 thresh_sh1; + __u32 lum_weight; + __u32 fac_sh1; + __u32 fac_sh0; + __u32 fac_mid; + __u32 fac_bl0; + __u32 fac_bl1; +}; + +/** + * struct rkisp1_cif_isp_bdm_config - Configuration used by Bayer DeMosaic + * + * @demosaic_th: threshold for bayer demosaicing texture detection + */ +struct rkisp1_cif_isp_bdm_config { + __u8 demosaic_th; +}; + +/** + * struct rkisp1_cif_isp_ctk_config - Configuration used by Cross Talk correction + * + * @coeff: color correction matrix. Values are 11-bit signed fixed-point numbers with 4 bit integer + * and 7 bit fractional part, ranging from -8 (0x400) to +7.992 (0x3FF). 0 is + * represented by 0x000 and a coefficient value of 1 as 0x080. + * @ct_offset: Red, Green, Blue offsets for the crosstalk correction matrix + */ +struct rkisp1_cif_isp_ctk_config { + __u16 coeff[3][3]; + __u16 ct_offset[3]; +}; + +enum rkisp1_cif_isp_goc_mode { + RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC, + RKISP1_CIF_ISP_GOC_MODE_EQUIDISTANT +}; + +/** + * struct rkisp1_cif_isp_goc_config - Configuration used by Gamma Out correction + * + * @mode: goc mode (from enum rkisp1_cif_isp_goc_mode) + * @gamma_y: gamma out curve y-axis for all color components + */ +struct rkisp1_cif_isp_goc_config { + __u32 mode; + __u16 gamma_y[RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES]; +}; + +/** + * struct rkisp1_cif_isp_hst_config - Configuration used by Histogram + * + * @mode: histogram mode (from enum rkisp1_cif_isp_histogram_mode) + * @histogram_predivider: process every stepsize pixel, all other pixels are + * skipped + * @meas_window: coordinates of the measure window + * @hist_weight: weighting factor for sub-windows + */ +struct rkisp1_cif_isp_hst_config { + __u32 mode; + __u8 histogram_predivider; + struct rkisp1_cif_isp_window meas_window; + __u8 hist_weight[RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE]; +}; + +/** + * struct rkisp1_cif_isp_aec_config - Configuration used by Auto Exposure Control + * + * @mode: Exposure measure mode (from enum rkisp1_cif_isp_exp_meas_mode) + * @autostop: stop mode (from enum rkisp1_cif_isp_exp_ctrl_autostop) + * @meas_window: coordinates of the measure window + */ +struct rkisp1_cif_isp_aec_config { + __u32 mode; + __u32 autostop; + struct rkisp1_cif_isp_window meas_window; +}; + +/** + * struct rkisp1_cif_isp_afc_config - Configuration used by Auto Focus Control + * + * @num_afm_win: max RKISP1_CIF_ISP_AFM_MAX_WINDOWS + * @afm_win: coordinates of the meas window + * @thres: threshold used for minimizing the influence of noise + * @var_shift: the number of bits for the shift operation at the end of the + * calculation chain. + */ +struct rkisp1_cif_isp_afc_config { + __u8 num_afm_win; + struct rkisp1_cif_isp_window afm_win[RKISP1_CIF_ISP_AFM_MAX_WINDOWS]; + __u32 thres; + __u32 var_shift; +}; + +/** + * enum rkisp1_cif_isp_dpf_gain_usage - dpf gain usage + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED: don't use any gains in preprocessing stage + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS: use only the noise function gains from + * registers DPF_NF_GAIN_R, ... + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS: use only the gains from LSC module + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS: use the noise function gains and the + * gains from LSC module + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS: use only the gains from AWB module + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS: use the gains from AWB and LSC module + * @RKISP1_CIF_ISP_DPF_GAIN_USAGE_MAX: upper border (only for an internal evaluation) + */ +enum rkisp1_cif_isp_dpf_gain_usage { + RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_GAINS, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_LSC_GAINS, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_NF_LSC_GAINS, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_GAINS, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_AWB_LSC_GAINS, + RKISP1_CIF_ISP_DPF_GAIN_USAGE_MAX +}; + +/** + * enum rkisp1_cif_isp_dpf_rb_filtersize - Red and blue filter sizes + * @RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9: red and blue filter kernel size 13x9 + * (means 7x5 active pixel) + * @RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9: red and blue filter kernel size 9x9 + * (means 5x5 active pixel) + */ +enum rkisp1_cif_isp_dpf_rb_filtersize { + RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_13x9, + RKISP1_CIF_ISP_DPF_RB_FILTERSIZE_9x9, +}; + +/** + * enum rkisp1_cif_isp_dpf_nll_scale_mode - dpf noise level scale mode + * @RKISP1_CIF_ISP_NLL_SCALE_LINEAR: use a linear scaling + * @RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC: use a logarithmic scaling + */ +enum rkisp1_cif_isp_dpf_nll_scale_mode { + RKISP1_CIF_ISP_NLL_SCALE_LINEAR, + RKISP1_CIF_ISP_NLL_SCALE_LOGARITHMIC, +}; + +/** + * struct rkisp1_cif_isp_dpf_nll - Noise level lookup + * + * @coeff: Noise level Lookup coefficient + * @scale_mode: dpf noise level scale mode (from enum rkisp1_cif_isp_dpf_nll_scale_mode) + */ +struct rkisp1_cif_isp_dpf_nll { + __u16 coeff[RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS]; + __u32 scale_mode; +}; + +/** + * struct rkisp1_cif_isp_dpf_rb_flt - Red blue filter config + * + * @fltsize: The filter size for the red and blue pixels + * (from enum rkisp1_cif_isp_dpf_rb_filtersize) + * @spatial_coeff: Spatial weights + * @r_enable: enable filter processing for red pixels + * @b_enable: enable filter processing for blue pixels + */ +struct rkisp1_cif_isp_dpf_rb_flt { + __u32 fltsize; + __u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS]; + __u8 r_enable; + __u8 b_enable; +}; + +/** + * struct rkisp1_cif_isp_dpf_g_flt - Green filter Configuration + * + * @spatial_coeff: Spatial weights + * @gr_enable: enable filter processing for green pixels in green/red lines + * @gb_enable: enable filter processing for green pixels in green/blue lines + */ +struct rkisp1_cif_isp_dpf_g_flt { + __u8 spatial_coeff[RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS]; + __u8 gr_enable; + __u8 gb_enable; +}; + +/** + * struct rkisp1_cif_isp_dpf_gain - Noise function Configuration + * + * @mode: dpf gain usage (from enum rkisp1_cif_isp_dpf_gain_usage) + * @nf_r_gain: Noise function Gain that replaces the AWB gain for red pixels + * @nf_b_gain: Noise function Gain that replaces the AWB gain for blue pixels + * @nf_gr_gain: Noise function Gain that replaces the AWB gain + * for green pixels in a red line + * @nf_gb_gain: Noise function Gain that replaces the AWB gain + * for green pixels in a blue line + */ +struct rkisp1_cif_isp_dpf_gain { + __u32 mode; + __u16 nf_r_gain; + __u16 nf_b_gain; + __u16 nf_gr_gain; + __u16 nf_gb_gain; +}; + +/** + * struct rkisp1_cif_isp_dpf_config - Configuration used by De-noising pre-filter + * + * @gain: noise function gain + * @g_flt: green filter config + * @rb_flt: red blue filter config + * @nll: noise level lookup + */ +struct rkisp1_cif_isp_dpf_config { + struct rkisp1_cif_isp_dpf_gain gain; + struct rkisp1_cif_isp_dpf_g_flt g_flt; + struct rkisp1_cif_isp_dpf_rb_flt rb_flt; + struct rkisp1_cif_isp_dpf_nll nll; +}; + +/** + * struct rkisp1_cif_isp_dpf_strength_config - strength of the filter + * + * @r: filter strength of the RED filter + * @g: filter strength of the GREEN filter + * @b: filter strength of the BLUE filter + */ +struct rkisp1_cif_isp_dpf_strength_config { + __u8 r; + __u8 g; + __u8 b; +}; + +/** + * struct rkisp1_cif_isp_isp_other_cfg - Parameters for some blocks in rockchip isp1 + * + * @dpcc_config: Defect Pixel Cluster Correction config + * @bls_config: Black Level Subtraction config + * @sdg_config: sensor degamma config + * @lsc_config: Lens Shade config + * @awb_gain_config: Auto White balance gain config + * @flt_config: filter config + * @bdm_config: demosaic config + * @ctk_config: cross talk config + * @goc_config: gamma out config + * @bls_config: black level subtraction config + * @dpf_config: De-noising pre-filter config + * @dpf_strength_config: dpf strength config + * @cproc_config: color process config + * @ie_config: image effects config + */ +struct rkisp1_cif_isp_isp_other_cfg { + struct rkisp1_cif_isp_dpcc_config dpcc_config; + struct rkisp1_cif_isp_bls_config bls_config; + struct rkisp1_cif_isp_sdg_config sdg_config; + struct rkisp1_cif_isp_lsc_config lsc_config; + struct rkisp1_cif_isp_awb_gain_config awb_gain_config; + struct rkisp1_cif_isp_flt_config flt_config; + struct rkisp1_cif_isp_bdm_config bdm_config; + struct rkisp1_cif_isp_ctk_config ctk_config; + struct rkisp1_cif_isp_goc_config goc_config; + struct rkisp1_cif_isp_dpf_config dpf_config; + struct rkisp1_cif_isp_dpf_strength_config dpf_strength_config; + struct rkisp1_cif_isp_cproc_config cproc_config; + struct rkisp1_cif_isp_ie_config ie_config; +}; + +/** + * struct rkisp1_cif_isp_isp_meas_cfg - Rockchip ISP1 Measure Parameters + * + * @awb_meas_config: auto white balance config + * @hst_config: histogram config + * @aec_config: auto exposure config + * @afc_config: auto focus config + */ +struct rkisp1_cif_isp_isp_meas_cfg { + struct rkisp1_cif_isp_awb_meas_config awb_meas_config; + struct rkisp1_cif_isp_hst_config hst_config; + struct rkisp1_cif_isp_aec_config aec_config; + struct rkisp1_cif_isp_afc_config afc_config; +}; + +/** + * struct rkisp1_params_cfg - Rockchip ISP1 Input Parameters Meta Data + * + * @module_en_update: mask the enable bits of which module should be updated + * @module_ens: mask the enable value of each module, only update the module + * which correspond bit was set in module_en_update + * @module_cfg_update: mask the config bits of which module should be updated + * @meas: measurement config + * @others: other config + */ +struct rkisp1_params_cfg { + __u32 module_en_update; + __u32 module_ens; + __u32 module_cfg_update; + + struct rkisp1_cif_isp_isp_meas_cfg meas; + struct rkisp1_cif_isp_isp_other_cfg others; +}; + +/*---------- PART2: Measurement Statistics ------------*/ + +/** + * struct rkisp1_cif_isp_awb_meas - AWB measured values + * + * @cnt: White pixel count, number of "white pixels" found during last + * measurement + * @mean_y_or_g: Mean value of Y within window and frames, + * Green if RGB is selected. + * @mean_cb_or_b: Mean value of Cb within window and frames, + * Blue if RGB is selected. + * @mean_cr_or_r: Mean value of Cr within window and frames, + * Red if RGB is selected. + */ +struct rkisp1_cif_isp_awb_meas { + __u32 cnt; + __u8 mean_y_or_g; + __u8 mean_cb_or_b; + __u8 mean_cr_or_r; +}; + +/** + * struct rkisp1_cif_isp_awb_stat - statistics automatic white balance data + * + * @awb_mean: Mean measured data + */ +struct rkisp1_cif_isp_awb_stat { + struct rkisp1_cif_isp_awb_meas awb_mean[RKISP1_CIF_ISP_AWB_MAX_GRID]; +}; + +/** + * struct rkisp1_cif_isp_bls_meas_val - BLS measured values + * + * @meas_r: Mean measured value for Bayer pattern R + * @meas_gr: Mean measured value for Bayer pattern Gr + * @meas_gb: Mean measured value for Bayer pattern Gb + * @meas_b: Mean measured value for Bayer pattern B + */ +struct rkisp1_cif_isp_bls_meas_val { + __u16 meas_r; + __u16 meas_gr; + __u16 meas_gb; + __u16 meas_b; +}; + +/** + * struct rkisp1_cif_isp_ae_stat - statistics auto exposure data + * + * @exp_mean: Mean luminance value of block xx + * @bls_val: BLS measured values + * + * Image is divided into 5x5 blocks. + */ +struct rkisp1_cif_isp_ae_stat { + __u8 exp_mean[RKISP1_CIF_ISP_AE_MEAN_MAX]; + struct rkisp1_cif_isp_bls_meas_val bls_val; +}; + +/** + * struct rkisp1_cif_isp_af_meas_val - AF measured values + * + * @sum: sharpness value + * @lum: luminance value + */ +struct rkisp1_cif_isp_af_meas_val { + __u32 sum; + __u32 lum; +}; + +/** + * struct rkisp1_cif_isp_af_stat - statistics auto focus data + * + * @window: AF measured value of window x + * + * The module measures the sharpness in 3 windows of selectable size via + * register settings(ISP_AFM_*_A/B/C) + */ +struct rkisp1_cif_isp_af_stat { + struct rkisp1_cif_isp_af_meas_val window[RKISP1_CIF_ISP_AFM_MAX_WINDOWS]; +}; + +/** + * struct rkisp1_cif_isp_hist_stat - statistics histogram data + * + * @hist_bins: measured bin counters + * + * Measurement window divided into 25 sub-windows, set + * with ISP_HIST_XXX + */ +struct rkisp1_cif_isp_hist_stat { + __u16 hist_bins[RKISP1_CIF_ISP_HIST_BIN_N_MAX]; +}; + +/** + * struct rkisp1_cif_isp_stat - Rockchip ISP1 Statistics Data + * + * @awb: statistics data for automatic white balance + * @ae: statistics data for auto exposure + * @af: statistics data for auto focus + * @hist: statistics histogram data + */ +struct rkisp1_cif_isp_stat { + struct rkisp1_cif_isp_awb_stat awb; + struct rkisp1_cif_isp_ae_stat ae; + struct rkisp1_cif_isp_af_stat af; + struct rkisp1_cif_isp_hist_stat hist; +}; + +/** + * struct rkisp1_stat_buffer - Rockchip ISP1 Statistics Meta Data + * + * @meas_type: measurement types (RKISP1_CIF_ISP_STAT_* definitions) + * @frame_id: frame ID for sync + * @params: statistics data + */ +struct rkisp1_stat_buffer { + __u32 meas_type; + __u32 frame_id; + struct rkisp1_cif_isp_stat params; +}; + +#endif /* _UAPI_RKISP1_CONFIG_H */ -- cgit v1.2.3 From d3f863a63fe4332cfda6174dfd4d2532eca7faf0 Mon Sep 17 00:00:00 2001 From: Tianshu Qiu Date: Thu, 29 Oct 2020 03:59:01 +0100 Subject: media: i2c: Add ov9734 image sensor driver Add a v4l2 sub-device driver for the OminiVision ov9734 image sensor which can deliver maximum 720p image frames at 30 fps. This driver also add vertical blanking, exposure, test pattern, digital and analog gain control for the image sensor. Signed-off-by: Bingbu Cao Signed-off-by: Tianshu Qiu Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 8 + drivers/media/i2c/Kconfig | 14 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ov9734.c | 1018 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1041 insertions(+) create mode 100644 drivers/media/i2c/ov9734.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 352b8eaa21f7..20e4afc53bdb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12995,6 +12995,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/ov9650.txt F: drivers/media/i2c/ov9650.c +OMNIVISION OV9734 SENSOR DRIVER +M: Tianshu Qiu +R: Bingbu Cao +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/i2c/ov9734.c + ONENAND FLASH DRIVER M: Kyungmin Park L: linux-mtd@lists.infradead.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index c64326ca331c..369b6d859da5 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1051,6 +1051,20 @@ config VIDEO_OV9650 This is a V4L2 sensor driver for the Omnivision OV9650 and OV9652 camera sensors. +config VIDEO_OV9734 + tristate "OmniVision OV9734 sensor support" + depends on VIDEO_V4L2 && I2C + depends on ACPI || COMPILE_TEST + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OV9734 camera. + + To compile this driver as a module, choose M here: the + module's name is ov9734. + config VIDEO_OV13858 tristate "OmniVision OV13858 sensor support" depends on I2C && VIDEO_V4L2 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f0a77473979d..b448506ce503 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_VIDEO_OV7740) += ov7740.o obj-$(CONFIG_VIDEO_OV8856) += ov8856.o obj-$(CONFIG_VIDEO_OV9640) += ov9640.o obj-$(CONFIG_VIDEO_OV9650) += ov9650.o +obj-$(CONFIG_VIDEO_OV9734) += ov9734.o obj-$(CONFIG_VIDEO_OV13858) += ov13858.o obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c new file mode 100644 index 000000000000..4b9a2e9288e7 --- /dev/null +++ b/drivers/media/i2c/ov9734.c @@ -0,0 +1,1018 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OV9734_LINK_FREQ_180MHZ 180000000ULL +#define OV9734_SCLK 36000000LL +#define OV9734_MCLK 19200000 +/* ov9734 only support 1-lane mipi output */ +#define OV9734_DATA_LANES 1 +#define OV9734_RGB_DEPTH 10 + +#define OV9734_REG_CHIP_ID 0x300a +#define OV9734_CHIP_ID 0x9734 + +#define OV9734_REG_MODE_SELECT 0x0100 +#define OV9734_MODE_STANDBY 0x00 +#define OV9734_MODE_STREAMING 0x01 + +/* vertical-timings from sensor */ +#define OV9734_REG_VTS 0x380e +#define OV9734_VTS_30FPS 0x0322 +#define OV9734_VTS_30FPS_MIN 0x0322 +#define OV9734_VTS_MAX 0x7fff + +/* horizontal-timings from sensor */ +#define OV9734_REG_HTS 0x380c + +/* Exposure controls from sensor */ +#define OV9734_REG_EXPOSURE 0x3500 +#define OV9734_EXPOSURE_MIN 4 +#define OV9734_EXPOSURE_MAX_MARGIN 4 +#define OV9734_EXPOSURE_STEP 1 + +/* Analog gain controls from sensor */ +#define OV9734_REG_ANALOG_GAIN 0x350a +#define OV9734_ANAL_GAIN_MIN 16 +#define OV9734_ANAL_GAIN_MAX 248 +#define OV9734_ANAL_GAIN_STEP 1 + +/* Digital gain controls from sensor */ +#define OV9734_REG_MWB_R_GAIN 0x5180 +#define OV9734_REG_MWB_G_GAIN 0x5182 +#define OV9734_REG_MWB_B_GAIN 0x5184 +#define OV9734_DGTL_GAIN_MIN 256 +#define OV9734_DGTL_GAIN_MAX 1023 +#define OV9734_DGTL_GAIN_STEP 1 +#define OV9734_DGTL_GAIN_DEFAULT 256 + +/* Test Pattern Control */ +#define OV9734_REG_TEST_PATTERN 0x5080 +#define OV9734_TEST_PATTERN_ENABLE BIT(7) +#define OV9734_TEST_PATTERN_BAR_SHIFT 2 + +enum { + OV9734_LINK_FREQ_180MHZ_INDEX, +}; + +struct ov9734_reg { + u16 address; + u8 val; +}; + +struct ov9734_reg_list { + u32 num_of_regs; + const struct ov9734_reg *regs; +}; + +struct ov9734_link_freq_config { + const struct ov9734_reg_list reg_list; +}; + +struct ov9734_mode { + /* Frame width in pixels */ + u32 width; + + /* Frame height in pixels */ + u32 height; + + /* Horizontal timining size */ + u32 hts; + + /* Default vertical timining size */ + u32 vts_def; + + /* Min vertical timining size */ + u32 vts_min; + + /* Link frequency needed for this resolution */ + u32 link_freq_index; + + /* Sensor register settings for this resolution */ + const struct ov9734_reg_list reg_list; +}; + +static const struct ov9734_reg mipi_data_rate_360mbps[] = { + {0x3030, 0x19}, + {0x3080, 0x02}, + {0x3081, 0x4b}, + {0x3082, 0x04}, + {0x3083, 0x00}, + {0x3084, 0x02}, + {0x3085, 0x01}, + {0x3086, 0x01}, + {0x3089, 0x01}, + {0x308a, 0x00}, + {0x301e, 0x15}, + {0x3103, 0x01}, +}; + +static const struct ov9734_reg mode_1296x734_regs[] = { + {0x3001, 0x00}, + {0x3002, 0x00}, + {0x3007, 0x00}, + {0x3010, 0x00}, + {0x3011, 0x08}, + {0x3014, 0x22}, + {0x3600, 0x55}, + {0x3601, 0x02}, + {0x3605, 0x22}, + {0x3611, 0xe7}, + {0x3654, 0x10}, + {0x3655, 0x77}, + {0x3656, 0x77}, + {0x3657, 0x07}, + {0x3658, 0x22}, + {0x3659, 0x22}, + {0x365a, 0x02}, + {0x3784, 0x05}, + {0x3785, 0x55}, + {0x37c0, 0x07}, + {0x3800, 0x00}, + {0x3801, 0x04}, + {0x3802, 0x00}, + {0x3803, 0x04}, + {0x3804, 0x05}, + {0x3805, 0x0b}, + {0x3806, 0x02}, + {0x3807, 0xdb}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x02}, + {0x380b, 0xd0}, + {0x380c, 0x05}, + {0x380d, 0xc6}, + {0x380e, 0x03}, + {0x380f, 0x22}, + {0x3810, 0x00}, + {0x3811, 0x04}, + {0x3812, 0x00}, + {0x3813, 0x04}, + {0x3816, 0x00}, + {0x3817, 0x00}, + {0x3818, 0x00}, + {0x3819, 0x04}, + {0x3820, 0x18}, + {0x3821, 0x00}, + {0x382c, 0x06}, + {0x3500, 0x00}, + {0x3501, 0x31}, + {0x3502, 0x00}, + {0x3503, 0x03}, + {0x3504, 0x00}, + {0x3505, 0x00}, + {0x3509, 0x10}, + {0x350a, 0x00}, + {0x350b, 0x40}, + {0x3d00, 0x00}, + {0x3d01, 0x00}, + {0x3d02, 0x00}, + {0x3d03, 0x00}, + {0x3d04, 0x00}, + {0x3d05, 0x00}, + {0x3d06, 0x00}, + {0x3d07, 0x00}, + {0x3d08, 0x00}, + {0x3d09, 0x00}, + {0x3d0a, 0x00}, + {0x3d0b, 0x00}, + {0x3d0c, 0x00}, + {0x3d0d, 0x00}, + {0x3d0e, 0x00}, + {0x3d0f, 0x00}, + {0x3d80, 0x00}, + {0x3d81, 0x00}, + {0x3d82, 0x38}, + {0x3d83, 0xa4}, + {0x3d84, 0x00}, + {0x3d85, 0x00}, + {0x3d86, 0x1f}, + {0x3d87, 0x03}, + {0x3d8b, 0x00}, + {0x3d8f, 0x00}, + {0x4001, 0xe0}, + {0x4009, 0x0b}, + {0x4300, 0x03}, + {0x4301, 0xff}, + {0x4304, 0x00}, + {0x4305, 0x00}, + {0x4309, 0x00}, + {0x4600, 0x00}, + {0x4601, 0x80}, + {0x4800, 0x00}, + {0x4805, 0x00}, + {0x4821, 0x50}, + {0x4823, 0x50}, + {0x4837, 0x2d}, + {0x4a00, 0x00}, + {0x4f00, 0x80}, + {0x4f01, 0x10}, + {0x4f02, 0x00}, + {0x4f03, 0x00}, + {0x4f04, 0x00}, + {0x4f05, 0x00}, + {0x4f06, 0x00}, + {0x4f07, 0x00}, + {0x4f08, 0x00}, + {0x4f09, 0x00}, + {0x5000, 0x2f}, + {0x500c, 0x00}, + {0x500d, 0x00}, + {0x500e, 0x00}, + {0x500f, 0x00}, + {0x5010, 0x00}, + {0x5011, 0x00}, + {0x5012, 0x00}, + {0x5013, 0x00}, + {0x5014, 0x00}, + {0x5015, 0x00}, + {0x5016, 0x00}, + {0x5017, 0x00}, + {0x5080, 0x00}, + {0x5180, 0x01}, + {0x5181, 0x00}, + {0x5182, 0x01}, + {0x5183, 0x00}, + {0x5184, 0x01}, + {0x5185, 0x00}, + {0x5708, 0x06}, + {0x380f, 0x2a}, + {0x5780, 0x3e}, + {0x5781, 0x0f}, + {0x5782, 0x44}, + {0x5783, 0x02}, + {0x5784, 0x01}, + {0x5785, 0x01}, + {0x5786, 0x00}, + {0x5787, 0x04}, + {0x5788, 0x02}, + {0x5789, 0x0f}, + {0x578a, 0xfd}, + {0x578b, 0xf5}, + {0x578c, 0xf5}, + {0x578d, 0x03}, + {0x578e, 0x08}, + {0x578f, 0x0c}, + {0x5790, 0x08}, + {0x5791, 0x04}, + {0x5792, 0x00}, + {0x5793, 0x52}, + {0x5794, 0xa3}, + {0x5000, 0x3f}, + {0x3801, 0x00}, + {0x3803, 0x00}, + {0x3805, 0x0f}, + {0x3807, 0xdf}, + {0x3809, 0x10}, + {0x380b, 0xde}, + {0x3811, 0x00}, + {0x3813, 0x01}, +}; + +static const char * const ov9734_test_pattern_menu[] = { + "Disabled", + "Standard Color Bar", + "Top-Bottom Darker Color Bar", + "Right-Left Darker Color Bar", + "Bottom-Top Darker Color Bar", +}; + +static const s64 link_freq_menu_items[] = { + OV9734_LINK_FREQ_180MHZ, +}; + +static const struct ov9734_link_freq_config link_freq_configs[] = { + [OV9734_LINK_FREQ_180MHZ_INDEX] = { + .reg_list = { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_360mbps), + .regs = mipi_data_rate_360mbps, + } + }, +}; + +static const struct ov9734_mode supported_modes[] = { + { + .width = 1296, + .height = 734, + .hts = 0x5c6, + .vts_def = OV9734_VTS_30FPS, + .vts_min = OV9734_VTS_30FPS_MIN, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1296x734_regs), + .regs = mode_1296x734_regs, + }, + .link_freq_index = OV9734_LINK_FREQ_180MHZ_INDEX, + }, +}; + +struct ov9734 { + struct v4l2_subdev sd; + struct media_pad pad; + 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; + + /* Current mode */ + const struct ov9734_mode *cur_mode; + + /* To serialize asynchronus callbacks */ + struct mutex mutex; + + /* Streaming on/off */ + bool streaming; +}; + +static inline struct ov9734 *to_ov9734(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct ov9734, sd); +} + +static u64 to_pixel_rate(u32 f_index) +{ + u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV9734_DATA_LANES; + + do_div(pixel_rate, OV9734_RGB_DEPTH); + + return pixel_rate; +} + +static u64 to_pixels_per_line(u32 hts, u32 f_index) +{ + u64 ppl = hts * to_pixel_rate(f_index); + + do_div(ppl, OV9734_SCLK); + + return ppl; +} + +static int ov9734_read_reg(struct ov9734 *ov9734, u16 reg, u16 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + struct i2c_msg msgs[2]; + u8 addr_buf[2]; + u8 data_buf[4] = {0}; + int ret; + + if (len > sizeof(data_buf)) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(addr_buf); + msgs[0].buf = addr_buf; + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[sizeof(data_buf) - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return ret < 0 ? ret : -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +static int ov9734_write_reg(struct ov9734 *ov9734, u16 reg, u16 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + u8 buf[6]; + int ret = 0; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << 8 * (4 - len), buf + 2); + + ret = i2c_master_send(client, buf, len + 2); + if (ret != len + 2) + return ret < 0 ? ret : -EIO; + + return 0; +} + +static int ov9734_write_reg_list(struct ov9734 *ov9734, + const struct ov9734_reg_list *r_list) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + unsigned int i; + int ret; + + for (i = 0; i < r_list->num_of_regs; i++) { + ret = ov9734_write_reg(ov9734, r_list->regs[i].address, 1, + r_list->regs[i].val); + if (ret) { + dev_err_ratelimited(&client->dev, + "write reg 0x%4.4x return err = %d", + r_list->regs[i].address, ret); + return ret; + } + } + + return 0; +} + +static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain) +{ + int ret; + + ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_R_GAIN, 2, d_gain); + if (ret) + return ret; + + ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_G_GAIN, 2, d_gain); + if (ret) + return ret; + + return ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain); +} + +static int ov9734_test_pattern(struct ov9734 *ov9734, u32 pattern) +{ + if (pattern) + pattern = (pattern - 1) << OV9734_TEST_PATTERN_BAR_SHIFT | + OV9734_TEST_PATTERN_ENABLE; + + return ov9734_write_reg(ov9734, OV9734_REG_TEST_PATTERN, 1, pattern); +} + +static int ov9734_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov9734 *ov9734 = container_of(ctrl->handler, + struct ov9734, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + s64 exposure_max; + int ret = 0; + + /* Propagate change of current control to all related controls */ + if (ctrl->id == V4L2_CID_VBLANK) { + /* Update max exposure while meeting expected vblanking */ + exposure_max = ov9734->cur_mode->height + ctrl->val - + OV9734_EXPOSURE_MAX_MARGIN; + __v4l2_ctrl_modify_range(ov9734->exposure, + ov9734->exposure->minimum, + exposure_max, ov9734->exposure->step, + exposure_max); + } + + /* V4L2 controls values will be applied only when power is already up */ + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = ov9734_write_reg(ov9734, OV9734_REG_ANALOG_GAIN, + 2, ctrl->val); + break; + + case V4L2_CID_DIGITAL_GAIN: + ret = ov9734_update_digital_gain(ov9734, ctrl->val); + break; + + case V4L2_CID_EXPOSURE: + /* 4 least significant bits of expsoure are fractional part */ + ret = ov9734_write_reg(ov9734, OV9734_REG_EXPOSURE, + 3, ctrl->val << 4); + break; + + case V4L2_CID_VBLANK: + ret = ov9734_write_reg(ov9734, OV9734_REG_VTS, 2, + ov9734->cur_mode->height + ctrl->val); + break; + + case V4L2_CID_TEST_PATTERN: + ret = ov9734_test_pattern(ov9734, ctrl->val); + break; + + default: + ret = -EINVAL; + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ov9734_ctrl_ops = { + .s_ctrl = ov9734_set_ctrl, +}; + +static int ov9734_init_controls(struct ov9734 *ov9734) +{ + struct v4l2_ctrl_handler *ctrl_hdlr; + const struct ov9734_mode *cur_mode; + s64 exposure_max, h_blank, pixel_rate; + u32 vblank_min, vblank_max, vblank_default; + int ret, size; + + ctrl_hdlr = &ov9734->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); + if (ret) + return ret; + + ctrl_hdlr->lock = &ov9734->mutex; + cur_mode = ov9734->cur_mode; + size = ARRAY_SIZE(link_freq_menu_items); + ov9734->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_LINK_FREQ, + size - 1, 0, + link_freq_menu_items); + if (ov9734->link_freq) + ov9734->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + pixel_rate = to_pixel_rate(OV9734_LINK_FREQ_180MHZ_INDEX); + ov9734->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_PIXEL_RATE, 0, + pixel_rate, 1, pixel_rate); + vblank_min = cur_mode->vts_min - cur_mode->height; + vblank_max = OV9734_VTS_MAX - cur_mode->height; + vblank_default = cur_mode->vts_def - cur_mode->height; + ov9734->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_VBLANK, vblank_min, + vblank_max, 1, vblank_default); + h_blank = to_pixels_per_line(cur_mode->hts, cur_mode->link_freq_index); + h_blank -= cur_mode->width; + ov9734->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_HBLANK, h_blank, h_blank, 1, + h_blank); + if (ov9734->hblank) + ov9734->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + OV9734_ANAL_GAIN_MIN, OV9734_ANAL_GAIN_MAX, + OV9734_ANAL_GAIN_STEP, OV9734_ANAL_GAIN_MIN); + v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + OV9734_DGTL_GAIN_MIN, OV9734_DGTL_GAIN_MAX, + OV9734_DGTL_GAIN_STEP, OV9734_DGTL_GAIN_DEFAULT); + exposure_max = ov9734->cur_mode->vts_def - OV9734_EXPOSURE_MAX_MARGIN; + ov9734->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_EXPOSURE, + OV9734_EXPOSURE_MIN, exposure_max, + OV9734_EXPOSURE_STEP, + exposure_max); + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov9734_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov9734_test_pattern_menu) - 1, + 0, 0, ov9734_test_pattern_menu); + if (ctrl_hdlr->error) + return ctrl_hdlr->error; + + ov9734->sd.ctrl_handler = ctrl_hdlr; + + return 0; +} + +static void ov9734_update_pad_format(const struct ov9734_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->width = mode->width; + fmt->height = mode->height; + fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; + fmt->field = V4L2_FIELD_NONE; +} + +static int ov9734_start_streaming(struct ov9734 *ov9734) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + const struct ov9734_reg_list *reg_list; + int link_freq_index, ret; + + link_freq_index = ov9734->cur_mode->link_freq_index; + reg_list = &link_freq_configs[link_freq_index].reg_list; + ret = ov9734_write_reg_list(ov9734, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set plls"); + return ret; + } + + reg_list = &ov9734->cur_mode->reg_list; + ret = ov9734_write_reg_list(ov9734, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set mode"); + return ret; + } + + ret = __v4l2_ctrl_handler_setup(ov9734->sd.ctrl_handler); + if (ret) + return ret; + + ret = ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, + 1, OV9734_MODE_STREAMING); + if (ret) + dev_err(&client->dev, "failed to start stream"); + + return ret; +} + +static void ov9734_stop_streaming(struct ov9734 *ov9734) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + + if (ov9734_write_reg(ov9734, OV9734_REG_MODE_SELECT, + 1, OV9734_MODE_STANDBY)) + dev_err(&client->dev, "failed to stop stream"); +} + +static int ov9734_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov9734 *ov9734 = to_ov9734(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = 0; + + if (ov9734->streaming == enable) + return 0; + + mutex_lock(&ov9734->mutex); + if (enable) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + mutex_unlock(&ov9734->mutex); + return ret; + } + + ret = ov9734_start_streaming(ov9734); + if (ret) { + enable = 0; + ov9734_stop_streaming(ov9734); + pm_runtime_put(&client->dev); + } + } else { + ov9734_stop_streaming(ov9734); + pm_runtime_put(&client->dev); + } + + ov9734->streaming = enable; + mutex_unlock(&ov9734->mutex); + + return ret; +} + +static int __maybe_unused ov9734_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9734 *ov9734 = to_ov9734(sd); + + mutex_lock(&ov9734->mutex); + if (ov9734->streaming) + ov9734_stop_streaming(ov9734); + + mutex_unlock(&ov9734->mutex); + + return 0; +} + +static int __maybe_unused ov9734_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9734 *ov9734 = to_ov9734(sd); + int ret = 0; + + mutex_lock(&ov9734->mutex); + if (!ov9734->streaming) + goto exit; + + ret = ov9734_start_streaming(ov9734); + if (ret) { + ov9734->streaming = false; + ov9734_stop_streaming(ov9734); + } + +exit: + mutex_unlock(&ov9734->mutex); + return ret; +} + +static int ov9734_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ov9734 *ov9734 = to_ov9734(sd); + const struct ov9734_mode *mode; + s32 vblank_def, h_blank; + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), width, + height, fmt->format.width, + fmt->format.height); + + mutex_lock(&ov9734->mutex); + ov9734_update_pad_format(mode, &fmt->format); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; + } else { + ov9734->cur_mode = mode; + __v4l2_ctrl_s_ctrl(ov9734->link_freq, mode->link_freq_index); + __v4l2_ctrl_s_ctrl_int64(ov9734->pixel_rate, + to_pixel_rate(mode->link_freq_index)); + + /* Update limits and set FPS to default */ + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(ov9734->vblank, + mode->vts_min - mode->height, + OV9734_VTS_MAX - mode->height, 1, + vblank_def); + __v4l2_ctrl_s_ctrl(ov9734->vblank, vblank_def); + h_blank = to_pixels_per_line(mode->hts, mode->link_freq_index) - + mode->width; + __v4l2_ctrl_modify_range(ov9734->hblank, h_blank, h_blank, 1, + h_blank); + } + + mutex_unlock(&ov9734->mutex); + + return 0; +} + +static int ov9734_get_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ov9734 *ov9734 = to_ov9734(sd); + + mutex_lock(&ov9734->mutex); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + fmt->format = *v4l2_subdev_get_try_format(&ov9734->sd, cfg, + fmt->pad); + else + ov9734_update_pad_format(ov9734->cur_mode, &fmt->format); + + mutex_unlock(&ov9734->mutex); + + return 0; +} + +static int ov9734_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SGRBG10_1X10; + + return 0; +} + +static int ov9734_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int ov9734_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct ov9734 *ov9734 = to_ov9734(sd); + + mutex_lock(&ov9734->mutex); + ov9734_update_pad_format(&supported_modes[0], + v4l2_subdev_get_try_format(sd, fh->pad, 0)); + mutex_unlock(&ov9734->mutex); + + return 0; +} + +static const struct v4l2_subdev_video_ops ov9734_video_ops = { + .s_stream = ov9734_set_stream, +}; + +static const struct v4l2_subdev_pad_ops ov9734_pad_ops = { + .set_fmt = ov9734_set_format, + .get_fmt = ov9734_get_format, + .enum_mbus_code = ov9734_enum_mbus_code, + .enum_frame_size = ov9734_enum_frame_size, +}; + +static const struct v4l2_subdev_ops ov9734_subdev_ops = { + .video = &ov9734_video_ops, + .pad = &ov9734_pad_ops, +}; + +static const struct media_entity_operations ov9734_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_internal_ops ov9734_internal_ops = { + .open = ov9734_open, +}; + +static int ov9734_identify_module(struct ov9734 *ov9734) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov9734->sd); + int ret; + u32 val; + + ret = ov9734_read_reg(ov9734, OV9734_REG_CHIP_ID, 2, &val); + if (ret) + return ret; + + if (val != OV9734_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + OV9734_CHIP_ID, val); + return -ENXIO; + } + + return 0; +} + +static int ov9734_check_hwcfg(struct device *dev) +{ + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + u32 mclk; + int ret; + unsigned int i, j; + + if (!fwnode) + return -ENXIO; + + ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); + if (ret) + return ret; + + if (mclk != OV9734_MCLK) { + dev_err(dev, "external clock %d is not supported", mclk); + return -EINVAL; + } + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return -ENXIO; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return ret; + + if (!bus_cfg.nr_of_link_frequencies) { + dev_err(dev, "no link frequencies defined"); + ret = -EINVAL; + goto check_hwcfg_error; + } + + 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] == + bus_cfg.link_frequencies[j]) + break; + } + + if (j == bus_cfg.nr_of_link_frequencies) { + dev_err(dev, "no link frequency %lld supported", + link_freq_menu_items[i]); + ret = -EINVAL; + goto check_hwcfg_error; + } + } + +check_hwcfg_error: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int ov9734_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov9734 *ov9734 = to_ov9734(sd); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + pm_runtime_disable(&client->dev); + mutex_destroy(&ov9734->mutex); + + return 0; +} + +static int ov9734_probe(struct i2c_client *client) +{ + struct ov9734 *ov9734; + int ret; + + ret = ov9734_check_hwcfg(&client->dev); + if (ret) { + dev_err(&client->dev, "failed to check HW configuration: %d", + ret); + return ret; + } + + ov9734 = devm_kzalloc(&client->dev, sizeof(*ov9734), GFP_KERNEL); + if (!ov9734) + return -ENOMEM; + + v4l2_i2c_subdev_init(&ov9734->sd, client, &ov9734_subdev_ops); + ret = ov9734_identify_module(ov9734); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + return ret; + } + + mutex_init(&ov9734->mutex); + ov9734->cur_mode = &supported_modes[0]; + ret = ov9734_init_controls(ov9734); + if (ret) { + dev_err(&client->dev, "failed to init controls: %d", ret); + goto probe_error_v4l2_ctrl_handler_free; + } + + ov9734->sd.internal_ops = &ov9734_internal_ops; + ov9734->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ov9734->sd.entity.ops = &ov9734_subdev_entity_ops; + ov9734->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov9734->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&ov9734->sd.entity, 1, &ov9734->pad); + if (ret) { + dev_err(&client->dev, "failed to init entity pads: %d", ret); + goto probe_error_v4l2_ctrl_handler_free; + } + + ret = v4l2_async_register_subdev_sensor_common(&ov9734->sd); + if (ret < 0) { + dev_err(&client->dev, "failed to register V4L2 subdev: %d", + ret); + goto probe_error_media_entity_cleanup; + } + + /* + * Device is already turned on by i2c-core with ACPI domain PM. + * Enable runtime PM and turn off the device. + */ + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + pm_runtime_idle(&client->dev); + + return 0; + +probe_error_media_entity_cleanup: + media_entity_cleanup(&ov9734->sd.entity); + +probe_error_v4l2_ctrl_handler_free: + v4l2_ctrl_handler_free(ov9734->sd.ctrl_handler); + mutex_destroy(&ov9734->mutex); + + return ret; +} + +static const struct dev_pm_ops ov9734_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ov9734_suspend, ov9734_resume) +}; + +static const struct acpi_device_id ov9734_acpi_ids[] = { + { "OVTI9734", }, + {} +}; + +MODULE_DEVICE_TABLE(acpi, ov9734_acpi_ids); + +static struct i2c_driver ov9734_i2c_driver = { + .driver = { + .name = "ov9734", + .pm = &ov9734_pm_ops, + .acpi_match_table = ov9734_acpi_ids, + }, + .probe_new = ov9734_probe, + .remove = ov9734_remove, +}; + +module_i2c_driver(ov9734_i2c_driver); + +MODULE_AUTHOR("Qiu, Tianshu "); +MODULE_AUTHOR("Bingbu Cao "); +MODULE_DESCRIPTION("OmniVision OV9734 sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 57226cd8c8bf14e2dfcb3deb4e44bb74ccdafda2 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 21 Oct 2020 23:25:41 +0200 Subject: media: dt-bindings: ov2680: convert bindings to yaml Convert ov2680 sensor bindings documentation to yaml schema, remove the textual bindings document and update MAINTAINERS entry. Signed-off-by: Rui Miguel Silva Reviewed-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/ov2680.txt | 46 ---------- .../devicetree/bindings/media/i2c/ovti,ov2680.yaml | 99 ++++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 100 insertions(+), 47 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/ov2680.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/ov2680.txt b/Documentation/devicetree/bindings/media/i2c/ov2680.txt deleted file mode 100644 index 11e925ed9dad..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/ov2680.txt +++ /dev/null @@ -1,46 +0,0 @@ -* Omnivision OV2680 MIPI CSI-2 sensor - -Required Properties: -- compatible: should be "ovti,ov2680". -- clocks: reference to the xvclk input clock. -- clock-names: should be "xvclk". -- DOVDD-supply: Digital I/O voltage supply. -- DVDD-supply: Digital core voltage supply. -- AVDD-supply: Analog voltage supply. - -Optional Properties: -- reset-gpios: reference to the GPIO connected to the powerdown/reset pin, - if any. This is an active low signal to the OV2680. - -The device node must contain one 'port' child node for its digital output -video port, and this port must have a single endpoint in accordance with - the video interface bindings defined in -Documentation/devicetree/bindings/media/video-interfaces.txt. - -Endpoint node required properties for CSI-2 connection are: -- remote-endpoint: a phandle to the bus receiver's endpoint node. -- clock-lanes: should be set to <0> (clock lane on hardware lane 0). -- data-lanes: should be set to <1> (one CSI-2 lane supported). - -Example: - -&i2c2 { - ov2680: camera-sensor@36 { - compatible = "ovti,ov2680"; - reg = <0x36>; - clocks = <&osc>; - clock-names = "xvclk"; - reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; - DOVDD-supply = <&sw2_reg>; - DVDD-supply = <&sw2_reg>; - AVDD-supply = <®_peri_3p15v>; - - port { - ov2680_to_mipi: endpoint { - remote-endpoint = <&mipi_from_sensor>; - clock-lanes = <0>; - data-lanes = <1>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml new file mode 100644 index 000000000000..43bf749807e1 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,ov2680.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Omnivision OV2680 CMOS Sensor + +maintainers: + - Rui Miguel Silva + +description: |- + The OV2680 color sensor is a low voltage, high performance 1/5 inch UXGA (2 + megapixel) CMOS image sensor that provides a single-chip UXGA (1600 x 1200) + camera. It provides full-frame, sub-sampled, or windowed 10-bit images in + various formats via the control of the Serial Camera Control Bus (SCCB) + interface. The OV2680 has an image array capable of operating at up to 30 + frames per second (fps) in UXGA resolution. + +properties: + compatible: + const: ovti,ov2680 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: xvclk + + reset-gpios: + description: + The phandle and specifier for the GPIO that controls sensor reset. + This corresponds to the hardware pin XSHUTDOWN which is physically + active low. + maxItems: 1 + + dovdd-supply: + description: + Definition of the regulator used as interface power supply. + + avdd-supply: + description: + Definition of the regulator used as analog power supply. + + dvdd-supply: + description: + Definition of the regulator used as digital power supply. + + port: + type: object + description: + A node containing an output port node with an endpoint definition + as documented in + Documentation/devicetree/bindings/media/video-interfaces.txt + +required: + - compatible + - reg + - clocks + - clock-names + - dovdd-supply + - avdd-supply + - dvdd-supply + - reset-gpios + - port + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + ov2680: camera-sensor@36 { + compatible = "ovti,ov2680"; + reg = <0x36>; + clocks = <&osc>; + clock-names = "xvclk"; + reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + + dovdd-supply = <&sw2_reg>; + dvdd-supply = <&sw2_reg>; + avdd-supply = <®_peri_3p15v>; + + port { + ov2680_to_mipi: endpoint { + remote-endpoint = <&mipi_from_sensor>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 20e4afc53bdb..551def33e98f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12889,7 +12889,7 @@ M: Rui Miguel Silva L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git -F: Documentation/devicetree/bindings/media/i2c/ov2680.txt +F: Documentation/devicetree/bindings/media/i2c/ov2680.yaml F: drivers/media/i2c/ov2680.c OMNIVISION OV2685 SENSOR DRIVER -- cgit v1.2.3 From 338de94d220d5c413b029460a59e7a5ebeeb903f Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 21 Oct 2020 23:25:42 +0200 Subject: media: dt-bindings: imx7-csi: convert bindings to yaml Convert imx7-csi bindings documentation to yaml schema, remove the textual bindings document and update MAINTAINERS entry. Signed-off-by: Rui Miguel Silva Reviewed-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/imx7-csi.txt | 42 ------------- .../devicetree/bindings/media/nxp,imx7-csi.yaml | 71 ++++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 72 insertions(+), 43 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/imx7-csi.txt create mode 100644 Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/imx7-csi.txt b/Documentation/devicetree/bindings/media/imx7-csi.txt deleted file mode 100644 index d80ceefa0c00..000000000000 --- a/Documentation/devicetree/bindings/media/imx7-csi.txt +++ /dev/null @@ -1,42 +0,0 @@ -Freescale i.MX7 CMOS Sensor Interface -===================================== - -csi node --------- - -This is device node for the CMOS Sensor Interface (CSI) which enables the chip -to connect directly to external CMOS image sensors. - -Required properties: - -- compatible : "fsl,imx7-csi" or "fsl,imx6ul-csi"; -- reg : base address and length of the register set for the device; -- interrupts : should contain CSI interrupt; -- clocks : list of clock specifiers, see - Documentation/devicetree/bindings/clock/clock-bindings.txt for details; -- clock-names : must contain "mclk"; - -The device node shall contain one 'port' child node with one child 'endpoint' -node, according to the bindings defined in: -Documentation/devicetree/bindings/media/video-interfaces.txt. - -In the following example a remote endpoint is a video multiplexer. - -example: - - csi: csi@30710000 { - #address-cells = <1>; - #size-cells = <0>; - - compatible = "fsl,imx7-csi"; - reg = <0x30710000 0x10000>; - interrupts = ; - clocks = <&clks IMX7D_CSI_MCLK_ROOT_CLK>; - clock-names = "mclk"; - - port { - csi_from_csi_mux: endpoint { - remote-endpoint = <&csi_mux_to_csi>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml new file mode 100644 index 000000000000..4e81a47e60ac --- /dev/null +++ b/Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/nxp,imx7-csi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: i.MX7 CMOS Sensor Interface + +maintainers: + - Rui Miguel Silva + +description: | + This is device node for the CMOS Sensor Interface (CSI) which enables the + chip to connect directly to external CMOS image sensors. + +properties: + compatible: + enum: + - fsl,imx7-csi + - fsl,imx6ul-csi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: mclk + + port: + type: object + description: + A node containing input port nodes with endpoint definitions as documented + in Documentation/devicetree/bindings/media/video-interfaces.txt + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - port + +additionalProperties: false + +examples: + - | + #include + #include + #include + + csi: csi@30710000 { + compatible = "fsl,imx7-csi"; + reg = <0x30710000 0x10000>; + interrupts = ; + clocks = <&clks IMX7D_CSI_MCLK_ROOT_CLK>; + clock-names = "mclk"; + + port { + csi_from_csi_mux: endpoint { + remote-endpoint = <&csi_mux_to_csi>; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 551def33e98f..221385eedc9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10849,8 +10849,8 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/imx7.rst -F: Documentation/devicetree/bindings/media/imx7-csi.txt F: Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt +F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml F: drivers/staging/media/imx/imx7-media-csi.c F: drivers/staging/media/imx/imx7-mipi-csis.c -- cgit v1.2.3 From 8b7c7828a311a18932ca63228ff3745a86cb880a Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 21 Oct 2020 23:25:43 +0200 Subject: media: dt-bindings: imx7-mipi-csi2: convert bindings to yaml Convert imx7 mipi csi2 bindings documentation to yaml schema, remove the textual document and update MAINTAINERS entry. Signed-off-by: Rui Miguel Silva Reviewed-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/imx7-mipi-csi2.txt | 90 ----------- .../bindings/media/nxp,imx7-mipi-csi2.yaml | 173 +++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 174 insertions(+), 91 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt create mode 100644 Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt b/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt deleted file mode 100644 index 71fd74ed3ec8..000000000000 --- a/Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt +++ /dev/null @@ -1,90 +0,0 @@ -Freescale i.MX7 Mipi CSI2 -========================= - -mipi_csi2 node --------------- - -This is the device node for the MIPI CSI-2 receiver core in i.MX7 SoC. It is -compatible with previous version of Samsung D-phy. - -Required properties: - -- compatible : "fsl,imx7-mipi-csi2"; -- reg : base address and length of the register set for the device; -- interrupts : should contain MIPI CSIS interrupt; -- clocks : list of clock specifiers, see - Documentation/devicetree/bindings/clock/clock-bindings.txt for details; -- clock-names : must contain "pclk", "wrap" and "phy" entries, matching - entries in the clock property; -- power-domains : a phandle to the power domain, see - Documentation/devicetree/bindings/power/power_domain.txt for details. -- reset-names : should include following entry "mrst"; -- resets : a list of phandle, should contain reset entry of - reset-names; -- phy-supply : from the generic phy bindings, a phandle to a regulator that - provides power to MIPI CSIS core; - -Optional properties: - -- clock-frequency : The IP's main (system bus) clock frequency in Hz, default - value when this property is not specified is 166 MHz; -- fsl,csis-hs-settle : differential receiver (HS-RX) settle time; - -The device node should contain two 'port' child nodes with one child 'endpoint' -node, according to the bindings defined in: - Documentation/devicetree/bindings/ media/video-interfaces.txt. - The following are properties specific to those nodes. - -port node ---------- - -- reg : (required) can take the values 0 or 1, where 0 shall be - related to the sink port and port 1 shall be the source - one; - -endpoint node -------------- - -- data-lanes : (required) an array specifying active physical MIPI-CSI2 - data input lanes and their mapping to logical lanes; this - shall only be applied to port 0 (sink port), the array's - content is unused only its length is meaningful, - in this case the maximum length supported is 2; - -example: - - mipi_csi: mipi-csi@30750000 { - #address-cells = <1>; - #size-cells = <0>; - - compatible = "fsl,imx7-mipi-csi2"; - reg = <0x30750000 0x10000>; - interrupts = ; - clocks = <&clks IMX7D_IPG_ROOT_CLK>, - <&clks IMX7D_MIPI_CSI_ROOT_CLK>, - <&clks IMX7D_MIPI_DPHY_ROOT_CLK>; - clock-names = "pclk", "wrap", "phy"; - clock-frequency = <166000000>; - power-domains = <&pgc_mipi_phy>; - phy-supply = <®_1p0d>; - resets = <&src IMX7_RESET_MIPI_PHY_MRST>; - reset-names = "mrst"; - fsl,csis-hs-settle = <3>; - - port@0 { - reg = <0>; - - mipi_from_sensor: endpoint { - remote-endpoint = <&ov2680_to_mipi>; - data-lanes = <1>; - }; - }; - - port@1 { - reg = <1>; - - mipi_vc0_to_csi_mux: endpoint { - remote-endpoint = <&csi_mux_from_mipi_vc0>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml new file mode 100644 index 000000000000..0668332959e7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml @@ -0,0 +1,173 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/nxp,imx7-mipi-csi2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX7 Mipi CSI2 + +maintainers: + - Rui Miguel Silva + +description: | + This is the device node for the MIPI CSI-2 receiver core in i.MX7 soc. It is + compatible with previous version of samsung d-phy. + +properties: + compatible: + const: fsl,imx7-mipi-csi2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 3 + maxItems: 3 + + clock-names: + items: + - const: pclk + - const: wrap + - const: phy + + power-domains: + maxItems: 1 + + phy-supply: + description: + Phandle to a regulator that provides power to the PHY. This + regulator will be managed during the PHY power on/off sequence. + + resets: + maxItems: 1 + + reset-names: + const: mrst + + clock-frequency: + description: + The IP main (system bus) clock frequency in Hertz + default: 166000000 + + fsl,csis-hs-settle: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Differential receiver (HS-RX) settle time + + ports: + type: object + description: + A node containing input and output port nodes with endpoint definitions + as documented in + Documentation/devicetree/bindings/media/video-interfaces.txt + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + port@0: + type: object + description: + Input port node, single endpoint describing the CSI-2 transmitter. + + properties: + reg: + const: 0 + + endpoint: + type: object + + properties: + data-lanes: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: See ../video-interfaces.txt + oneOf: + - items: + - const: 1 + - items: + - const: 1 + - const: 2 + + remote-endpoint: true + + required: + - data-lanes + - remote-endpoint + + additionalProperties: false + + additionalProperties: false + + port@1: + type: object + description: + Output port node + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - power-domains + - phy-supply + - resets + - reset-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + + mipi_csi: mipi-csi@30750000 { + compatible = "fsl,imx7-mipi-csi2"; + reg = <0x30750000 0x10000>; + interrupts = ; + + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_MIPI_CSI_ROOT_CLK>, + <&clks IMX7D_MIPI_DPHY_ROOT_CLK>; + clock-names = "pclk", "wrap", "phy"; + clock-frequency = <166000000>; + + power-domains = <&pgc_mipi_phy>; + phy-supply = <®_1p0d>; + resets = <&src IMX7_RESET_MIPI_PHY_MRST>; + reset-names = "mrst"; + fsl,csis-hs-settle = <3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + mipi_from_sensor: endpoint { + remote-endpoint = <&ov2680_to_mipi>; + data-lanes = <1>; + }; + }; + + port@1 { + reg = <1>; + + mipi_vc0_to_csi_mux: endpoint { + remote-endpoint = <&csi_mux_from_mipi_vc0>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 221385eedc9d..e3a828249c8c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10849,8 +10849,8 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/imx7.rst -F: Documentation/devicetree/bindings/media/imx7-mipi-csi2.txt F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml +F: Documentation/devicetree/bindings/media/nxp,imx7-mipi-csi2.yaml F: drivers/staging/media/imx/imx7-media-csi.c F: drivers/staging/media/imx/imx7-mipi-csis.c -- cgit v1.2.3 From 1ec0b899c2b776c0c2dd03044b171a52b5211570 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 3 Feb 2020 10:39:24 +0100 Subject: media: ccs: Add the generator for CCS register definitions and limits Add register definitions of the MIPI CCS 1.1 standard. The CCS driver makes extended use of device's capability registers that are dependent on CCS version. This involves having an in-memory data structure for limit and capability information, creating that data structure and accessing it. The register definitions as well as the definitions of this data structure are generated from a text file using a Perl script. Add the generator script to make it easy to update the generated files. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../driver-api/media/drivers/ccs/ccs-regs.txt | 1041 ++++++++++++++++++++ .../driver-api/media/drivers/ccs/mk-ccs-regs | 433 ++++++++ MAINTAINERS | 1 + 3 files changed, 1475 insertions(+) create mode 100644 Documentation/driver-api/media/drivers/ccs/ccs-regs.txt create mode 100755 Documentation/driver-api/media/drivers/ccs/mk-ccs-regs (limited to 'MAINTAINERS') diff --git a/Documentation/driver-api/media/drivers/ccs/ccs-regs.txt b/Documentation/driver-api/media/drivers/ccs/ccs-regs.txt new file mode 100644 index 000000000000..93f0131aa304 --- /dev/null +++ b/Documentation/driver-api/media/drivers/ccs/ccs-regs.txt @@ -0,0 +1,1041 @@ +# Copyright (C) 2019--2020 Intel Corporation +# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause + +# register rflags +# - f field LSB MSB rflags +# - e enum value # after a field +# - e enum value [LSB MSB] +# - b bool bit +# - l arg name min max elsize [discontig...] +# +# rflags +# 8, 16, 32 register bits (default is 8) +# v1.1 defined in version 1.1 +# f formula +# float_ireal iReal or IEEE 754; 32 bits +# ireal unsigned iReal + +# general status registers +module_model_id 0x0000 16 +module_revision_number_major 0x0002 8 +frame_count 0x0005 8 +pixel_order 0x0006 8 +- e GRBG 0 +- e RGGB 1 +- e BGGR 2 +- e GBRG 3 +MIPI_CCS_version 0x0007 8 +- e v1_0 0x10 +- e v1_1 0x11 +- f major 4 7 +- f minor 0 3 +data_pedestal 0x0008 16 +module_manufacturer_id 0x000e 16 +module_revision_number_minor 0x0010 8 +module_date_year 0x0012 8 +module_date_month 0x0013 8 +module_date_day 0x0014 8 +module_date_phase 0x0015 8 +- f 0 2 +- e ts 0 +- e es 1 +- e cs 2 +- e mp 3 +sensor_model_id 0x0016 16 +sensor_revision_number 0x0018 8 +sensor_firmware_version 0x001a 8 +serial_number 0x001c 32 +sensor_manufacturer_id 0x0020 16 +sensor_revision_number_16 0x0022 16 + +# frame format description registers +frame_format_model_type 0x0040 8 +- e 2-byte 1 +- e 4-byte 2 +frame_format_model_subtype 0x0041 8 +- f rows 0 3 +- f columns 4 7 +frame_format_descriptor(n) 0x0042 16 f +- l n 0 14 2 +- f pixels 0 11 +- f pcode 12 15 +- e embedded 1 +- e dummy_pixel 2 +- e black_pixel 3 +- e dark_pixel 4 +- e visible_pixel 5 +- e manuf_specific_0 8 +- e manuf_specific_1 9 +- e manuf_specific_2 10 +- e manuf_specific_3 11 +- e manuf_specific_4 12 +- e manuf_specific_5 13 +- e manuf_specific_6 14 +frame_format_descriptor_4(n) 0x0060 32 f +- l n 0 7 4 +- f pixels 0 15 +- f pcode 28 31 +- e embedded 1 +- e dummy_pixel 2 +- e black_pixel 3 +- e dark_pixel 4 +- e visible_pixel 5 +- e manuf_specific_0 8 +- e manuf_specific_1 9 +- e manuf_specific_2 10 +- e manuf_specific_3 11 +- e manuf_specific_4 12 +- e manuf_specific_5 13 +- e manuf_specific_6 14 + +# analog gain description registers +analog_gain_capability 0x0080 16 +- e global 0 +- e alternate_global 2 +analog_gain_code_min 0x0084 16 +analog_gain_code_max 0x0086 16 +analog_gain_code_step 0x0088 16 +analog_gain_type 0x008a 16 +analog_gain_m0 0x008c 16 +analog_gain_c0 0x008e 16 +analog_gain_m1 0x0090 16 +analog_gain_c1 0x0092 16 +analog_linear_gain_min 0x0094 16 v1.1 +analog_linear_gain_max 0x0096 16 v1.1 +analog_linear_gain_step_size 0x0098 16 v1.1 +analog_exponential_gain_min 0x009a 16 v1.1 +analog_exponential_gain_max 0x009c 16 v1.1 +analog_exponential_gain_step_size 0x009e 16 v1.1 + +# data format description registers +data_format_model_type 0x00c0 8 +- e normal 1 +- e extended 2 +data_format_model_subtype 0x00c1 8 +- f rows 0 3 +- f columns 4 7 +data_format_descriptor(n) 0x00c2 16 f +- l n 0 15 2 +- f compressed 0 7 +- f uncompressed 8 15 + +# general set-up registers +mode_select 0x0100 8 +- e software_standby 0 +- e streaming 1 +image_orientation 0x0101 8 +- b horizontal_mirror 0 +- b vertical_flip 1 +software_reset 0x0103 8 +- e off 0 +- e on 1 +grouped_parameter_hold 0x0104 8 +mask_corrupted_frames 0x0105 8 +- e allow 0 +- e mask 1 +fast_standby_ctrl 0x0106 8 +- e complete_frames 0 +- e frame_truncation 1 +CCI_address_ctrl 0x0107 8 +2nd_CCI_if_ctrl 0x0108 8 +- b enable 0 +- b ack 1 +2nd_CCI_address_ctrl 0x0109 8 +CSI_channel_identifier 0x0110 8 +CSI_signaling_mode 0x0111 8 +- e csi_2_dphy 2 +- e csi_2_cphy 3 +CSI_data_format 0x0112 16 +CSI_lane_mode 0x0114 8 +DPCM_Frame_DT 0x011d 8 +Bottom_embedded_data_DT 0x011e 8 +Bottom_embedded_data_VC 0x011f 8 + +gain_mode 0x0120 8 +- e global 0 +- e alternate 1 +ADC_bit_depth 0x0121 8 +emb_data_ctrl 0x0122 v1.1 +- b raw8_packing_for_raw16 0 +- b raw10_packing_for_raw20 1 +- b raw12_packing_for_raw24 2 + +GPIO_TRIG_mode 0x0130 8 +extclk_frequency_mhz 0x0136 16 ireal +temp_sensor_ctrl 0x0138 8 +- b enable 0 +temp_sensor_mode 0x0139 8 +temp_sensor_output 0x013a 8 + +# integration time registers +fine_integration_time 0x0200 16 +coarse_integration_time 0x0202 16 + +# analog gain registers +analog_gain_code_global 0x0204 16 +analog_linear_gain_global 0x0206 16 v1.1 +analog_exponential_gain_global 0x0208 16 v1.1 + +# digital gain registers +digital_gain_global 0x020e 16 + +# hdr control registers +Short_analog_gain_global 0x0216 16 +Short_digital_gain_global 0x0218 16 + +HDR_mode 0x0220 8 +- b enabled 0 +- b separate_analog_gain 1 +- b upscaling 2 +- b reset_sync 3 +- b timing_mode 4 +- b exposure_ctrl_direct 5 +- b separate_digital_gain 6 +HDR_resolution_reduction 0x0221 8 +- f row 0 3 +- f column 4 7 +Exposure_ratio 0x0222 8 +HDR_internal_bit_depth 0x0223 8 +Direct_short_integration_time 0x0224 16 +Short_analog_linear_gain_global 0x0226 16 v1.1 +Short_analog_exponential_gain_global 0x0228 16 v1.1 + +# clock set-up registers +vt_pix_clk_div 0x0300 16 +vt_sys_clk_div 0x0302 16 +pre_pll_clk_div 0x0304 16 +#vt_pre_pll_clk_div 0x0304 16 +pll_multiplier 0x0306 16 +#vt_pll_multiplier 0x0306 16 +op_pix_clk_div 0x0308 16 +op_sys_clk_div 0x030a 16 +op_pre_pll_clk_div 0x030c 16 +op_pll_multiplier 0x031e 16 +pll_mode 0x0310 8 +- f 0 0 +- e single 0 +- e dual 1 +op_pix_clk_div_rev 0x0312 16 v1.1 +op_sys_clk_div_rev 0x0314 16 v1.1 + +# frame timing registers +frame_length_lines 0x0340 16 +line_length_pck 0x0342 16 + +# image size registers +x_addr_start 0x0344 16 +y_addr_start 0x0346 16 +x_addr_end 0x0348 16 +y_addr_end 0x034a 16 +x_output_size 0x034c 16 +y_output_size 0x034e 16 + +# timing mode registers +Frame_length_ctrl 0x0350 8 +- b automatic 0 +Timing_mode_ctrl 0x0352 8 +- b manual_readout 0 +- b delayed_exposure 1 +Start_readout_rs 0x0353 8 +- b manual_readout_start 0 +Frame_margin 0x0354 16 + +# sub-sampling registers +x_even_inc 0x0380 16 +x_odd_inc 0x0382 16 +y_even_inc 0x0384 16 +y_odd_inc 0x0386 16 + +# monochrome readout registers +monochrome_en 0x0390 v1.1 +- e enabled 0 + +# image scaling registers +Scaling_mode 0x0400 16 +- e no_scaling 0 +- e horizontal 1 +scale_m 0x0404 16 +scale_n 0x0406 16 +digital_crop_x_offset 0x0408 16 +digital_crop_y_offset 0x040a 16 +digital_crop_image_width 0x040c 16 +digital_crop_image_height 0x040e 16 + +# image compression registers +compression_mode 0x0500 16 +- e none 0 +- e dpcm_pcm_simple 1 + +# test pattern registers +test_pattern_mode 0x0600 16 +- e none 0 +- e solid_color 1 +- e color_bars 2 +- e fade_to_grey 3 +- e pn9 4 +- e color_tile 5 +test_data_red 0x0602 16 +test_data_greenR 0x0604 16 +test_data_blue 0x0606 16 +test_data_greenB 0x0608 16 +value_step_size_smooth 0x060a 8 +value_step_size_quantised 0x060b 8 + +# phy configuration registers +tclk_post 0x0800 8 +ths_prepare 0x0801 8 +ths_zero_min 0x0802 8 +ths_trail 0x0803 8 +tclk_trail_min 0x0804 8 +tclk_prepare 0x0805 8 +tclk_zero 0x0806 8 +tlpx 0x0807 8 +phy_ctrl 0x0808 8 +- e auto 0 +- e UI 1 +- e manual 2 +tclk_post_ex 0x080a 16 +ths_prepare_ex 0x080c 16 +ths_zero_min_ex 0x080e 16 +ths_trail_ex 0x0810 16 +tclk_trail_min_ex 0x0812 16 +tclk_prepare_ex 0x0814 16 +tclk_zero_ex 0x0816 16 +tlpx_ex 0x0818 16 + +# link rate register +requested_link_rate 0x0820 32 u16.16 + +# equalization control registers +DPHY_equalization_mode 0x0824 8 v1.1 +- b eq2 0 +PHY_equalization_ctrl 0x0825 8 v1.1 +- b enable 0 + +# d-phy preamble control registers +DPHY_preamble_ctrl 0x0826 8 v1.1 +- b enable 0 +DPHY_preamble_length 0x0826 8 v1.1 + +# d-phy spread spectrum control registers +PHY_SSC_ctrl 0x0828 8 v1.1 +- b enable 0 + +# manual lp control register +manual_LP_ctrl 0x0829 8 v1.1 +- b enable 0 + +# additional phy configuration registers +twakeup 0x082a v1.1 +tinit 0x082b v1.1 +ths_exit 0x082c v1.1 +ths_exit_ex 0x082e 16 v1.1 + +# phy calibration configuration registers +PHY_periodic_calibration_ctrl 0x0830 8 +- b frame_blanking 0 +PHY_periodic_calibration_interval 0x0831 8 +PHY_init_calibration_ctrl 0x0832 8 +- b stream_start 0 +DPHY_calibration_mode 0x0833 8 v1.1 +- b also_alternate 0 +CPHY_calibration_mode 0x0834 8 v1.1 +- e format_1 0 +- e format_2 1 +- e format_3 2 +t3_calpreamble_length 0x0835 8 v1.1 +t3_calpreamble_length_per 0x0836 8 v1.1 +t3_calaltseq_length 0x0837 8 v1.1 +t3_calaltseq_length_per 0x0838 8 v1.1 +FM2_init_seed 0x083a 16 v1.1 +t3_caludefseq_length 0x083c 16 v1.1 +t3_caludefseq_length_per 0x083e 16 v1.1 + +# c-phy manual control registers +TGR_Preamble_Length 0x0841 8 +- b preamable_prog_seq 7 +- f begin_preamble_length 0 5 +TGR_Post_Length 0x0842 8 +- f post_length 0 4 +TGR_Preamble_Prog_Sequence(n2) 0x0843 +- l n2 0 6 1 +- f symbol_n_1 3 5 +- f symbol_n 0 2 +t3_prepare 0x084e 16 +t3_lpx 0x0850 16 + +# alps control register +ALPS_ctrl 0x085a 8 +- b lvlp_dphy 0 +- b lvlp_cphy 1 +- b alp_cphy 2 + +# lrte control registers +TX_REG_CSI_EPD_EN_SSP_cphy 0x0860 16 +TX_REG_CSI_EPD_OP_SLP_cphy 0x0862 16 +TX_REG_CSI_EPD_EN_SSP_dphy 0x0864 16 +TX_REG_CSI_EPD_OP_SLP_dphy 0x0866 16 +TX_REG_CSI_EPD_MISC_OPTION_cphy 0x0868 v1.1 +TX_REG_CSI_EPD_MISC_OPTION_dphy 0x0869 v1.1 + +# scrambling control registers +Scrambling_ctrl 0x0870 +- b enabled 0 +- f 2 3 +- e 1_seed_cphy 0 +- e 4_seed_cphy 3 +lane_seed_value(seed, lane) 0x0872 16 +- l seed 0 3 0x10 +- l lane 0 7 0x2 + +# usl control registers +TX_USL_REV_ENTRY 0x08c0 16 v1.1 +TX_USL_REV_Clock_Counter 0x08c2 16 v1.1 +TX_USL_REV_LP_Counter 0x08c4 16 v1.1 +TX_USL_REV_Frame_Counter 0x08c6 16 v1.1 +TX_USL_REV_Chronological_Timer 0x08c8 16 v1.1 +TX_USL_FWD_ENTRY 0x08ca 16 v1.1 +TX_USL_GPIO 0x08cc 16 v1.1 +TX_USL_Operation 0x08ce 16 v1.1 +- b reset 0 +TX_USL_ALP_ctrl 0x08d0 16 v1.1 +- b clock_pause 0 +TX_USL_APP_BTA_ACK_TIMEOUT 0x08d2 16 v1.1 +TX_USL_SNS_BTA_ACK_TIMEOUT 0x08d2 16 v1.1 +USL_Clock_Mode_d_ctrl 0x08d2 v1.1 +- b cont_clock_standby 0 +- b cont_clock_vblank 1 +- b cont_clock_hblank 2 + +# binning configuration registers +binning_mode 0x0900 8 +binning_type 0x0901 8 +binning_weighting 0x0902 8 + +# data transfer interface registers +data_transfer_if_1_ctrl 0x0a00 8 +- b enable 0 +- b write 1 +- b clear_error 2 +data_transfer_if_1_status 0x0a01 8 +- b read_if_ready 0 +- b write_if_ready 1 +- b data_corrupted 2 +- b improper_if_usage 3 +data_transfer_if_1_page_select 0x0a02 8 +data_transfer_if_1_data(p) 0x0a04 8 f +- l p 0 63 1 + +# image processing and sensor correction configuration registers +shading_correction_en 0x0b00 8 +- b enable 0 +luminance_correction_level 0x0b01 8 +green_imbalance_filter_en 0x0b02 8 +- b enable 0 +mapped_defect_correct_en 0x0b05 8 +- b enable 0 +single_defect_correct_en 0x0b06 8 +- b enable 0 +dynamic_couplet_correct_en 0x0b08 8 +- b enable 0 +combined_defect_correct_en 0x0b0a 8 +- b enable 0 +module_specific_correction_en 0x0b0c 8 +- b enable 0 +dynamic_triplet_defect_correct_en 0x0b13 8 +- b enable 0 +NF_ctrl 0x0b15 8 +- b luma 0 +- b chroma 1 +- b combined 2 + +# optical black pixel readout registers +OB_readout_control 0x0b30 8 +- b enable 0 +- b interleaving 1 +OB_virtual_channel 0x0b31 8 +OB_DT 0x0b32 8 +OB_data_format 0x0b33 8 + +# color temperature feedback registers +color_temperature 0x0b8c 16 +absolute_gain_greenr 0x0b8e 16 +absolute_gain_red 0x0b90 16 +absolute_gain_blue 0x0b92 16 +absolute_gain_greenb 0x0b94 16 + +# cfa conversion registers +CFA_conversion_ctrl 0x0ba0 v1.1 +- b bayer_conversion_enable 0 + +# flash strobe and sa strobe control registers +flash_strobe_adjustment 0x0c12 8 +flash_strobe_start_point 0x0c14 16 +tflash_strobe_delay_rs_ctrl 0x0c16 16 +tflash_strobe_width_high_rs_ctrl 0x0c18 16 +flash_mode_rs 0x0c1a 8 +- b continuous 0 +- b truncate 1 +- b async 3 +flash_trigger_rs 0x0c1b 8 +flash_status 0x0c1c 8 +- b retimed 0 +sa_strobe_mode 0x0c1d 8 +- b continuous 0 +- b truncate 1 +- b async 3 +- b adjust_edge 4 +sa_strobe_start_point 0x0c1e 16 +tsa_strobe_delay_ctrl 0x0c20 16 +tsa_strobe_width_ctrl 0x0c22 16 +sa_strobe_trigger 0x0c24 8 +sa_strobe_status 0x0c25 8 +- b retimed 0 +tSA_strobe_re_delay_ctrl 0x0c30 16 +tSA_strobe_fe_delay_ctrl 0x0c32 16 + +# pdaf control registers +PDAF_ctrl 0x0d00 16 +- b enable 0 +- b processed 1 +- b interleaved 2 +- b visible_pdaf_correction 3 +PDAF_VC 0x0d02 8 +PDAF_DT 0x0d03 8 +pd_x_addr_start 0x0d04 16 +pd_y_addr_start 0x0d06 16 +pd_x_addr_end 0x0d08 16 +pd_y_addr_end 0x0d0a 16 + +# bracketing interface configuration registers +bracketing_LUT_ctrl 0x0e00 8 +bracketing_LUT_mode 0x0e01 8 +- b continue_streaming 0 +- b loop_mode 1 +bracketing_LUT_entry_ctrl 0x0e02 8 +bracketing_LUT_frame(n) 0x0e10 v1.1 f +- l n 0 0xef 1 + +# integration time and gain parameter limit registers +integration_time_capability 0x1000 16 +- b fine 0 +coarse_integration_time_min 0x1004 16 +coarse_integration_time_max_margin 0x1006 16 +fine_integration_time_min 0x1008 16 +fine_integration_time_max_margin 0x100a 16 + +# digital gain parameter limit registers +digital_gain_capability 0x1081 +- e none 0 +- e global 2 +digital_gain_min 0x1084 16 +digital_gain_max 0x1086 16 +digital_gain_step_size 0x1088 16 + +# data pedestal capability registers +Pedestal_capability 0x10e0 8 v1.1 + +# adc capability registers +ADC_capability 0x10f0 8 +- b bit_depth_ctrl 0 +ADC_bit_depth_capability 0x10f4 32 v1.1 + +# video timing parameter limit registers +min_ext_clk_freq_mhz 0x1100 32 float_ireal +max_ext_clk_freq_mhz 0x1104 32 float_ireal +min_pre_pll_clk_div 0x1108 16 +# min_vt_pre_pll_clk_div 0x1108 16 +max_pre_pll_clk_div 0x110a 16 +# max_vt_pre_pll_clk_div 0x110a 16 +min_pll_ip_clk_freq_mhz 0x110c 32 float_ireal +# min_vt_pll_ip_clk_freq_mhz 0x110c 32 float_ireal +max_pll_ip_clk_freq_mhz 0x1110 32 float_ireal +# max_vt_pll_ip_clk_freq_mhz 0x1110 32 float_ireal +min_pll_multiplier 0x1114 16 +# min_vt_pll_multiplier 0x1114 16 +max_pll_multiplier 0x1116 16 +# max_vt_pll_multiplier 0x1116 16 +min_pll_op_clk_freq_mhz 0x1118 32 float_ireal +max_pll_op_clk_freq_mhz 0x111c 32 float_ireal + +# video timing set-up capability registers +min_vt_sys_clk_div 0x1120 16 +max_vt_sys_clk_div 0x1122 16 +min_vt_sys_clk_freq_mhz 0x1124 32 float_ireal +max_vt_sys_clk_freq_mhz 0x1128 32 float_ireal +min_vt_pix_clk_freq_mhz 0x112c 32 float_ireal +max_vt_pix_clk_freq_mhz 0x1130 32 float_ireal +min_vt_pix_clk_div 0x1134 16 +max_vt_pix_clk_div 0x1136 16 +clock_calculation 0x1138 +- b lane_speed 0 +- b link_decoupled 1 +- b dual_pll_op_sys_ddr 2 +- b dual_pll_op_pix_ddr 3 +num_of_vt_lanes 0x1139 +num_of_op_lanes 0x113a +op_bits_per_lane 0x113b 8 v1.1 + +# frame timing parameter limits +min_frame_length_lines 0x1140 16 +max_frame_length_lines 0x1142 16 +min_line_length_pck 0x1144 16 +max_line_length_pck 0x1146 16 +min_line_blanking_pck 0x1148 16 +min_frame_blanking_lines 0x114a 16 +min_line_length_pck_step_size 0x114c +timing_mode_capability 0x114d +- b auto_frame_length 0 +- b rolling_shutter_manual_readout 2 +- b delayed_exposure_start 3 +- b manual_exposure_embedded_data 4 +frame_margin_max_value 0x114e 16 +frame_margin_min_value 0x1150 +gain_delay_type 0x1151 +- e fixed 0 +- e variable 1 + +# output clock set-up capability registers +min_op_sys_clk_div 0x1160 16 +max_op_sys_clk_div 0x1162 16 +min_op_sys_clk_freq_mhz 0x1164 32 float_ireal +max_op_sys_clk_freq_mhz 0x1168 32 float_ireal +min_op_pix_clk_div 0x116c 16 +max_op_pix_clk_div 0x116e 16 +min_op_pix_clk_freq_mhz 0x1170 32 float_ireal +max_op_pix_clk_freq_mhz 0x1174 32 float_ireal + +# image size parameter limit registers +x_addr_min 0x1180 16 +y_addr_min 0x1182 16 +x_addr_max 0x1184 16 +y_addr_max 0x1186 16 +min_x_output_size 0x1188 16 +min_y_output_size 0x118a 16 +max_x_output_size 0x118c 16 +max_y_output_size 0x118e 16 + +x_addr_start_div_constant 0x1190 v1.1 +y_addr_start_div_constant 0x1191 v1.1 +x_addr_end_div_constant 0x1192 v1.1 +y_addr_end_div_constant 0x1193 v1.1 +x_size_div 0x1194 v1.1 +y_size_div 0x1195 v1.1 +x_output_div 0x1196 v1.1 +y_output_div 0x1197 v1.1 +non_flexible_resolution_support 0x1198 v1.1 +- b new_pix_addr 0 +- b new_output_res 1 +- b output_crop_no_pad 2 +- b output_size_lane_dep 3 + +min_op_pre_pll_clk_div 0x11a0 16 +max_op_pre_pll_clk_div 0x11a2 16 +min_op_pll_ip_clk_freq_mhz 0x11a4 32 float_ireal +max_op_pll_ip_clk_freq_mhz 0x11a8 32 float_ireal +min_op_pll_multiplier 0x11ac 16 +max_op_pll_multiplier 0x11ae 16 +min_op_pll_op_clk_freq_mhz 0x11b0 32 float_ireal +max_op_pll_op_clk_freq_mhz 0x11b4 32 float_ireal +clock_tree_pll_capability 0x11b8 8 +- b dual_pll 0 +- b single_pll 1 +- b ext_divider 2 +- b flexible_op_pix_clk_div 3 +clock_capa_type_capability 0x11b9 v1.1 +- b ireal 0 + +# sub-sampling parameters limit registers +min_even_inc 0x11c0 16 +min_odd_inc 0x11c2 16 +max_even_inc 0x11c4 16 +max_odd_inc 0x11c6 16 +aux_subsamp_capability 0x11c8 v1.1 +- b factor_power_of_2 1 +aux_subsamp_mono_capability 0x11c9 v1.1 +- b factor_power_of_2 1 +monochrome_capability 0x11ca v1.1 +- e inc_odd 0 +- e inc_even 1 +pixel_readout_capability 0x11cb v1.1 +- e bayer 0 +- e monochrome 1 +- e bayer_and_mono 2 +min_even_inc_mono 0x11cc 16 v1.1 +max_even_inc_mono 0x11ce 16 v1.1 +min_odd_inc_mono 0x11d0 16 v1.1 +max_odd_inc_mono 0x11d2 16 v1.1 +min_even_inc_bc2 0x11d4 16 v1.1 +max_even_inc_bc2 0x11d6 16 v1.1 +min_odd_inc_bc2 0x11d8 16 v1.1 +max_odd_inc_bc2 0x11da 16 v1.1 +min_even_inc_mono_bc2 0x11dc 16 v1.1 +max_even_inc_mono_bc2 0x11de 16 v1.1 +min_odd_inc_mono_bc2 0x11f0 16 v1.1 +max_odd_inc_mono_bc2 0x11f2 16 v1.1 + +# image scaling limit parameters +scaling_capability 0x1200 16 +- e none 0 +- e horizontal 1 +- e reserved 2 +scaler_m_min 0x1204 16 +scaler_m_max 0x1206 16 +scaler_n_min 0x1208 16 +scaler_n_max 0x120a 16 +digital_crop_capability 0x120e +- e none 0 +- e input_crop 1 + +# hdr limit registers +hdr_capability_1 0x1210 +- b 2x2_binning 0 +- b combined_analog_gain 1 +- b separate_analog_gain 2 +- b upscaling 3 +- b reset_sync 4 +- b direct_short_exp_timing 5 +- b direct_short_exp_synthesis 6 +min_hdr_bit_depth 0x1211 +hdr_resolution_sub_types 0x1212 +hdr_resolution_sub_type(n) 0x1213 +- l n 0 1 1 +- f row 0 3 +- f column 4 7 +hdr_capability_2 0x121b +- b combined_digital_gain 0 +- b separate_digital_gain 1 +- b timing_mode 3 +- b synthesis_mode 4 +max_hdr_bit_depth 0x121c + +# usl capability register +usl_support_capability 0x1230 v1.1 +- b clock_tree 0 +- b rev_clock_tree 1 +- b rev_clock_calc 2 +usl_clock_mode_d_capability 0x1231 v1.1 +- b cont_clock_standby 0 +- b cont_clock_vblank 1 +- b cont_clock_hblank 2 +- b noncont_clock_standby 3 +- b noncont_clock_vblank 4 +- b noncont_clock_hblank 5 +min_op_sys_clk_div_rev 0x1234 v1.1 +max_op_sys_clk_div_rev 0x1236 v1.1 +min_op_pix_clk_div_rev 0x1238 v1.1 +max_op_pix_clk_div_rev 0x123a v1.1 +min_op_sys_clk_freq_rev_mhz 0x123c 32 v1.1 float_ireal +max_op_sys_clk_freq_rev_mhz 0x1240 32 v1.1 float_ireal +min_op_pix_clk_freq_rev_mhz 0x1244 32 v1.1 float_ireal +max_op_pix_clk_freq_rev_mhz 0x1248 32 v1.1 float_ireal +max_bitrate_rev_d_mode_mbps 0x124c 32 v1.1 ireal +max_symrate_rev_c_mode_msps 0x1250 32 v1.1 ireal + +# image compression capability registers +compression_capability 0x1300 +- b dpcm_pcm_simple 0 + +# test mode capability registers +test_mode_capability 0x1310 16 +- b solid_color 0 +- b color_bars 1 +- b fade_to_grey 2 +- b pn9 3 +- b color_tile 5 +pn9_data_format1 0x1312 +pn9_data_format2 0x1313 +pn9_data_format3 0x1314 +pn9_data_format4 0x1315 +pn9_misc_capability 0x1316 +- f num_pixels 0 2 +- b compression 3 +test_pattern_capability 0x1317 v1.1 +- b no_repeat 1 +pattern_size_div_m1 0x1318 v1.1 + +# fifo capability registers +fifo_support_capability 0x1502 +- e none 0 +- e derating 1 +- e derating_overrating 2 + +# csi-2 capability registers +phy_ctrl_capability 0x1600 +- b auto_phy_ctl 0 +- b ui_phy_ctl 1 +- b dphy_time_ui_reg_1_ctl 2 +- b dphy_time_ui_reg_2_ctl 3 +- b dphy_time_ctl 4 +- b dphy_ext_time_ui_reg_1_ctl 5 +- b dphy_ext_time_ui_reg_2_ctl 6 +- b dphy_ext_time_ctl 7 +csi_dphy_lane_mode_capability 0x1601 +- b 1_lane 0 +- b 2_lane 1 +- b 3_lane 2 +- b 4_lane 3 +- b 5_lane 4 +- b 6_lane 5 +- b 7_lane 6 +- b 8_lane 7 +csi_signaling_mode_capability 0x1602 +- b csi_dphy 2 +- b csi_cphy 3 +fast_standby_capability 0x1603 +- e no_frame_truncation 0 +- e frame_truncation 1 +csi_address_control_capability 0x1604 +- b cci_addr_change 0 +- b 2nd_cci_addr 1 +- b sw_changeable_2nd_cci_addr 2 +data_type_capability 0x1605 +- b dpcm_programmable 0 +- b bottom_embedded_dt_programmable 1 +- b bottom_embedded_vc_programmable 2 +- b ext_vc_range 3 +csi_cphy_lane_mode_capability 0x1606 +- b 1_lane 0 +- b 2_lane 1 +- b 3_lane 2 +- b 4_lane 3 +- b 5_lane 4 +- b 6_lane 5 +- b 7_lane 6 +- b 8_lane 7 +emb_data_capability 0x1607 v1.1 +- b two_bytes_per_raw16 0 +- b two_bytes_per_raw20 1 +- b two_bytes_per_raw24 2 +- b no_one_byte_per_raw16 3 +- b no_one_byte_per_raw20 4 +- b no_one_byte_per_raw24 5 +max_per_lane_bitrate_lane_d_mode_mbps(n) 0x1608 32 ireal +- l n 0 7 4 4,0x32 +temp_sensor_capability 0x1618 +- b supported 0 +- b CCS_format 1 +- b reset_0x80 2 +max_per_lane_bitrate_lane_c_mode_mbps(n) 0x161a 32 ireal +- l n 0 7 4 4,0x30 +dphy_equalization_capability 0x162b +- b equalization_ctrl 0 +- b eq1 1 +- b eq2 2 +cphy_equalization_capability 0x162c +- b equalization_ctrl 0 +dphy_preamble_capability 0x162d +- b preamble_seq_ctrl 0 +dphy_ssc_capability 0x162e +- b supported 0 +cphy_calibration_capability 0x162f +- b manual 0 +- b manual_streaming 1 +- b format_1_ctrl 2 +- b format_2_ctrl 3 +- b format_3_ctrl 4 +dphy_calibration_capability 0x1630 +- b manual 0 +- b manual_streaming 1 +- b alternate_seq 2 +phy_ctrl_capability_2 0x1631 +- b tgr_length 0 +- b tgr_preamble_prog_seq 1 +- b extra_cphy_manual_timing 2 +- b clock_based_manual_cdphy 3 +- b clock_based_manual_dphy 4 +- b clock_based_manual_cphy 5 +- b manual_lp_dphy 6 +- b manual_lp_cphy 7 +lrte_cphy_capability 0x1632 +- b pdq_short 0 +- b spacer_short 1 +- b pdq_long 2 +- b spacer_long 3 +- b spacer_no_pdq 4 +lrte_dphy_capability 0x1633 +- b pdq_short_opt1 0 +- b spacer_short_opt1 1 +- b pdq_long_opt1 2 +- b spacer_long_opt1 3 +- b spacer_short_opt2 4 +- b spacer_long_opt2 5 +- b spacer_no_pdq_opt1 6 +- b spacer_variable_opt2 7 +alps_capability_dphy 0x1634 +- e lvlp_not_supported 0 0x3 +- e lvlp_supported 1 0x3 +- e controllable_lvlp 2 0x3 +alps_capability_cphy 0x1635 +- e lvlp_not_supported 0 0x3 +- e lvlp_supported 1 0x3 +- e controllable_lvlp 2 0x3 +- e alp_not_supported 0xc 0xc +- e alp_supported 0xd 0xc +- e controllable_alp 0xe 0xc +scrambling_capability 0x1636 +- b scrambling_supported 0 +- f max_seeds_per_lane_c 1 2 +- e 1 0 +- e 4 3 +- f num_seed_regs 3 5 +- e 0 0 +- e 1 1 +- e 4 4 +- b num_seed_per_lane 6 +dphy_manual_constant 0x1637 +cphy_manual_constant 0x1638 +CSI2_interface_capability_misc 0x1639 v1.1 +- b eotp_short_pkt_opt2 0 +PHY_ctrl_capability_3 0x165c v1.1 +- b dphy_timing_not_multiple 0 +- b dphy_min_timing_value_1 1 +- b twakeup_supported 2 +- b tinit_supported 3 +- b ths_exit_supported 4 +- b cphy_timing_not_multiple 5 +- b cphy_min_timing_value_1 6 +dphy_sf 0x165d v1.1 +cphy_sf 0x165e v1.1 +- f twakeup 0 3 +- f tinit 4 7 +dphy_limits_1 0x165f v1.1 +- f ths_prepare 0 3 +- f ths_zero 4 7 +dphy_limits_2 0x1660 v1.1 +- f ths_trail 0 3 +- f tclk_trail_min 4 7 +dphy_limits_3 0x1661 v1.1 +- f tclk_prepare 0 3 +- f tclk_zero 4 7 +dphy_limits_4 0x1662 v1.1 +- f tclk_post 0 3 +- f tlpx 4 7 +dphy_limits_5 0x1663 v1.1 +- f ths_exit 0 3 +- f twakeup 4 7 +dphy_limits_6 0x1664 v1.1 +- f tinit 0 3 +cphy_limits_1 0x1665 v1.1 +- f t3_prepare_max 0 3 +- f t3_lpx_max 4 7 +cphy_limits_2 0x1666 v1.1 +- f ths_exit_max 0 3 +- f twakeup_max 4 7 +cphy_limits_3 0x1667 v1.1 +- f tinit_max 0 3 + +# binning capability registers +min_frame_length_lines_bin 0x1700 16 +max_frame_length_lines_bin 0x1702 16 +min_line_length_pck_bin 0x1704 16 +max_line_length_pck_bin 0x1706 16 +min_line_blanking_pck_bin 0x1708 16 +fine_integration_time_min_bin 0x170a 16 +fine_integration_time_max_margin_bin 0x170c 16 +binning_capability 0x1710 +- e unsupported 0 +- e binning_then_subsampling 1 +- e subsampling_then_binning 2 +binning_weighting_capability 0x1711 +- b averaged 0 +- b summed 1 +- b bayer_corrected 2 +- b module_specific_weight 3 +binning_sub_types 0x1712 +binning_sub_type(n) 0x1713 +- l n 0 63 1 +- f row 0 3 +- f column 4 7 +binning_weighting_mono_capability 0x1771 v1.1 +- b averaged 0 +- b summed 1 +- b bayer_corrected 2 +- b module_specific_weight 3 +binning_sub_types_mono 0x1772 v1.1 +binning_sub_type_mono(n) 0x1773 v1.1 f +- l n 0 63 1 + +# data transfer interface capability registers +data_transfer_if_capability 0x1800 +- b supported 0 +- b polling 2 + +# sensor correction capability registers +shading_correction_capability 0x1900 +- b color_shading 0 +- b luminance_correction 1 +green_imbalance_capability 0x1901 +- b supported 0 +module_specific_correction_capability 0x1903 +defect_correction_capability 0x1904 16 +- b mapped_defect 0 +- b dynamic_couplet 2 +- b dynamic_single 5 +- b combined_dynamic 8 +defect_correction_capability_2 0x1906 16 +- b dynamic_triplet 3 +nf_capability 0x1908 +- b luma 0 +- b chroma 1 +- b combined 2 + +# optical black readout capability registers +ob_readout_capability 0x1980 +- b controllable_readout 0 +- b visible_pixel_readout 1 +- b different_vc_readout 2 +- b different_dt_readout 3 +- b prog_data_format 4 + +# color feedback capability registers +color_feedback_capability 0x1987 +- b kelvin 0 +- b awb_gain 1 + +# cfa pattern capability registers +CFA_pattern_capability 0x1990 v1.1 +- e bayer 0 +- e monochrome 1 +- e 4x4_quad_bayer 2 +- e vendor_specific 3 +CFA_pattern_conversion_capability 0x1991 v1.1 +- b bayer 0 + +# timer capability registers +flash_mode_capability 0x1a02 +- b single_strobe 0 +sa_strobe_mode_capability 0x1a03 +- b fixed_width 0 +- b edge_ctrl 1 + +# soft reset capability registers +reset_max_delay 0x1a10 v1.1 +reset_min_time 0x1a11 v1.1 + +# pdaf capability registers +pdaf_capability_1 0x1b80 +- b supported 0 +- b processed_bottom_embedded 1 +- b processed_interleaved 2 +- b raw_bottom_embedded 3 +- b raw_interleaved 4 +- b visible_pdaf_correction 5 +- b vc_interleaving 6 +- b dt_interleaving 7 +pdaf_capability_2 0x1b81 +- b ROI 0 +- b after_digital_crop 1 +- b ctrl_retimed 2 + +# bracketing interface capability registers +bracketing_lut_capability_1 0x1c00 +- b coarse_integration 0 +- b global_analog_gain 1 +- b flash 4 +- b global_digital_gain 5 +- b alternate_global_analog_gain 6 +bracketing_lut_capability_2 0x1c01 +- b single_bracketing_mode 0 +- b looped_bracketing_mode 1 +bracketing_lut_size 0x1c02 diff --git a/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs new file mode 100755 index 000000000000..3d6a2a7aac3a --- /dev/null +++ b/Documentation/driver-api/media/drivers/ccs/mk-ccs-regs @@ -0,0 +1,433 @@ +#!/usr/bin/perl -w +# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause +# Copyright (C) 2019--2020 Intel Corporation + +use Getopt::Long qw(:config no_ignore_case); +use File::Basename; + +my $ccsregs = "ccs-regs.txt"; +my $header; +my $regarray; +my $limitc; +my $limith; +my $kernel; +my $help; + +GetOptions("ccsregs|c=s" => \$ccsregs, + "header|e=s" => \$header, + "regarray|r=s" => \$regarray, + "limitc|l=s" => \$limitc, + "limith|L=s" => \$limith, + "kernel|k" => \$kernel, + "help|h" => \$help) or die "can't parse options"; + +$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith; + +if (defined $help) { + print <\n#include \n"; +my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32'; +my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16'; + +open(my $R, "< $ccsregs") or die "can't open $ccsregs"; + +open(my $H, "> $header") or die "can't open $header"; +my $A; +if (defined $regarray) { + open($A, "> $regarray") or die "can't open $regarray"; +} +open(my $LC, "> $limitc") or die "can't open $limitc"; +open(my $LH, "> $limith") or die "can't open $limith"; + +my %this; + +sub is_limit_reg($) { + my $addr = hex $_[0]; + + return 0 if $addr < 0x40; # weed out status registers + return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers + + return 1; +} + +my $uc_header = basename uc $header; +$uc_header =~ s/[^A-Z0-9]/_/g; + +my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n"; +my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause"; + +for my $fh ($A, $LC) { + print $fh "// $license\n$copyright\n" if defined $fh; +} + +for my $fh ($H, $LH) { + print $fh "/* $license */\n$copyright\n"; +} + +sub bit_def($) { + my $bit = shift @_; + + return "BIT($bit)" if defined $kernel; + return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/; + return "(1U << ($bit))"; +} + +print $H <\n\n" if defined $kernel; + +print $H < +#include +#include "ccs-extra.h" +#include "ccs-regs.h" + +EOF + if defined $A; + +my $uc_limith = basename uc $limith; +$uc_limith =~ s/[^A-Z0-9]/_/g; + +print $LH <{elsize}; + my $h = $this->{argparams}; + + foreach my $arg (@{$this->{args}}) { + my $apref = $h->{$arg}; + + $size *= $apref->{max} - $apref->{min} + 1; + } + + return $size; +} + +sub print_args($$$) { + my ($this, $postfix, $is_same_reg) = @_; + my ($args, $argparams, $name) = + ($this->{args}, $this->{argparams}, $this->{name}); + my $varname = "ccs_reg_arg_" . (lc $name) . $postfix; + my @mins; + my @sorted_args = @{$this->{sorted_args}}; + my $lim_arg; + my $size = arr_size($this); + + $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n"; + + foreach my $sorted_arg (@sorted_args) { + push @mins, $argparams->{$sorted_arg}->{min}; + } + + foreach my $sorted_arg (@sorted_args) { + my $h = $argparams->{$sorted_arg}; + + $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n"; + + $lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}"; + } + + $argdescs .= "};\n\n"; + + $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) . + "), $size, sizeof($varname) / sizeof(*$varname)," . + " \"" . (lc $name) . "\", $varname },\n"; + + print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " . + $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") . + ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n" + if is_limit_reg $this->{base_addr}; +} + +my $hdr_data; + +while (<$R>) { + chop; + s/^\s*//; + next if /^[#;]/ || /^$/; + if (s/^-\s*//) { + if (s/^b\s*//) { + my ($bit, $addr) = split /\t+/; + $bit = uc $bit; + $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n"; + } elsif (s/^f\s*//) { + s/[,\.-]/_/g; + my @a = split /\s+/; + my ($msb, $lsb, $this_field) = reverse @a; + @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", }, + { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } ); + $this{"field"} = $this_field; + foreach my $ar (@a) { + #print $ar->{fmt}."\n"; + $hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n"; + } + } elsif (s/^e\s*//) { + s/[,\.-]/_/g; + my ($enum, $addr) = split /\s+/; + $enum = uc $enum; + $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n"; + } elsif (s/^l\s*//) { + my ($arg, $min, $max, $elsize, @discontig) = split /\s+/; + my $size; + + foreach my $num ($min, $max) { + $num = hex $num if $num =~ /0x/i; + } + + $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n"; + $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n"; + + my $h = $this{argparams}; + + $h->{$arg} = { "min" => $min, + "max" => $max, + "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize, + "discontig" => \@discontig }; + + $this{discontig} = $arg if @discontig; + + next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}}; + + my $reg_formula = "($this{addr}"; + my $lim_formula; + + foreach my $arg (@{$this{args}}) { + my $d = $h->{$arg}->{discontig}; + my $times = $h->{$arg}->{elsize} != 1 ? + " * " . $h->{$arg}->{elsize} : ""; + + if (@$d) { + my ($lim, $offset) = split /,/, $d->[0]; + + $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)"; + } else { + $reg_formula .= " + ($arg)$times"; + } + + $lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times"; + } + + $reg_formula .= ")\n"; + $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i; + + print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) . + $this{arglist}, $reg_formula); + + print $H tabconv $hdr_data; + undef $hdr_data; + + # Sort arguments in descending order by size + @{$this{sorted_args}} = sort { + $h->{$a}->{elsize} <= $h->{$b}->{elsize} + } @{$this{args}}; + + if (defined $this{discontig}) { + my $da = $this{argparams}->{$this{discontig}}; + my ($first_discontig) = split /,/, $da->{discontig}->[0]; + my $max = $da->{max}; + + $da->{max} = $first_discontig - 1; + print_args(\%this, "", 0); + + $da->{min} = $da->{max} + 1; + $da->{max} = $max; + print_args(\%this, $first_discontig, 1); + } else { + print_args(\%this, "", 0); + } + + next unless is_limit_reg $this{base_addr}; + + print $LH tabconv sprintf "#define %-63s%s\n", + "CCS_L_" . (uc $this{name}) . "_OFFSET(" . + (join ", ", @{$this{args}}) . ")", "($lim_formula)"; + } + + if (! @{$this{args}}) { + print $H tabconv($hdr_data); + undef $hdr_data; + } + + next; + } + + my ($name, $addr, @flags) = split /\t+/, $_; + my $args = []; + + my $sp; + + ($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/; + + $name =~ s/[,\.-]/_/g; + + my $flagstring = ""; + my $size = elem_size(@flags); + $flagstring .= "| CCS_FL_16BIT " if $size eq "2"; + $flagstring .= "| CCS_FL_32BIT " if $size eq "4"; + $flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags; + $flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags; + $flagstring =~ s/^\| //; + $flagstring =~ s/ $//; + $flagstring = "($flagstring)" if $flagstring =~ /\|/; + my $base_addr = $addr; + $addr = "($addr | $flagstring)" if $flagstring ne ""; + + my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : ""; + $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr + if !@$args; + + $name =~ s/\(.*//; + + %this = ( name => $name, + addr => $addr, + base_addr => $base_addr, + argparams => {}, + args => $args, + arglist => $arglist, + elsize => $size, + ); + + if (!@$args) { + $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n"; + print $H tabconv $hdr_data; + undef $hdr_data; + + print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " . + $this{elsize} . ", 0, \"$name\" },\n" + if is_limit_reg $this{base_addr}; + } + + print $LH tabconv sprintf "#define %-63s%s\n", + "CCS_L_" . (uc $this{name}), $limitcount++ + if is_limit_reg $this{base_addr}; +} + +if (defined $A) { + print $A $argdescs, $reglist; + + print $A "\t{ 0 }\n"; + + print $A "};\n"; +} + +print $H "\n#endif /* __${uc_header}__ */\n"; + +print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount; + +print $LH "\n#endif /* __${uc_limith}__ */\n"; + +print $LC "\t{ 0 } /* Guardian */\n"; +print $LC "};\n"; + +close($R); +close($H); +close($A) if defined $A; +close($LC); +close($LH); diff --git a/MAINTAINERS b/MAINTAINERS index a22392994667..0864fe0f945a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16108,6 +16108,7 @@ M: Sakari Ailus L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt +F: Documentation/driver-api/media/drivers/ccs/ F: drivers/media/i2c/smiapp-pll.c F: drivers/media/i2c/smiapp-pll.h F: drivers/media/i2c/smiapp/ -- cgit v1.2.3 From b24cc2a18c50e4e315abc76a86b26b4c49652f79 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 11 Feb 2020 19:05:57 +0100 Subject: media: smiapp: Rename as "ccs" Rename the "smiapp" driver as "ccs". MIPI CCS is the contemporary standard for raw Bayer camera sensors. The driver retains support for the SMIA++ and SMIA compliant camera sensors. A module alias is added for old user space using "smiapp" module name. Add Intel copyright while at it. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 22 +- drivers/media/i2c/Kconfig | 2 +- drivers/media/i2c/Makefile | 2 +- drivers/media/i2c/ccs/Kconfig | 11 + drivers/media/i2c/ccs/Makefile | 6 + drivers/media/i2c/ccs/ccs-core.c | 3302 ++++++++++++++++++++++++++++ drivers/media/i2c/ccs/ccs-limits.c | 239 ++ drivers/media/i2c/ccs/ccs-limits.h | 259 +++ drivers/media/i2c/ccs/ccs-quirk.c | 215 ++ drivers/media/i2c/ccs/ccs-quirk.h | 79 + drivers/media/i2c/ccs/ccs-reg-access.c | 266 +++ drivers/media/i2c/ccs/ccs-reg-access.h | 38 + drivers/media/i2c/ccs/ccs-regs.h | 954 ++++++++ drivers/media/i2c/ccs/ccs.h | 281 +++ drivers/media/i2c/ccs/smiapp-reg-defs.h | 580 +++++ drivers/media/i2c/smiapp/Kconfig | 10 - drivers/media/i2c/smiapp/Makefile | 6 - drivers/media/i2c/smiapp/ccs-core.c | 3300 --------------------------- drivers/media/i2c/smiapp/ccs-limits.c | 239 -- drivers/media/i2c/smiapp/ccs-limits.h | 259 --- drivers/media/i2c/smiapp/ccs-quirk.c | 214 -- drivers/media/i2c/smiapp/ccs-quirk.h | 78 - drivers/media/i2c/smiapp/ccs-reg-access.c | 265 --- drivers/media/i2c/smiapp/ccs-reg-access.h | 37 - drivers/media/i2c/smiapp/ccs-regs.h | 954 -------- drivers/media/i2c/smiapp/ccs.h | 280 --- drivers/media/i2c/smiapp/smiapp-reg-defs.h | 579 ----- 27 files changed, 6243 insertions(+), 6234 deletions(-) create mode 100644 drivers/media/i2c/ccs/Kconfig create mode 100644 drivers/media/i2c/ccs/Makefile create mode 100644 drivers/media/i2c/ccs/ccs-core.c create mode 100644 drivers/media/i2c/ccs/ccs-limits.c create mode 100644 drivers/media/i2c/ccs/ccs-limits.h create mode 100644 drivers/media/i2c/ccs/ccs-quirk.c create mode 100644 drivers/media/i2c/ccs/ccs-quirk.h create mode 100644 drivers/media/i2c/ccs/ccs-reg-access.c create mode 100644 drivers/media/i2c/ccs/ccs-reg-access.h create mode 100644 drivers/media/i2c/ccs/ccs-regs.h create mode 100644 drivers/media/i2c/ccs/ccs.h create mode 100644 drivers/media/i2c/ccs/smiapp-reg-defs.h delete mode 100644 drivers/media/i2c/smiapp/Kconfig delete mode 100644 drivers/media/i2c/smiapp/Makefile delete mode 100644 drivers/media/i2c/smiapp/ccs-core.c delete mode 100644 drivers/media/i2c/smiapp/ccs-limits.c delete mode 100644 drivers/media/i2c/smiapp/ccs-limits.h delete mode 100644 drivers/media/i2c/smiapp/ccs-quirk.c delete mode 100644 drivers/media/i2c/smiapp/ccs-quirk.h delete mode 100644 drivers/media/i2c/smiapp/ccs-reg-access.c delete mode 100644 drivers/media/i2c/smiapp/ccs-reg-access.h delete mode 100644 drivers/media/i2c/smiapp/ccs-regs.h delete mode 100644 drivers/media/i2c/smiapp/ccs.h delete mode 100644 drivers/media/i2c/smiapp/smiapp-reg-defs.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 0864fe0f945a..e23b3e4d9a9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11630,6 +11630,17 @@ M: Oliver Neukum S: Maintained F: drivers/usb/image/microtek.* +MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER +M: Sakari Ailus +L: linux-media@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt +F: Documentation/driver-api/media/drivers/ccs/ +F: drivers/media/i2c/ccs/ +F: drivers/media/i2c/smiapp-pll.c +F: drivers/media/i2c/smiapp-pll.h +F: include/uapi/linux/smiapp.h + MIPS M: Thomas Bogendoerfer L: linux-mips@vger.kernel.org @@ -16103,17 +16114,6 @@ S: Maintained F: drivers/firmware/smccc/ F: include/linux/arm-smccc.h -SMIA AND SMIA++ IMAGE SENSOR DRIVER -M: Sakari Ailus -L: linux-media@vger.kernel.org -S: Maintained -F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt -F: Documentation/driver-api/media/drivers/ccs/ -F: drivers/media/i2c/smiapp-pll.c -F: drivers/media/i2c/smiapp-pll.h -F: drivers/media/i2c/smiapp/ -F: include/uapi/linux/smiapp.h - SMM665 HARDWARE MONITOR DRIVER M: Guenter Roeck L: linux-hwmon@vger.kernel.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 369b6d859da5..3787c22767d9 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1247,7 +1247,7 @@ config VIDEO_S5K5BAF This is a V4L2 sensor driver for Samsung S5K5BAF 2M camera sensor with an embedded SoC image signal processor. -source "drivers/media/i2c/smiapp/Kconfig" +source "drivers/media/i2c/ccs/Kconfig" source "drivers/media/i2c/et8ek8/Kconfig" config VIDEO_S5C73M3 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index b448506ce503..5c733394171d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -2,7 +2,7 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o -obj-$(CONFIG_VIDEO_SMIAPP) += smiapp/ +obj-$(CONFIG_VIDEO_CCS) += ccs/ obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/ obj-$(CONFIG_VIDEO_CX25840) += cx25840/ obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ diff --git a/drivers/media/i2c/ccs/Kconfig b/drivers/media/i2c/ccs/Kconfig new file mode 100644 index 000000000000..b4f8b10da420 --- /dev/null +++ b/drivers/media/i2c/ccs/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config VIDEO_CCS + tristate "MIPI CCS/SMIA++/SMIA sensor support" + depends on I2C && VIDEO_V4L2 && HAVE_CLK + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select VIDEO_SMIAPP_PLL + select V4L2_FWNODE + help + This is a generic driver for MIPI CCS, SMIA++ and SMIA compliant + camera sensors. diff --git a/drivers/media/i2c/ccs/Makefile b/drivers/media/i2c/ccs/Makefile new file mode 100644 index 000000000000..08dd4e948fb0 --- /dev/null +++ b/drivers/media/i2c/ccs/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +ccs-objs += ccs-core.o ccs-reg-access.o \ + ccs-quirk.o ccs-limits.o +obj-$(CONFIG_VIDEO_CCS) += ccs.o + +ccflags-y += -I $(srctree)/drivers/media/i2c diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c new file mode 100644 index 000000000000..2dfb26cb3a40 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -0,0 +1,3302 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * drivers/media/i2c/ccs/ccs-core.c + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2010--2012 Nokia Corporation + * Contact: Sakari Ailus + * + * Based on smiapp driver by Vimarsh Zutshi + * Based on jt8ev1.c by Vimarsh Zutshi + * Based on smia-sensor.c by Tuukka Toivonen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccs.h" +#include "ccs-limits.h" + +#define CCS_ALIGN_DIM(dim, flags) \ + ((flags) & V4L2_SEL_FLAG_GE \ + ? ALIGN((dim), 2) \ + : (dim) & ~1) + +static struct ccs_limit_offset { + u16 lim; + u16 info; +} ccs_limit_offsets[CCS_L_LAST + 1]; + +/* + * ccs_module_idents - supported camera modules + */ +static const struct ccs_module_ident ccs_module_idents[] = { + CCS_IDENT_L(0x01, 0x022b, -1, "vs6555"), + CCS_IDENT_L(0x01, 0x022e, -1, "vw6558"), + CCS_IDENT_L(0x07, 0x7698, -1, "ovm7698"), + CCS_IDENT_L(0x0b, 0x4242, -1, "smiapp-003"), + CCS_IDENT_L(0x0c, 0x208a, -1, "tcm8330md"), + CCS_IDENT_LQ(0x0c, 0x2134, -1, "tcm8500md", &smiapp_tcm8500md_quirk), + CCS_IDENT_L(0x0c, 0x213e, -1, "et8en2"), + CCS_IDENT_L(0x0c, 0x2184, -1, "tcm8580md"), + CCS_IDENT_LQ(0x0c, 0x560f, -1, "jt8ew9", &smiapp_jt8ew9_quirk), + CCS_IDENT_LQ(0x10, 0x4141, -1, "jt8ev1", &smiapp_jt8ev1_quirk), + CCS_IDENT_LQ(0x10, 0x4241, -1, "imx125es", &smiapp_imx125es_quirk), +}; + +/* + * + * Dynamic Capability Identification + * + */ + +static void ccs_assign_limit(void *ptr, unsigned int width, u32 val) +{ + switch (width) { + case sizeof(u8): + *(u8 *)ptr = val; + break; + case sizeof(u16): + *(u16 *)ptr = val; + break; + case sizeof(u32): + *(u32 *)ptr = val; + break; + } +} + +static int ccs_limit_ptr(struct ccs_sensor *sensor, unsigned int limit, + unsigned int offset, void **__ptr) +{ + const struct ccs_limit *linfo; + + if (WARN_ON(limit >= CCS_L_LAST)) + return -EINVAL; + + linfo = &ccs_limits[ccs_limit_offsets[limit].info]; + + if (WARN_ON(!sensor->ccs_limits) || + WARN_ON(offset + ccs_reg_width(linfo->reg) > + ccs_limit_offsets[limit + 1].lim)) + return -EINVAL; + + *__ptr = sensor->ccs_limits + ccs_limit_offsets[limit].lim + offset; + + return 0; +} + +void ccs_replace_limit(struct ccs_sensor *sensor, + unsigned int limit, unsigned int offset, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + const struct ccs_limit *linfo; + void *ptr; + int ret; + + ret = ccs_limit_ptr(sensor, limit, offset, &ptr); + if (ret) + return; + + linfo = &ccs_limits[ccs_limit_offsets[limit].info]; + + dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %d, 0x%x\n", + linfo->reg, linfo->name, offset, val, val); + + ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val); +} + +static u32 ccs_get_limit(struct ccs_sensor *sensor, + unsigned int limit, unsigned int offset) +{ + void *ptr; + int ret; + + ret = ccs_limit_ptr(sensor, limit, offset, &ptr); + if (ret) + return 0; + + switch (ccs_reg_width(ccs_limits[ccs_limit_offsets[limit].info].reg)) { + case sizeof(u8): + return *(u8 *)ptr; + case sizeof(u16): + return *(u16 *)ptr; + case sizeof(u32): + return *(u32 *)ptr; + } + + WARN_ON(1); + + return 0; +} + +#define CCS_LIM(sensor, limit) \ + ccs_get_limit(sensor, CCS_L_##limit, 0) + +#define CCS_LIM_AT(sensor, limit, offset) \ + ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset)) + +static int ccs_read_all_limits(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + void *ptr, *alloc, *end; + unsigned int i, l; + int ret; + + kfree(sensor->ccs_limits); + sensor->ccs_limits = NULL; + + alloc = kzalloc(ccs_limit_offsets[CCS_L_LAST].lim, GFP_KERNEL); + if (!alloc) + return -ENOMEM; + + end = alloc + ccs_limit_offsets[CCS_L_LAST].lim; + + for (i = 0, l = 0, ptr = alloc; ccs_limits[i].size; i++) { + u32 reg = ccs_limits[i].reg; + unsigned int width = ccs_reg_width(reg); + unsigned int j; + + if (l == CCS_L_LAST) { + dev_err(&client->dev, + "internal error --- end of limit array\n"); + ret = -EINVAL; + goto out_err; + } + + for (j = 0; j < ccs_limits[i].size / width; + j++, reg += width, ptr += width) { + u32 val; + + ret = ccs_read_addr(sensor, reg, &val); + if (ret) + goto out_err; + + if (ptr + width > end) { + dev_err(&client->dev, + "internal error --- no room for regs\n"); + ret = -EINVAL; + goto out_err; + } + + ccs_assign_limit(ptr, width, val); + + dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n", + reg, ccs_limits[i].name, val, val); + } + + if (ccs_limits[i].flags & CCS_L_FL_SAME_REG) + continue; + + l++; + ptr = alloc + ccs_limit_offsets[l].lim; + } + + if (l != CCS_L_LAST) { + dev_err(&client->dev, + "internal error --- insufficient limits\n"); + ret = -EINVAL; + goto out_err; + } + + sensor->ccs_limits = alloc; + + if (CCS_LIM(sensor, SCALER_N_MIN) < 16) + ccs_replace_limit(sensor, CCS_L_SCALER_N_MIN, 0, 16); + + return 0; + +out_err: + kfree(alloc); + + return ret; +} + +static int ccs_read_frame_fmt(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + u8 fmt_model_type, fmt_model_subtype, ncol_desc, nrow_desc; + unsigned int i; + int pixel_count = 0; + int line_count = 0; + + fmt_model_type = CCS_LIM(sensor, FRAME_FORMAT_MODEL_TYPE); + fmt_model_subtype = CCS_LIM(sensor, FRAME_FORMAT_MODEL_SUBTYPE); + + ncol_desc = (fmt_model_subtype + & CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK) + >> CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT; + nrow_desc = fmt_model_subtype + & CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_MASK; + + dev_dbg(&client->dev, "format_model_type %s\n", + fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE + ? "2 byte" : + fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE + ? "4 byte" : "is simply bad"); + + dev_dbg(&client->dev, "%u column and %u row descriptors\n", + ncol_desc, nrow_desc); + + for (i = 0; i < ncol_desc + nrow_desc; i++) { + u32 desc; + u32 pixelcode; + u32 pixels; + char *which; + char *what; + u32 reg; + + if (fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE) { + desc = CCS_LIM_AT(sensor, FRAME_FORMAT_DESCRIPTOR, i); + + pixelcode = + (desc + & CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MASK) + >> CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_SHIFT; + pixels = desc & CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_MASK; + } else if (fmt_model_type + == CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE) { + desc = CCS_LIM_AT(sensor, FRAME_FORMAT_DESCRIPTOR_4, i); + + pixelcode = + (desc + & CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MASK) + >> CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_SHIFT; + pixels = desc & + CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK; + } else { + dev_dbg(&client->dev, + "invalid frame format model type %d\n", + fmt_model_type); + return -EINVAL; + } + + if (i < ncol_desc) + which = "columns"; + else + which = "rows"; + + switch (pixelcode) { + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED: + what = "embedded"; + break; + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DUMMY_PIXEL: + what = "dummy"; + break; + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_BLACK_PIXEL: + what = "black"; + break; + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DARK_PIXEL: + what = "dark"; + break; + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL: + what = "visible"; + break; + default: + what = "invalid"; + break; + } + + dev_dbg(&client->dev, + "0x%8.8x %s pixels: %d %s (pixelcode %u)\n", reg, + what, pixels, which, pixelcode); + + if (i < ncol_desc) { + if (pixelcode == + CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL) + sensor->visible_pixel_start = pixel_count; + pixel_count += pixels; + continue; + } + + /* Handle row descriptors */ + switch (pixelcode) { + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED: + if (sensor->embedded_end) + break; + sensor->embedded_start = line_count; + sensor->embedded_end = line_count + pixels; + break; + case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL: + sensor->image_start = line_count; + break; + } + line_count += pixels; + } + + if (sensor->embedded_end > sensor->image_start) { + dev_dbg(&client->dev, + "adjusting image start line to %u (was %u)\n", + sensor->embedded_end, sensor->image_start); + sensor->image_start = sensor->embedded_end; + } + + dev_dbg(&client->dev, "embedded data from lines %d to %d\n", + sensor->embedded_start, sensor->embedded_end); + dev_dbg(&client->dev, "image data starts at line %d\n", + sensor->image_start); + + return 0; +} + +static int ccs_pll_configure(struct ccs_sensor *sensor) +{ + struct smiapp_pll *pll = &sensor->pll; + int rval; + + rval = ccs_write(sensor, VT_PIX_CLK_DIV, pll->vt.pix_clk_div); + if (rval < 0) + return rval; + + rval = ccs_write(sensor, VT_SYS_CLK_DIV, pll->vt.sys_clk_div); + if (rval < 0) + return rval; + + rval = ccs_write(sensor, PRE_PLL_CLK_DIV, pll->pre_pll_clk_div); + if (rval < 0) + return rval; + + rval = ccs_write(sensor, PLL_MULTIPLIER, pll->pll_multiplier); + if (rval < 0) + return rval; + + /* Lane op clock ratio does not apply here. */ + rval = ccs_write(sensor, REQUESTED_LINK_RATE, + DIV_ROUND_UP(pll->op.sys_clk_freq_hz, + 1000000 / 256 / 256)); + if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) + return rval; + + rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op.pix_clk_div); + if (rval < 0) + return rval; + + return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op.sys_clk_div); +} + +static int ccs_pll_try(struct ccs_sensor *sensor, struct smiapp_pll *pll) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct smiapp_pll_limits lim = { + .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_PRE_PLL_CLK_DIV), + .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_PRE_PLL_CLK_DIV), + .min_pll_ip_freq_hz = CCS_LIM(sensor, MIN_PLL_IP_CLK_FREQ_MHZ), + .max_pll_ip_freq_hz = CCS_LIM(sensor, MAX_PLL_IP_CLK_FREQ_MHZ), + .min_pll_multiplier = CCS_LIM(sensor, MIN_PLL_MULTIPLIER), + .max_pll_multiplier = CCS_LIM(sensor, MAX_PLL_MULTIPLIER), + .min_pll_op_freq_hz = CCS_LIM(sensor, MIN_PLL_OP_CLK_FREQ_MHZ), + .max_pll_op_freq_hz = CCS_LIM(sensor, MAX_PLL_OP_CLK_FREQ_MHZ), + + .op.min_sys_clk_div = CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV), + .op.max_sys_clk_div = CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV), + .op.min_pix_clk_div = CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV), + .op.max_pix_clk_div = CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV), + .op.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_OP_SYS_CLK_FREQ_MHZ), + .op.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_OP_SYS_CLK_FREQ_MHZ), + .op.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PIX_CLK_FREQ_MHZ), + .op.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PIX_CLK_FREQ_MHZ), + + .vt.min_sys_clk_div = CCS_LIM(sensor, MIN_VT_SYS_CLK_DIV), + .vt.max_sys_clk_div = CCS_LIM(sensor, MAX_VT_SYS_CLK_DIV), + .vt.min_pix_clk_div = CCS_LIM(sensor, MIN_VT_PIX_CLK_DIV), + .vt.max_pix_clk_div = CCS_LIM(sensor, MAX_VT_PIX_CLK_DIV), + .vt.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_VT_SYS_CLK_FREQ_MHZ), + .vt.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_VT_SYS_CLK_FREQ_MHZ), + .vt.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_VT_PIX_CLK_FREQ_MHZ), + .vt.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_VT_PIX_CLK_FREQ_MHZ), + + .min_line_length_pck_bin = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN), + .min_line_length_pck = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK), + }; + + return smiapp_pll_calculate(&client->dev, &lim, pll); +} + +static int ccs_pll_update(struct ccs_sensor *sensor) +{ + struct smiapp_pll *pll = &sensor->pll; + int rval; + + pll->binning_horizontal = sensor->binning_horizontal; + pll->binning_vertical = sensor->binning_vertical; + pll->link_freq = + sensor->link_freq->qmenu_int[sensor->link_freq->val]; + pll->scale_m = sensor->scale_m; + pll->bits_per_pixel = sensor->csi_format->compressed; + + rval = ccs_pll_try(sensor, pll); + if (rval < 0) + return rval; + + __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray, + pll->pixel_rate_pixel_array); + __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi); + + return 0; +} + + +/* + * + * V4L2 Controls handling + * + */ + +static void __ccs_update_exposure_limits(struct ccs_sensor *sensor) +{ + struct v4l2_ctrl *ctrl = sensor->exposure; + int max; + + max = sensor->pixel_array->crop[CCS_PA_PAD_SRC].height + + sensor->vblank->val + - CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); + + __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max); +} + +/* + * Order matters. + * + * 1. Bits-per-pixel, descending. + * 2. Bits-per-pixel compressed, descending. + * 3. Pixel order, same as in pixel_order_str. Formats for all four pixel + * orders must be defined. + */ +static const struct ccs_csi_data_format ccs_csi_data_formats[] = { + { MEDIA_BUS_FMT_SGRBG16_1X16, 16, 16, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB16_1X16, 16, 16, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR16_1X16, 16, 16, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG16_1X16, 16, 16, CCS_PIXEL_ORDER_GBRG, }, + { MEDIA_BUS_FMT_SGRBG14_1X14, 14, 14, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB14_1X14, 14, 14, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR14_1X14, 14, 14, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG14_1X14, 14, 14, CCS_PIXEL_ORDER_GBRG, }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, CCS_PIXEL_ORDER_GBRG, }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, CCS_PIXEL_ORDER_GBRG, }, + { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_GBRG, }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, CCS_PIXEL_ORDER_GRBG, }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, CCS_PIXEL_ORDER_RGGB, }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, CCS_PIXEL_ORDER_BGGR, }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, CCS_PIXEL_ORDER_GBRG, }, +}; + +static const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" }; + +#define to_csi_format_idx(fmt) (((unsigned long)(fmt) \ + - (unsigned long)ccs_csi_data_formats) \ + / sizeof(*ccs_csi_data_formats)) + +static u32 ccs_pixel_order(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int flip = 0; + + if (sensor->hflip) { + if (sensor->hflip->val) + flip |= CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR; + + if (sensor->vflip->val) + flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; + } + + flip ^= sensor->hvflip_inv_mask; + + dev_dbg(&client->dev, "flip %d\n", flip); + return sensor->default_pixel_order ^ flip; +} + +static void ccs_update_mbus_formats(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + unsigned int csi_format_idx = + to_csi_format_idx(sensor->csi_format) & ~3; + unsigned int internal_csi_format_idx = + to_csi_format_idx(sensor->internal_csi_format) & ~3; + unsigned int pixel_order = ccs_pixel_order(sensor); + + sensor->mbus_frame_fmts = + sensor->default_mbus_frame_fmts << pixel_order; + sensor->csi_format = + &ccs_csi_data_formats[csi_format_idx + pixel_order]; + sensor->internal_csi_format = + &ccs_csi_data_formats[internal_csi_format_idx + + pixel_order]; + + BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order + >= ARRAY_SIZE(ccs_csi_data_formats)); + + dev_dbg(&client->dev, "new pixel order %s\n", + pixel_order_str[pixel_order]); +} + +static const char * const ccs_test_patterns[] = { + "Disabled", + "Solid Colour", + "Eight Vertical Colour Bars", + "Colour Bars With Fade to Grey", + "Pseudorandom Sequence (PN9)", +}; + +static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ccs_sensor *sensor = + container_of(ctrl->handler, struct ccs_subdev, ctrl_handler) + ->sensor; + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int pm_status; + u32 orient = 0; + unsigned int i; + int exposure; + int rval; + + switch (ctrl->id) { + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + if (sensor->streaming) + return -EBUSY; + + if (sensor->hflip->val) + orient |= CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR; + + if (sensor->vflip->val) + orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; + + orient ^= sensor->hvflip_inv_mask; + + ccs_update_mbus_formats(sensor); + + break; + case V4L2_CID_VBLANK: + exposure = sensor->exposure->val; + + __ccs_update_exposure_limits(sensor); + + if (exposure > sensor->exposure->maximum) { + sensor->exposure->val = sensor->exposure->maximum; + rval = ccs_set_ctrl(sensor->exposure); + if (rval < 0) + return rval; + } + + break; + case V4L2_CID_LINK_FREQ: + if (sensor->streaming) + return -EBUSY; + + rval = ccs_pll_update(sensor); + if (rval) + return rval; + + return 0; + case V4L2_CID_TEST_PATTERN: + for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) + v4l2_ctrl_activate( + sensor->test_data[i], + ctrl->val == + V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR); + + break; + } + + pm_status = pm_runtime_get_if_active(&client->dev, true); + if (!pm_status) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + rval = ccs_write(sensor, ANALOG_GAIN_CODE_GLOBAL, ctrl->val); + + break; + case V4L2_CID_EXPOSURE: + rval = ccs_write(sensor, COARSE_INTEGRATION_TIME, ctrl->val); + + break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + rval = ccs_write(sensor, IMAGE_ORIENTATION, orient); + + break; + case V4L2_CID_VBLANK: + rval = ccs_write(sensor, FRAME_LENGTH_LINES, + sensor->pixel_array->crop[ + CCS_PA_PAD_SRC].height + + ctrl->val); + + break; + case V4L2_CID_HBLANK: + rval = ccs_write(sensor, LINE_LENGTH_PCK, + sensor->pixel_array->crop[ + CCS_PA_PAD_SRC].width + + ctrl->val); + + break; + case V4L2_CID_TEST_PATTERN: + rval = ccs_write(sensor, TEST_PATTERN_MODE, ctrl->val); + + break; + case V4L2_CID_TEST_PATTERN_RED: + rval = ccs_write(sensor, TEST_DATA_RED, ctrl->val); + + break; + case V4L2_CID_TEST_PATTERN_GREENR: + rval = ccs_write(sensor, TEST_DATA_GREENR, ctrl->val); + + break; + case V4L2_CID_TEST_PATTERN_BLUE: + rval = ccs_write(sensor, TEST_DATA_BLUE, ctrl->val); + + break; + case V4L2_CID_TEST_PATTERN_GREENB: + rval = ccs_write(sensor, TEST_DATA_GREENB, ctrl->val); + + break; + case V4L2_CID_PIXEL_RATE: + /* For v4l2_ctrl_s_ctrl_int64() used internally. */ + rval = 0; + + break; + default: + rval = -EINVAL; + } + + if (pm_status > 0) { + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + } + + return rval; +} + +static const struct v4l2_ctrl_ops ccs_ctrl_ops = { + .s_ctrl = ccs_set_ctrl, +}; + +static int ccs_init_controls(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12); + if (rval) + return rval; + + sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; + + sensor->analog_gain = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, + CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN), + CCS_LIM(sensor, ANALOG_GAIN_CODE_MAX), + max(CCS_LIM(sensor, ANALOG_GAIN_CODE_STEP), 1U), + CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN)); + + /* Exposure limits will be updated soon, use just something here. */ + sensor->exposure = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 0, 1, 0); + + sensor->hflip = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + sensor->vflip = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + sensor->vblank = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_VBLANK, 0, 1, 1, 0); + + if (sensor->vblank) + sensor->vblank->flags |= V4L2_CTRL_FLAG_UPDATE; + + sensor->hblank = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_HBLANK, 0, 1, 1, 0); + + if (sensor->hblank) + sensor->hblank->flags |= V4L2_CTRL_FLAG_UPDATE; + + sensor->pixel_rate_parray = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); + + v4l2_ctrl_new_std_menu_items(&sensor->pixel_array->ctrl_handler, + &ccs_ctrl_ops, V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ccs_test_patterns) - 1, + 0, 0, ccs_test_patterns); + + if (sensor->pixel_array->ctrl_handler.error) { + dev_err(&client->dev, + "pixel array controls initialization failed (%d)\n", + sensor->pixel_array->ctrl_handler.error); + return sensor->pixel_array->ctrl_handler.error; + } + + sensor->pixel_array->sd.ctrl_handler = + &sensor->pixel_array->ctrl_handler; + + v4l2_ctrl_cluster(2, &sensor->hflip); + + rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0); + if (rval) + return rval; + + sensor->src->ctrl_handler.lock = &sensor->mutex; + + sensor->pixel_rate_csi = v4l2_ctrl_new_std( + &sensor->src->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); + + if (sensor->src->ctrl_handler.error) { + dev_err(&client->dev, + "src controls initialization failed (%d)\n", + sensor->src->ctrl_handler.error); + return sensor->src->ctrl_handler.error; + } + + sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler; + + return 0; +} + +/* + * For controls that require information on available media bus codes + * and linke frequencies. + */ +static int ccs_init_late_controls(struct ccs_sensor *sensor) +{ + unsigned long *valid_link_freqs = &sensor->valid_link_freqs[ + sensor->csi_format->compressed - sensor->compressed_min_bpp]; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { + int max_value = (1 << sensor->csi_format->width) - 1; + + sensor->test_data[i] = v4l2_ctrl_new_std( + &sensor->pixel_array->ctrl_handler, + &ccs_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i, + 0, max_value, 1, max_value); + } + + sensor->link_freq = v4l2_ctrl_new_int_menu( + &sensor->src->ctrl_handler, &ccs_ctrl_ops, + V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), + __ffs(*valid_link_freqs), sensor->hwcfg->op_sys_clock); + + return sensor->src->ctrl_handler.error; +} + +static void ccs_free_controls(struct ccs_sensor *sensor) +{ + unsigned int i; + + for (i = 0; i < sensor->ssds_used; i++) + v4l2_ctrl_handler_free(&sensor->ssds[i].ctrl_handler); +} + +static int ccs_get_mbus_formats(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct smiapp_pll *pll = &sensor->pll; + u8 compressed_max_bpp = 0; + unsigned int type, n; + unsigned int i, pixel_order; + int rval; + + type = CCS_LIM(sensor, DATA_FORMAT_MODEL_TYPE); + + dev_dbg(&client->dev, "data_format_model_type %d\n", type); + + rval = ccs_read(sensor, PIXEL_ORDER, &pixel_order); + if (rval) + return rval; + + if (pixel_order >= ARRAY_SIZE(pixel_order_str)) { + dev_dbg(&client->dev, "bad pixel order %d\n", pixel_order); + return -EINVAL; + } + + dev_dbg(&client->dev, "pixel order %d (%s)\n", pixel_order, + pixel_order_str[pixel_order]); + + switch (type) { + case CCS_DATA_FORMAT_MODEL_TYPE_NORMAL: + n = SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N; + break; + case CCS_DATA_FORMAT_MODEL_TYPE_EXTENDED: + n = CCS_LIM_DATA_FORMAT_DESCRIPTOR_MAX_N + 1; + break; + default: + return -EINVAL; + } + + sensor->default_pixel_order = pixel_order; + sensor->mbus_frame_fmts = 0; + + for (i = 0; i < n; i++) { + unsigned int fmt, j; + + fmt = CCS_LIM_AT(sensor, DATA_FORMAT_DESCRIPTOR, i); + + dev_dbg(&client->dev, "%u: bpp %u, compressed %u\n", + i, fmt >> 8, (u8)fmt); + + for (j = 0; j < ARRAY_SIZE(ccs_csi_data_formats); j++) { + const struct ccs_csi_data_format *f = + &ccs_csi_data_formats[j]; + + if (f->pixel_order != CCS_PIXEL_ORDER_GRBG) + continue; + + if (f->width != fmt >> + CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT || + f->compressed != + (fmt & CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK)) + continue; + + dev_dbg(&client->dev, "jolly good! %d\n", j); + + sensor->default_mbus_frame_fmts |= 1 << j; + } + } + + /* Figure out which BPP values can be used with which formats. */ + pll->binning_horizontal = 1; + pll->binning_vertical = 1; + pll->scale_m = sensor->scale_m; + + for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { + sensor->compressed_min_bpp = + min(ccs_csi_data_formats[i].compressed, + sensor->compressed_min_bpp); + compressed_max_bpp = + max(ccs_csi_data_formats[i].compressed, + compressed_max_bpp); + } + + sensor->valid_link_freqs = devm_kcalloc( + &client->dev, + compressed_max_bpp - sensor->compressed_min_bpp + 1, + sizeof(*sensor->valid_link_freqs), GFP_KERNEL); + if (!sensor->valid_link_freqs) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { + const struct ccs_csi_data_format *f = + &ccs_csi_data_formats[i]; + unsigned long *valid_link_freqs = + &sensor->valid_link_freqs[ + f->compressed - sensor->compressed_min_bpp]; + unsigned int j; + + if (!(sensor->default_mbus_frame_fmts & 1 << i)) + continue; + + pll->bits_per_pixel = f->compressed; + + for (j = 0; sensor->hwcfg->op_sys_clock[j]; j++) { + pll->link_freq = sensor->hwcfg->op_sys_clock[j]; + + rval = ccs_pll_try(sensor, pll); + dev_dbg(&client->dev, "link freq %u Hz, bpp %u %s\n", + pll->link_freq, pll->bits_per_pixel, + rval ? "not ok" : "ok"); + if (rval) + continue; + + set_bit(j, valid_link_freqs); + } + + if (!*valid_link_freqs) { + dev_info(&client->dev, + "no valid link frequencies for %u bpp\n", + f->compressed); + sensor->default_mbus_frame_fmts &= ~BIT(i); + continue; + } + + if (!sensor->csi_format + || f->width > sensor->csi_format->width + || (f->width == sensor->csi_format->width + && f->compressed > sensor->csi_format->compressed)) { + sensor->csi_format = f; + sensor->internal_csi_format = f; + } + } + + if (!sensor->csi_format) { + dev_err(&client->dev, "no supported mbus code found\n"); + return -EINVAL; + } + + ccs_update_mbus_formats(sensor); + + return 0; +} + +static void ccs_update_blanking(struct ccs_sensor *sensor) +{ + struct v4l2_ctrl *vblank = sensor->vblank; + struct v4l2_ctrl *hblank = sensor->hblank; + uint16_t min_fll, max_fll, min_llp, max_llp, min_lbp; + int min, max; + + if (sensor->binning_vertical > 1 || sensor->binning_horizontal > 1) { + min_fll = CCS_LIM(sensor, MIN_FRAME_LENGTH_LINES_BIN); + max_fll = CCS_LIM(sensor, MAX_FRAME_LENGTH_LINES_BIN); + min_llp = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN); + max_llp = CCS_LIM(sensor, MAX_LINE_LENGTH_PCK_BIN); + min_lbp = CCS_LIM(sensor, MIN_LINE_BLANKING_PCK_BIN); + } else { + min_fll = CCS_LIM(sensor, MIN_FRAME_LENGTH_LINES); + max_fll = CCS_LIM(sensor, MAX_FRAME_LENGTH_LINES); + min_llp = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK); + max_llp = CCS_LIM(sensor, MAX_LINE_LENGTH_PCK); + min_lbp = CCS_LIM(sensor, MIN_LINE_BLANKING_PCK); + } + + min = max_t(int, + CCS_LIM(sensor, MIN_FRAME_BLANKING_LINES), + min_fll - + sensor->pixel_array->crop[CCS_PA_PAD_SRC].height); + max = max_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height; + + __v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); + + min = max_t(int, + min_llp - + sensor->pixel_array->crop[CCS_PA_PAD_SRC].width, + min_lbp); + max = max_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width; + + __v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min); + + __ccs_update_exposure_limits(sensor); +} + +static int ccs_pll_blanking_update(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + rval = ccs_pll_update(sensor); + if (rval < 0) + return rval; + + /* Output from pixel array, including blanking */ + ccs_update_blanking(sensor); + + dev_dbg(&client->dev, "vblank\t\t%d\n", sensor->vblank->val); + dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val); + + dev_dbg(&client->dev, "real timeperframe\t100/%d\n", + sensor->pll.pixel_rate_pixel_array / + ((sensor->pixel_array->crop[CCS_PA_PAD_SRC].width + + sensor->hblank->val) * + (sensor->pixel_array->crop[CCS_PA_PAD_SRC].height + + sensor->vblank->val) / 100)); + + return 0; +} + +/* + * + * SMIA++ NVM handling + * + */ + +static int ccs_read_nvm_page(struct ccs_sensor *sensor, u32 p, u8 *nvm, + u8 *status) +{ + unsigned int i; + int rval; + u32 s; + + *status = 0; + + rval = ccs_write(sensor, DATA_TRANSFER_IF_1_PAGE_SELECT, p); + if (rval) + return rval; + + rval = ccs_write(sensor, DATA_TRANSFER_IF_1_CTRL, + CCS_DATA_TRANSFER_IF_1_CTRL_ENABLE); + if (rval) + return rval; + + rval = ccs_read(sensor, DATA_TRANSFER_IF_1_STATUS, &s); + if (rval) + return rval; + + if (s & CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE) { + *status = s; + return -ENODATA; + } + + if (CCS_LIM(sensor, DATA_TRANSFER_IF_CAPABILITY) & + CCS_DATA_TRANSFER_IF_CAPABILITY_POLLING) { + for (i = 1000; i > 0; i--) { + if (s & CCS_DATA_TRANSFER_IF_1_STATUS_READ_IF_READY) + break; + + rval = ccs_read(sensor, DATA_TRANSFER_IF_1_STATUS, &s); + if (rval) + return rval; + } + + if (!i) + return -ETIMEDOUT; + } + + for (i = 0; i <= CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P; i++) { + u32 v; + + rval = ccs_read(sensor, DATA_TRANSFER_IF_1_DATA(i), &v); + if (rval) + return rval; + + *nvm++ = v; + } + + return 0; +} + +static int ccs_read_nvm(struct ccs_sensor *sensor, unsigned char *nvm, + size_t nvm_size) +{ + u8 status = 0; + u32 p; + int rval = 0, rval2; + + for (p = 0; p < nvm_size / (CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1) + && !rval; p++) { + rval = ccs_read_nvm_page(sensor, p, nvm, &status); + nvm += CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1; + } + + if (rval == -ENODATA && + status & CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE) + rval = 0; + + rval2 = ccs_write(sensor, DATA_TRANSFER_IF_1_CTRL, 0); + if (rval < 0) + return rval; + else + return rval2 ?: p * (CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1); +} + +/* + * + * SMIA++ CCI address control + * + */ +static int ccs_change_cci_addr(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + u32 val; + + client->addr = sensor->hwcfg->i2c_addr_dfl; + + rval = ccs_write(sensor, CCI_ADDRESS_CTRL, + sensor->hwcfg->i2c_addr_alt << 1); + if (rval) + return rval; + + client->addr = sensor->hwcfg->i2c_addr_alt; + + /* verify addr change went ok */ + rval = ccs_read(sensor, CCI_ADDRESS_CTRL, &val); + if (rval) + return rval; + + if (val != sensor->hwcfg->i2c_addr_alt << 1) + return -ENODEV; + + return 0; +} + +/* + * + * SMIA++ Mode Control + * + */ +static int ccs_setup_flash_strobe(struct ccs_sensor *sensor) +{ + struct ccs_flash_strobe_parms *strobe_setup; + unsigned int ext_freq = sensor->hwcfg->ext_clk; + u32 tmp; + u32 strobe_adjustment; + u32 strobe_width_high_rs; + int rval; + + strobe_setup = sensor->hwcfg->strobe_setup; + + /* + * How to calculate registers related to strobe length. Please + * do not change, or if you do at least know what you're + * doing. :-) + * + * Sakari Ailus 2010-10-25 + * + * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl + * / EXTCLK freq [Hz]) * flash_strobe_adjustment + * + * tFlash_strobe_width_ctrl E N, [1 - 0xffff] + * flash_strobe_adjustment E N, [1 - 0xff] + * + * The formula above is written as below to keep it on one + * line: + * + * l / 10^6 = w / e * a + * + * Let's mark w * a by x: + * + * x = w * a + * + * Thus, we get: + * + * x = l * e / 10^6 + * + * The strobe width must be at least as long as requested, + * thus rounding upwards is needed. + * + * x = (l * e + 10^6 - 1) / 10^6 + * ----------------------------- + * + * Maximum possible accuracy is wanted at all times. Thus keep + * a as small as possible. + * + * Calculate a, assuming maximum w, with rounding upwards: + * + * a = (x + (2^16 - 1) - 1) / (2^16 - 1) + * ------------------------------------- + * + * Thus, we also get w, with that a, with rounding upwards: + * + * w = (x + a - 1) / a + * ------------------- + * + * To get limits: + * + * x E [1, (2^16 - 1) * (2^8 - 1)] + * + * Substituting maximum x to the original formula (with rounding), + * the maximum l is thus + * + * (2^16 - 1) * (2^8 - 1) * 10^6 = l * e + 10^6 - 1 + * + * l = (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / e + * -------------------------------------------------- + * + * flash_strobe_length must be clamped between 1 and + * (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / EXTCLK freq. + * + * Then, + * + * flash_strobe_adjustment = ((flash_strobe_length * + * EXTCLK freq + 10^6 - 1) / 10^6 + (2^16 - 1) - 1) / (2^16 - 1) + * + * tFlash_strobe_width_ctrl = ((flash_strobe_length * + * EXTCLK freq + 10^6 - 1) / 10^6 + + * flash_strobe_adjustment - 1) / flash_strobe_adjustment + */ + tmp = div_u64(1000000ULL * ((1 << 16) - 1) * ((1 << 8) - 1) - + 1000000 + 1, ext_freq); + strobe_setup->strobe_width_high_us = + clamp_t(u32, strobe_setup->strobe_width_high_us, 1, tmp); + + tmp = div_u64(((u64)strobe_setup->strobe_width_high_us * (u64)ext_freq + + 1000000 - 1), 1000000ULL); + strobe_adjustment = (tmp + (1 << 16) - 1 - 1) / ((1 << 16) - 1); + strobe_width_high_rs = (tmp + strobe_adjustment - 1) / + strobe_adjustment; + + rval = ccs_write(sensor, FLASH_MODE_RS, strobe_setup->mode); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, FLASH_STROBE_ADJUSTMENT, strobe_adjustment); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, TFLASH_STROBE_WIDTH_HIGH_RS_CTRL, + strobe_width_high_rs); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, TFLASH_STROBE_DELAY_RS_CTRL, + strobe_setup->strobe_delay); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, FLASH_STROBE_START_POINT, + strobe_setup->stobe_start_point); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, FLASH_TRIGGER_RS, strobe_setup->trigger); + +out: + sensor->hwcfg->strobe_setup->trigger = 0; + + return rval; +} + +/* ----------------------------------------------------------------------------- + * Power management + */ + +static int ccs_power_on(struct device *dev) +{ + struct v4l2_subdev *subdev = dev_get_drvdata(dev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + /* + * The sub-device related to the I2C device is always the + * source one, i.e. ssds[0]. + */ + struct ccs_sensor *sensor = + container_of(ssd, struct ccs_sensor, ssds[0]); + unsigned int sleep; + int rval; + + rval = regulator_enable(sensor->vana); + if (rval) { + dev_err(dev, "failed to enable vana regulator\n"); + return rval; + } + usleep_range(1000, 1000); + + rval = clk_prepare_enable(sensor->ext_clk); + if (rval < 0) { + dev_dbg(dev, "failed to enable xclk\n"); + goto out_xclk_fail; + } + usleep_range(1000, 1000); + + gpiod_set_value(sensor->xshutdown, 1); + + sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk); + usleep_range(sleep, sleep); + + /* + * Failures to respond to the address change command have been noticed. + * Those failures seem to be caused by the sensor requiring a longer + * boot time than advertised. An additional 10ms delay seems to work + * around the issue, but the SMIA++ I2C write retry hack makes the delay + * unnecessary. The failures need to be investigated to find a proper + * fix, and a delay will likely need to be added here if the I2C write + * retry hack is reverted before the root cause of the boot time issue + * is found. + */ + + if (sensor->hwcfg->i2c_addr_alt) { + rval = ccs_change_cci_addr(sensor); + if (rval) { + dev_err(dev, "cci address change error\n"); + goto out_cci_addr_fail; + } + } + + rval = ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON); + if (rval < 0) { + dev_err(dev, "software reset failed\n"); + goto out_cci_addr_fail; + } + + if (sensor->hwcfg->i2c_addr_alt) { + rval = ccs_change_cci_addr(sensor); + if (rval) { + dev_err(dev, "cci address change error\n"); + goto out_cci_addr_fail; + } + } + + rval = ccs_write(sensor, COMPRESSION_MODE, + CCS_COMPRESSION_MODE_DPCM_PCM_SIMPLE); + if (rval) { + dev_err(dev, "compression mode set failed\n"); + goto out_cci_addr_fail; + } + + rval = ccs_write(sensor, EXTCLK_FREQUENCY_MHZ, + sensor->hwcfg->ext_clk / (1000000 / (1 << 8))); + if (rval) { + dev_err(dev, "extclk frequency set failed\n"); + goto out_cci_addr_fail; + } + + rval = ccs_write(sensor, CSI_LANE_MODE, sensor->hwcfg->lanes - 1); + if (rval) { + dev_err(dev, "csi lane mode set failed\n"); + goto out_cci_addr_fail; + } + + rval = ccs_write(sensor, FAST_STANDBY_CTRL, + CCS_FAST_STANDBY_CTRL_FRAME_TRUNCATION); + if (rval) { + dev_err(dev, "fast standby set failed\n"); + goto out_cci_addr_fail; + } + + rval = ccs_write(sensor, CSI_SIGNALING_MODE, + sensor->hwcfg->csi_signalling_mode); + if (rval) { + dev_err(dev, "csi signalling mode set failed\n"); + goto out_cci_addr_fail; + } + + /* DPHY control done by sensor based on requested link rate */ + rval = ccs_write(sensor, PHY_CTRL, CCS_PHY_CTRL_UI); + if (rval < 0) + goto out_cci_addr_fail; + + rval = ccs_call_quirk(sensor, post_poweron); + if (rval) { + dev_err(dev, "post_poweron quirks failed\n"); + goto out_cci_addr_fail; + } + + return 0; + +out_cci_addr_fail: + gpiod_set_value(sensor->xshutdown, 0); + clk_disable_unprepare(sensor->ext_clk); + +out_xclk_fail: + regulator_disable(sensor->vana); + + return rval; +} + +static int ccs_power_off(struct device *dev) +{ + struct v4l2_subdev *subdev = dev_get_drvdata(dev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct ccs_sensor *sensor = + container_of(ssd, struct ccs_sensor, ssds[0]); + + /* + * Currently power/clock to lens are enable/disabled separately + * but they are essentially the same signals. So if the sensor is + * powered off while the lens is powered on the sensor does not + * really see a power off and next time the cci address change + * will fail. So do a soft reset explicitly here. + */ + if (sensor->hwcfg->i2c_addr_alt) + ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON); + + gpiod_set_value(sensor->xshutdown, 0); + clk_disable_unprepare(sensor->ext_clk); + usleep_range(5000, 5000); + regulator_disable(sensor->vana); + sensor->streaming = false; + + return 0; +} + +/* ----------------------------------------------------------------------------- + * Video stream management + */ + +static int ccs_start_streaming(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + unsigned int binning_mode; + int rval; + + mutex_lock(&sensor->mutex); + + rval = ccs_write(sensor, CSI_DATA_FORMAT, + (sensor->csi_format->width << 8) | + sensor->csi_format->compressed); + if (rval) + goto out; + + /* Binning configuration */ + if (sensor->binning_horizontal == 1 && + sensor->binning_vertical == 1) { + binning_mode = 0; + } else { + u8 binning_type = + (sensor->binning_horizontal << 4) + | sensor->binning_vertical; + + rval = ccs_write(sensor, BINNING_TYPE, binning_type); + if (rval < 0) + goto out; + + binning_mode = 1; + } + rval = ccs_write(sensor, BINNING_MODE, binning_mode); + if (rval < 0) + goto out; + + /* Set up PLL */ + rval = ccs_pll_configure(sensor); + if (rval) + goto out; + + /* Analog crop start coordinates */ + rval = ccs_write(sensor, X_ADDR_START, + sensor->pixel_array->crop[CCS_PA_PAD_SRC].left); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, Y_ADDR_START, + sensor->pixel_array->crop[CCS_PA_PAD_SRC].top); + if (rval < 0) + goto out; + + /* Analog crop end coordinates */ + rval = ccs_write( + sensor, X_ADDR_END, + sensor->pixel_array->crop[CCS_PA_PAD_SRC].left + + sensor->pixel_array->crop[CCS_PA_PAD_SRC].width - 1); + if (rval < 0) + goto out; + + rval = ccs_write( + sensor, Y_ADDR_END, + sensor->pixel_array->crop[CCS_PA_PAD_SRC].top + + sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - 1); + if (rval < 0) + goto out; + + /* + * Output from pixel array, including blanking, is set using + * controls below. No need to set here. + */ + + /* Digital crop */ + if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) + == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { + rval = ccs_write( + sensor, DIGITAL_CROP_X_OFFSET, + sensor->scaler->crop[CCS_PAD_SINK].left); + if (rval < 0) + goto out; + + rval = ccs_write( + sensor, DIGITAL_CROP_Y_OFFSET, + sensor->scaler->crop[CCS_PAD_SINK].top); + if (rval < 0) + goto out; + + rval = ccs_write( + sensor, DIGITAL_CROP_IMAGE_WIDTH, + sensor->scaler->crop[CCS_PAD_SINK].width); + if (rval < 0) + goto out; + + rval = ccs_write( + sensor, DIGITAL_CROP_IMAGE_HEIGHT, + sensor->scaler->crop[CCS_PAD_SINK].height); + if (rval < 0) + goto out; + } + + /* Scaling */ + if (CCS_LIM(sensor, SCALING_CAPABILITY) + != CCS_SCALING_CAPABILITY_NONE) { + rval = ccs_write(sensor, SCALING_MODE, sensor->scaling_mode); + if (rval < 0) + goto out; + + rval = ccs_write(sensor, SCALE_M, sensor->scale_m); + if (rval < 0) + goto out; + } + + /* Output size from sensor */ + rval = ccs_write(sensor, X_OUTPUT_SIZE, + sensor->src->crop[CCS_PAD_SRC].width); + if (rval < 0) + goto out; + rval = ccs_write(sensor, Y_OUTPUT_SIZE, + sensor->src->crop[CCS_PAD_SRC].height); + if (rval < 0) + goto out; + + if (CCS_LIM(sensor, FLASH_MODE_CAPABILITY) & + (CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE | + SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE) && + sensor->hwcfg->strobe_setup != NULL && + sensor->hwcfg->strobe_setup->trigger != 0) { + rval = ccs_setup_flash_strobe(sensor); + if (rval) + goto out; + } + + rval = ccs_call_quirk(sensor, pre_streamon); + if (rval) { + dev_err(&client->dev, "pre_streamon quirks failed\n"); + goto out; + } + + rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_STREAMING); + +out: + mutex_unlock(&sensor->mutex); + + return rval; +} + +static int ccs_stop_streaming(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + mutex_lock(&sensor->mutex); + rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_SOFTWARE_STANDBY); + if (rval) + goto out; + + rval = ccs_call_quirk(sensor, post_streamoff); + if (rval) + dev_err(&client->dev, "post_streamoff quirks failed\n"); + +out: + mutex_unlock(&sensor->mutex); + return rval; +} + +/* ----------------------------------------------------------------------------- + * V4L2 subdev video operations + */ + +static int ccs_pm_get_init(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + rval = pm_runtime_get_sync(&client->dev); + if (rval < 0) { + if (rval != -EBUSY && rval != -EAGAIN) + pm_runtime_set_active(&client->dev); + pm_runtime_put_noidle(&client->dev); + + return rval; + } else if (!rval) { + rval = v4l2_ctrl_handler_setup(&sensor->pixel_array-> + ctrl_handler); + if (rval) + return rval; + + return v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); + } + + return 0; +} + +static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + if (sensor->streaming == enable) + return 0; + + if (!enable) { + ccs_stop_streaming(sensor); + sensor->streaming = false; + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + + return 0; + } + + rval = ccs_pm_get_init(sensor); + if (rval) + return rval; + + sensor->streaming = true; + + rval = ccs_start_streaming(sensor); + if (rval < 0) { + sensor->streaming = false; + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + } + + return rval; +} + +static int ccs_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + unsigned int i; + int idx = -1; + int rval = -EINVAL; + + mutex_lock(&sensor->mutex); + + dev_err(&client->dev, "subdev %s, pad %d, index %d\n", + subdev->name, code->pad, code->index); + + if (subdev != &sensor->src->sd || code->pad != CCS_PAD_SRC) { + if (code->index) + goto out; + + code->code = sensor->internal_csi_format->code; + rval = 0; + goto out; + } + + for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { + if (sensor->mbus_frame_fmts & (1 << i)) + idx++; + + if (idx == code->index) { + code->code = ccs_csi_data_formats[i].code; + dev_err(&client->dev, "found index %d, i %d, code %x\n", + code->index, i, code->code); + rval = 0; + break; + } + } + +out: + mutex_unlock(&sensor->mutex); + + return rval; +} + +static u32 __ccs_get_mbus_code(struct v4l2_subdev *subdev, unsigned int pad) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + + if (subdev == &sensor->src->sd && pad == CCS_PAD_SRC) + return sensor->csi_format->code; + else + return sensor->internal_csi_format->code; +} + +static int __ccs_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + fmt->format = *v4l2_subdev_get_try_format(subdev, cfg, + fmt->pad); + } else { + struct v4l2_rect *r; + + if (fmt->pad == ssd->source_pad) + r = &ssd->crop[ssd->source_pad]; + else + r = &ssd->sink_fmt; + + fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); + fmt->format.width = r->width; + fmt->format.height = r->height; + fmt->format.field = V4L2_FIELD_NONE; + } + + return 0; +} + +static int ccs_get_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int rval; + + mutex_lock(&sensor->mutex); + rval = __ccs_get_format(subdev, cfg, fmt); + mutex_unlock(&sensor->mutex); + + return rval; +} + +static void ccs_get_crop_compose(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_rect **crops, + struct v4l2_rect **comps, int which) +{ + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + unsigned int i; + + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (crops) + for (i = 0; i < subdev->entity.num_pads; i++) + crops[i] = &ssd->crop[i]; + if (comps) + *comps = &ssd->compose; + } else { + if (crops) { + for (i = 0; i < subdev->entity.num_pads; i++) { + crops[i] = v4l2_subdev_get_try_crop(subdev, cfg, i); + BUG_ON(!crops[i]); + } + } + if (comps) { + *comps = v4l2_subdev_get_try_compose(subdev, cfg, + CCS_PAD_SINK); + BUG_ON(!*comps); + } + } +} + +/* Changes require propagation only on sink pad. */ +static void ccs_propagate(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, int which, + int target) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct v4l2_rect *comp, *crops[CCS_PADS]; + + ccs_get_crop_compose(subdev, cfg, crops, &comp, which); + + switch (target) { + case V4L2_SEL_TGT_CROP: + comp->width = crops[CCS_PAD_SINK]->width; + comp->height = crops[CCS_PAD_SINK]->height; + if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (ssd == sensor->scaler) { + sensor->scale_m = + CCS_LIM(sensor, SCALER_N_MIN); + sensor->scaling_mode = + CCS_SCALING_MODE_NO_SCALING; + } else if (ssd == sensor->binner) { + sensor->binning_horizontal = 1; + sensor->binning_vertical = 1; + } + } + fallthrough; + case V4L2_SEL_TGT_COMPOSE: + *crops[CCS_PAD_SRC] = *comp; + break; + default: + BUG(); + } +} + +static const struct ccs_csi_data_format +*ccs_validate_csi_data_format(struct ccs_sensor *sensor, u32 code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { + if (sensor->mbus_frame_fmts & (1 << i) && + ccs_csi_data_formats[i].code == code) + return &ccs_csi_data_formats[i]; + } + + return sensor->csi_format; +} + +static int ccs_set_format_source(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + const struct ccs_csi_data_format *csi_format, + *old_csi_format = sensor->csi_format; + unsigned long *valid_link_freqs; + u32 code = fmt->format.code; + unsigned int i; + int rval; + + rval = __ccs_get_format(subdev, cfg, fmt); + if (rval) + return rval; + + /* + * Media bus code is changeable on src subdev's source pad. On + * other source pads we just get format here. + */ + if (subdev != &sensor->src->sd) + return 0; + + csi_format = ccs_validate_csi_data_format(sensor, code); + + fmt->format.code = csi_format->code; + + if (fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return 0; + + sensor->csi_format = csi_format; + + if (csi_format->width != old_csi_format->width) + for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) + __v4l2_ctrl_modify_range( + sensor->test_data[i], 0, + (1 << csi_format->width) - 1, 1, 0); + + if (csi_format->compressed == old_csi_format->compressed) + return 0; + + valid_link_freqs = + &sensor->valid_link_freqs[sensor->csi_format->compressed + - sensor->compressed_min_bpp]; + + __v4l2_ctrl_modify_range( + sensor->link_freq, 0, + __fls(*valid_link_freqs), ~*valid_link_freqs, + __ffs(*valid_link_freqs)); + + return ccs_pll_update(sensor); +} + +static int ccs_set_format(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct v4l2_rect *crops[CCS_PADS]; + + mutex_lock(&sensor->mutex); + + if (fmt->pad == ssd->source_pad) { + int rval; + + rval = ccs_set_format_source(subdev, cfg, fmt); + + mutex_unlock(&sensor->mutex); + + return rval; + } + + /* Sink pad. Width and height are changeable here. */ + fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); + fmt->format.width &= ~1; + fmt->format.height &= ~1; + fmt->format.field = V4L2_FIELD_NONE; + + fmt->format.width = + clamp(fmt->format.width, + CCS_LIM(sensor, MIN_X_OUTPUT_SIZE), + CCS_LIM(sensor, MAX_X_OUTPUT_SIZE)); + fmt->format.height = + clamp(fmt->format.height, + CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), + CCS_LIM(sensor, MAX_Y_OUTPUT_SIZE)); + + ccs_get_crop_compose(subdev, cfg, crops, NULL, fmt->which); + + crops[ssd->sink_pad]->left = 0; + crops[ssd->sink_pad]->top = 0; + crops[ssd->sink_pad]->width = fmt->format.width; + crops[ssd->sink_pad]->height = fmt->format.height; + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) + ssd->sink_fmt = *crops[ssd->sink_pad]; + ccs_propagate(subdev, cfg, fmt->which, V4L2_SEL_TGT_CROP); + + mutex_unlock(&sensor->mutex); + + return 0; +} + +/* + * Calculate goodness of scaled image size compared to expected image + * size and flags provided. + */ +#define SCALING_GOODNESS 100000 +#define SCALING_GOODNESS_EXTREME 100000000 +static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w, + int h, int ask_h, u32 flags) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct i2c_client *client = v4l2_get_subdevdata(subdev); + int val = 0; + + w &= ~1; + ask_w &= ~1; + h &= ~1; + ask_h &= ~1; + + if (flags & V4L2_SEL_FLAG_GE) { + if (w < ask_w) + val -= SCALING_GOODNESS; + if (h < ask_h) + val -= SCALING_GOODNESS; + } + + if (flags & V4L2_SEL_FLAG_LE) { + if (w > ask_w) + val -= SCALING_GOODNESS; + if (h > ask_h) + val -= SCALING_GOODNESS; + } + + val -= abs(w - ask_w); + val -= abs(h - ask_h); + + if (w < CCS_LIM(sensor, MIN_X_OUTPUT_SIZE)) + val -= SCALING_GOODNESS_EXTREME; + + dev_dbg(&client->dev, "w %d ask_w %d h %d ask_h %d goodness %d\n", + w, ask_w, h, ask_h, val); + + return val; +} + +static void ccs_set_compose_binner(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel, + struct v4l2_rect **crops, + struct v4l2_rect *comp) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + unsigned int i; + unsigned int binh = 1, binv = 1; + int best = scaling_goodness( + subdev, + crops[CCS_PAD_SINK]->width, sel->r.width, + crops[CCS_PAD_SINK]->height, sel->r.height, sel->flags); + + for (i = 0; i < sensor->nbinning_subtypes; i++) { + int this = scaling_goodness( + subdev, + crops[CCS_PAD_SINK]->width + / sensor->binning_subtypes[i].horizontal, + sel->r.width, + crops[CCS_PAD_SINK]->height + / sensor->binning_subtypes[i].vertical, + sel->r.height, sel->flags); + + if (this > best) { + binh = sensor->binning_subtypes[i].horizontal; + binv = sensor->binning_subtypes[i].vertical; + best = this; + } + } + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + sensor->binning_vertical = binv; + sensor->binning_horizontal = binh; + } + + sel->r.width = (crops[CCS_PAD_SINK]->width / binh) & ~1; + sel->r.height = (crops[CCS_PAD_SINK]->height / binv) & ~1; +} + +/* + * Calculate best scaling ratio and mode for given output resolution. + * + * Try all of these: horizontal ratio, vertical ratio and smallest + * size possible (horizontally). + * + * Also try whether horizontal scaler or full scaler gives a better + * result. + */ +static void ccs_set_compose_scaler(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel, + struct v4l2_rect **crops, + struct v4l2_rect *comp) +{ + struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + u32 min, max, a, b, max_m; + u32 scale_m = CCS_LIM(sensor, SCALER_N_MIN); + int mode = CCS_SCALING_MODE_HORIZONTAL; + u32 try[4]; + u32 ntry = 0; + unsigned int i; + int best = INT_MIN; + + sel->r.width = min_t(unsigned int, sel->r.width, + crops[CCS_PAD_SINK]->width); + sel->r.height = min_t(unsigned int, sel->r.height, + crops[CCS_PAD_SINK]->height); + + a = crops[CCS_PAD_SINK]->width + * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.width; + b = crops[CCS_PAD_SINK]->height + * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.height; + max_m = crops[CCS_PAD_SINK]->width + * CCS_LIM(sensor, SCALER_N_MIN) + / CCS_LIM(sensor, MIN_X_OUTPUT_SIZE); + + a = clamp(a, CCS_LIM(sensor, SCALER_M_MIN), + CCS_LIM(sensor, SCALER_M_MAX)); + b = clamp(b, CCS_LIM(sensor, SCALER_M_MIN), + CCS_LIM(sensor, SCALER_M_MAX)); + max_m = clamp(max_m, CCS_LIM(sensor, SCALER_M_MIN), + CCS_LIM(sensor, SCALER_M_MAX)); + + dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); + + min = min(max_m, min(a, b)); + max = min(max_m, max(a, b)); + + try[ntry] = min; + ntry++; + if (min != max) { + try[ntry] = max; + ntry++; + } + if (max != max_m) { + try[ntry] = min + 1; + ntry++; + if (min != max) { + try[ntry] = max + 1; + ntry++; + } + } + + for (i = 0; i < ntry; i++) { + int this = scaling_goodness( + subdev, + crops[CCS_PAD_SINK]->width + / try[i] * CCS_LIM(sensor, SCALER_N_MIN), + sel->r.width, + crops[CCS_PAD_SINK]->height, + sel->r.height, + sel->flags); + + dev_dbg(&client->dev, "trying factor %d (%d)\n", try[i], i); + + if (this > best) { + scale_m = try[i]; + mode = CCS_SCALING_MODE_HORIZONTAL; + best = this; + } + + if (CCS_LIM(sensor, SCALING_CAPABILITY) + == CCS_SCALING_CAPABILITY_HORIZONTAL) + continue; + + this = scaling_goodness( + subdev, crops[CCS_PAD_SINK]->width + / try[i] + * CCS_LIM(sensor, SCALER_N_MIN), + sel->r.width, + crops[CCS_PAD_SINK]->height + / try[i] + * CCS_LIM(sensor, SCALER_N_MIN), + sel->r.height, + sel->flags); + + if (this > best) { + scale_m = try[i]; + mode = SMIAPP_SCALING_MODE_BOTH; + best = this; + } + } + + sel->r.width = + (crops[CCS_PAD_SINK]->width + / scale_m + * CCS_LIM(sensor, SCALER_N_MIN)) & ~1; + if (mode == SMIAPP_SCALING_MODE_BOTH) + sel->r.height = + (crops[CCS_PAD_SINK]->height + / scale_m + * CCS_LIM(sensor, SCALER_N_MIN)) + & ~1; + else + sel->r.height = crops[CCS_PAD_SINK]->height; + + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + sensor->scale_m = scale_m; + sensor->scaling_mode = mode; + } +} +/* We're only called on source pads. This function sets scaling. */ +static int ccs_set_compose(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct v4l2_rect *comp, *crops[CCS_PADS]; + + ccs_get_crop_compose(subdev, cfg, crops, &comp, sel->which); + + sel->r.top = 0; + sel->r.left = 0; + + if (ssd == sensor->binner) + ccs_set_compose_binner(subdev, cfg, sel, crops, comp); + else + ccs_set_compose_scaler(subdev, cfg, sel, crops, comp); + + *comp = sel->r; + ccs_propagate(subdev, cfg, sel->which, V4L2_SEL_TGT_COMPOSE); + + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) + return ccs_pll_blanking_update(sensor); + + return 0; +} + +static int __ccs_sel_supported(struct v4l2_subdev *subdev, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + + /* We only implement crop in three places. */ + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP_BOUNDS: + if (ssd == sensor->pixel_array && sel->pad == CCS_PA_PAD_SRC) + return 0; + if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) + return 0; + if (ssd == sensor->scaler && sel->pad == CCS_PAD_SINK && + CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) + == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) + return 0; + return -EINVAL; + case V4L2_SEL_TGT_NATIVE_SIZE: + if (ssd == sensor->pixel_array && sel->pad == CCS_PA_PAD_SRC) + return 0; + return -EINVAL; + case V4L2_SEL_TGT_COMPOSE: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + if (sel->pad == ssd->source_pad) + return -EINVAL; + if (ssd == sensor->binner) + return 0; + if (ssd == sensor->scaler && CCS_LIM(sensor, SCALING_CAPABILITY) + != CCS_SCALING_CAPABILITY_NONE) + return 0; + fallthrough; + default: + return -EINVAL; + } +} + +static int ccs_set_crop(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct v4l2_rect *src_size, *crops[CCS_PADS]; + struct v4l2_rect _r; + + ccs_get_crop_compose(subdev, cfg, crops, NULL, sel->which); + + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + if (sel->pad == ssd->sink_pad) + src_size = &ssd->sink_fmt; + else + src_size = &ssd->compose; + } else { + if (sel->pad == ssd->sink_pad) { + _r.left = 0; + _r.top = 0; + _r.width = v4l2_subdev_get_try_format(subdev, cfg, sel->pad) + ->width; + _r.height = v4l2_subdev_get_try_format(subdev, cfg, sel->pad) + ->height; + src_size = &_r; + } else { + src_size = v4l2_subdev_get_try_compose( + subdev, cfg, ssd->sink_pad); + } + } + + if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) { + sel->r.left = 0; + sel->r.top = 0; + } + + sel->r.width = min(sel->r.width, src_size->width); + sel->r.height = min(sel->r.height, src_size->height); + + sel->r.left = min_t(int, sel->r.left, src_size->width - sel->r.width); + sel->r.top = min_t(int, sel->r.top, src_size->height - sel->r.height); + + *crops[sel->pad] = sel->r; + + if (ssd != sensor->pixel_array && sel->pad == CCS_PAD_SINK) + ccs_propagate(subdev, cfg, sel->which, V4L2_SEL_TGT_CROP); + + return 0; +} + +static void ccs_get_native_size(struct ccs_subdev *ssd, struct v4l2_rect *r) +{ + r->top = 0; + r->left = 0; + r->width = CCS_LIM(ssd->sensor, X_ADDR_MAX) + 1; + r->height = CCS_LIM(ssd->sensor, Y_ADDR_MAX) + 1; +} + +static int __ccs_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_subdev *ssd = to_ccs_subdev(subdev); + struct v4l2_rect *comp, *crops[CCS_PADS]; + struct v4l2_rect sink_fmt; + int ret; + + ret = __ccs_sel_supported(subdev, sel); + if (ret) + return ret; + + ccs_get_crop_compose(subdev, cfg, crops, &comp, sel->which); + + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + sink_fmt = ssd->sink_fmt; + } else { + struct v4l2_mbus_framefmt *fmt = + v4l2_subdev_get_try_format(subdev, cfg, ssd->sink_pad); + + sink_fmt.left = 0; + sink_fmt.top = 0; + sink_fmt.width = fmt->width; + sink_fmt.height = fmt->height; + } + + switch (sel->target) { + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_NATIVE_SIZE: + if (ssd == sensor->pixel_array) + ccs_get_native_size(ssd, &sel->r); + else if (sel->pad == ssd->sink_pad) + sel->r = sink_fmt; + else + sel->r = *comp; + break; + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + sel->r = *crops[sel->pad]; + break; + case V4L2_SEL_TGT_COMPOSE: + sel->r = *comp; + break; + } + + return 0; +} + +static int ccs_get_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int rval; + + mutex_lock(&sensor->mutex); + rval = __ccs_get_selection(subdev, cfg, sel); + mutex_unlock(&sensor->mutex); + + return rval; +} + +static int ccs_set_selection(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int ret; + + ret = __ccs_sel_supported(subdev, sel); + if (ret) + return ret; + + mutex_lock(&sensor->mutex); + + sel->r.left = max(0, sel->r.left & ~1); + sel->r.top = max(0, sel->r.top & ~1); + sel->r.width = CCS_ALIGN_DIM(sel->r.width, sel->flags); + sel->r.height = CCS_ALIGN_DIM(sel->r.height, sel->flags); + + sel->r.width = max_t(unsigned int, + CCS_LIM(sensor, MIN_X_OUTPUT_SIZE), + sel->r.width); + sel->r.height = max_t(unsigned int, + CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), + sel->r.height); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + ret = ccs_set_crop(subdev, cfg, sel); + break; + case V4L2_SEL_TGT_COMPOSE: + ret = ccs_set_compose(subdev, cfg, sel); + break; + default: + ret = -EINVAL; + } + + mutex_unlock(&sensor->mutex); + return ret; +} + +static int ccs_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + + *frames = sensor->frame_skip; + return 0; +} + +static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + + *lines = sensor->image_start; + + return 0; +} + +/* ----------------------------------------------------------------------------- + * sysfs attributes + */ + +static ssize_t +ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); + struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int rval; + + if (!sensor->dev_init_done) + return -EBUSY; + + rval = ccs_pm_get_init(sensor); + if (rval < 0) + return -ENODEV; + + rval = ccs_read_nvm(sensor, buf, PAGE_SIZE); + if (rval < 0) { + pm_runtime_put(&client->dev); + dev_err(&client->dev, "nvm read failed\n"); + return -ENODEV; + } + + pm_runtime_mark_last_busy(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + + /* + * NVM is still way below a PAGE_SIZE, so we can safely + * assume this for now. + */ + return rval; +} +static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL); + +static ssize_t +ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + struct ccs_module_info *minfo = &sensor->minfo; + + if (minfo->mipi_manufacturer_id) + return snprintf(buf, PAGE_SIZE, "%4.4x%4.4x%2.2x\n", + minfo->mipi_manufacturer_id, minfo->model_id, + minfo->revision_number_major) + 1; + else + return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n", + minfo->smia_manufacturer_id, minfo->model_id, + minfo->revision_number_major) + 1; +} + +static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL); + +/* ----------------------------------------------------------------------------- + * V4L2 subdev core operations + */ + +static int ccs_identify_module(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct ccs_module_info *minfo = &sensor->minfo; + unsigned int i; + int rval = 0; + + /* Module info */ + rval = ccs_read(sensor, MODULE_MANUFACTURER_ID, + &minfo->mipi_manufacturer_id); + if (!rval && !minfo->mipi_manufacturer_id) + rval = ccs_read_addr_8only(sensor, + SMIAPP_REG_U8_MANUFACTURER_ID, + &minfo->smia_manufacturer_id); + if (!rval) + rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_MODEL_ID, + &minfo->model_id); + if (!rval) + rval = ccs_read_addr_8only(sensor, + CCS_R_MODULE_REVISION_NUMBER_MAJOR, + &minfo->revision_number_major); + if (!rval) + rval = ccs_read_addr_8only(sensor, + CCS_R_MODULE_REVISION_NUMBER_MINOR, + &minfo->revision_number_minor); + if (!rval) + rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_YEAR, + &minfo->module_year); + if (!rval) + rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_MONTH, + &minfo->module_month); + if (!rval) + rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_DAY, + &minfo->module_day); + + /* Sensor info */ + if (!rval) + rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID, + &minfo->sensor_mipi_manufacturer_id); + if (!rval && !minfo->sensor_mipi_manufacturer_id) + rval = ccs_read_addr_8only(sensor, + CCS_R_SENSOR_MANUFACTURER_ID, + &minfo->sensor_smia_manufacturer_id); + if (!rval) + rval = ccs_read_addr_8only(sensor, + CCS_R_SENSOR_MODEL_ID, + &minfo->sensor_model_id); + if (!rval) + rval = ccs_read_addr_8only(sensor, + CCS_R_SENSOR_REVISION_NUMBER, + &minfo->sensor_revision_number); + if (!rval) + rval = ccs_read_addr_8only(sensor, + CCS_R_SENSOR_FIRMWARE_VERSION, + &minfo->sensor_firmware_version); + + /* SMIA */ + if (!rval) + rval = ccs_read(sensor, MIPI_CCS_VERSION, &minfo->ccs_version); + if (!rval && !minfo->ccs_version) + rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIA_VERSION, + &minfo->smia_version); + if (!rval && !minfo->ccs_version) + rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIAPP_VERSION, + &minfo->smiapp_version); + + if (rval) { + dev_err(&client->dev, "sensor detection failed\n"); + return -ENODEV; + } + + if (minfo->mipi_manufacturer_id) + dev_dbg(&client->dev, "MIPI CCS module 0x%4.4x-0x%4.4x\n", + minfo->mipi_manufacturer_id, minfo->model_id); + else + dev_dbg(&client->dev, "SMIA module 0x%2.2x-0x%4.4x\n", + minfo->smia_manufacturer_id, minfo->model_id); + + dev_dbg(&client->dev, + "module revision 0x%2.2x-0x%2.2x date %2.2d-%2.2d-%2.2d\n", + minfo->revision_number_major, minfo->revision_number_minor, + minfo->module_year, minfo->module_month, minfo->module_day); + + if (minfo->sensor_mipi_manufacturer_id) + dev_dbg(&client->dev, "MIPI CCS sensor 0x%4.4x-0x%4.4x\n", + minfo->sensor_mipi_manufacturer_id, + minfo->sensor_model_id); + else + dev_dbg(&client->dev, "SMIA sensor 0x%2.2x-0x%4.4x\n", + minfo->sensor_smia_manufacturer_id, + minfo->sensor_model_id); + + dev_dbg(&client->dev, + "sensor revision 0x%2.2x firmware version 0x%2.2x\n", + minfo->sensor_revision_number, minfo->sensor_firmware_version); + + if (minfo->ccs_version) { + dev_dbg(&client->dev, "MIPI CCS version %u.%u", + (minfo->ccs_version & CCS_MIPI_CCS_VERSION_MAJOR_MASK) + >> CCS_MIPI_CCS_VERSION_MAJOR_SHIFT, + (minfo->ccs_version & CCS_MIPI_CCS_VERSION_MINOR_MASK)); + minfo->name = CCS_NAME; + } else { + dev_dbg(&client->dev, + "smia version %2.2d smiapp version %2.2d\n", + minfo->smia_version, minfo->smiapp_version); + minfo->name = SMIAPP_NAME; + } + + /* + * Some modules have bad data in the lvalues below. Hope the + * rvalues have better stuff. The lvalues are module + * parameters whereas the rvalues are sensor parameters. + */ + if (minfo->sensor_smia_manufacturer_id && + !minfo->smia_manufacturer_id && !minfo->model_id) { + minfo->smia_manufacturer_id = + minfo->sensor_smia_manufacturer_id; + minfo->model_id = minfo->sensor_model_id; + minfo->revision_number_major = minfo->sensor_revision_number; + } + + for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) { + if (ccs_module_idents[i].mipi_manufacturer_id && + ccs_module_idents[i].mipi_manufacturer_id + != minfo->mipi_manufacturer_id) + continue; + if (ccs_module_idents[i].smia_manufacturer_id && + ccs_module_idents[i].smia_manufacturer_id + != minfo->smia_manufacturer_id) + continue; + if (ccs_module_idents[i].model_id != minfo->model_id) + continue; + if (ccs_module_idents[i].flags + & CCS_MODULE_IDENT_FLAG_REV_LE) { + if (ccs_module_idents[i].revision_number_major + < minfo->revision_number_major) + continue; + } else { + if (ccs_module_idents[i].revision_number_major + != minfo->revision_number_major) + continue; + } + + minfo->name = ccs_module_idents[i].name; + minfo->quirk = ccs_module_idents[i].quirk; + break; + } + + if (i >= ARRAY_SIZE(ccs_module_idents)) + dev_warn(&client->dev, + "no quirks for this module; let's hope it's fully compliant\n"); + + dev_dbg(&client->dev, "the sensor is called %s\n", + minfo->name); + + return 0; +} + +static const struct v4l2_subdev_ops ccs_ops; +static const struct v4l2_subdev_internal_ops ccs_internal_ops; +static const struct media_entity_operations ccs_entity_ops; + +static int ccs_register_subdev(struct ccs_sensor *sensor, + struct ccs_subdev *ssd, + struct ccs_subdev *sink_ssd, + u16 source_pad, u16 sink_pad, u32 link_flags) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + if (!sink_ssd) + return 0; + + rval = media_entity_pads_init(&ssd->sd.entity, + ssd->npads, ssd->pads); + if (rval) { + dev_err(&client->dev, + "media_entity_pads_init failed\n"); + return rval; + } + + rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, + &ssd->sd); + if (rval) { + dev_err(&client->dev, + "v4l2_device_register_subdev failed\n"); + return rval; + } + + rval = media_create_pad_link(&ssd->sd.entity, source_pad, + &sink_ssd->sd.entity, sink_pad, + link_flags); + if (rval) { + dev_err(&client->dev, + "media_create_pad_link failed\n"); + v4l2_device_unregister_subdev(&ssd->sd); + return rval; + } + + return 0; +} + +static void ccs_unregistered(struct v4l2_subdev *subdev) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + unsigned int i; + + for (i = 1; i < sensor->ssds_used; i++) + v4l2_device_unregister_subdev(&sensor->ssds[i].sd); +} + +static int ccs_registered(struct v4l2_subdev *subdev) +{ + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int rval; + + if (sensor->scaler) { + rval = ccs_register_subdev(sensor, sensor->binner, + sensor->scaler, + CCS_PAD_SRC, CCS_PAD_SINK, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (rval < 0) + return rval; + } + + rval = ccs_register_subdev(sensor, sensor->pixel_array, sensor->binner, + CCS_PA_PAD_SRC, CCS_PAD_SINK, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (rval) + goto out_err; + + return 0; + +out_err: + ccs_unregistered(subdev); + + return rval; +} + +static void ccs_cleanup(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + + device_remove_file(&client->dev, &dev_attr_nvm); + device_remove_file(&client->dev, &dev_attr_ident); + + ccs_free_controls(sensor); +} + +static void ccs_create_subdev(struct ccs_sensor *sensor, + struct ccs_subdev *ssd, const char *name, + unsigned short num_pads) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + + if (!ssd) + return; + + if (ssd != sensor->src) + v4l2_subdev_init(&ssd->sd, &ccs_ops); + + ssd->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ssd->sensor = sensor; + + ssd->npads = num_pads; + ssd->source_pad = num_pads - 1; + + v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name); + + ccs_get_native_size(ssd, &ssd->sink_fmt); + + ssd->compose.width = ssd->sink_fmt.width; + ssd->compose.height = ssd->sink_fmt.height; + ssd->crop[ssd->source_pad] = ssd->compose; + ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE; + if (ssd != sensor->pixel_array) { + ssd->crop[ssd->sink_pad] = ssd->compose; + ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK; + } + + ssd->sd.entity.ops = &ccs_entity_ops; + + if (ssd == sensor->src) + return; + + ssd->sd.internal_ops = &ccs_internal_ops; + ssd->sd.owner = THIS_MODULE; + ssd->sd.dev = &client->dev; + v4l2_set_subdevdata(&ssd->sd, client); +} + +static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct ccs_subdev *ssd = to_ccs_subdev(sd); + struct ccs_sensor *sensor = ssd->sensor; + unsigned int i; + + mutex_lock(&sensor->mutex); + + for (i = 0; i < ssd->npads; i++) { + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, i); + struct v4l2_rect *try_crop = + v4l2_subdev_get_try_crop(sd, fh->pad, i); + struct v4l2_rect *try_comp; + + ccs_get_native_size(ssd, try_crop); + + try_fmt->width = try_crop->width; + try_fmt->height = try_crop->height; + try_fmt->code = sensor->internal_csi_format->code; + try_fmt->field = V4L2_FIELD_NONE; + + if (ssd != sensor->pixel_array) + continue; + + try_comp = v4l2_subdev_get_try_compose(sd, fh->pad, i); + *try_comp = *try_crop; + } + + mutex_unlock(&sensor->mutex); + + return 0; +} + +static const struct v4l2_subdev_video_ops ccs_video_ops = { + .s_stream = ccs_set_stream, +}; + +static const struct v4l2_subdev_pad_ops ccs_pad_ops = { + .enum_mbus_code = ccs_enum_mbus_code, + .get_fmt = ccs_get_format, + .set_fmt = ccs_set_format, + .get_selection = ccs_get_selection, + .set_selection = ccs_set_selection, +}; + +static const struct v4l2_subdev_sensor_ops ccs_sensor_ops = { + .g_skip_frames = ccs_get_skip_frames, + .g_skip_top_lines = ccs_get_skip_top_lines, +}; + +static const struct v4l2_subdev_ops ccs_ops = { + .video = &ccs_video_ops, + .pad = &ccs_pad_ops, + .sensor = &ccs_sensor_ops, +}; + +static const struct media_entity_operations ccs_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { + .registered = ccs_registered, + .unregistered = ccs_unregistered, + .open = ccs_open, +}; + +static const struct v4l2_subdev_internal_ops ccs_internal_ops = { + .open = ccs_open, +}; + +/* ----------------------------------------------------------------------------- + * I2C Driver + */ + +static int __maybe_unused ccs_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + bool streaming = sensor->streaming; + int rval; + + rval = pm_runtime_get_sync(dev); + if (rval < 0) { + if (rval != -EBUSY && rval != -EAGAIN) + pm_runtime_set_active(&client->dev); + pm_runtime_put(dev); + return -EAGAIN; + } + + if (sensor->streaming) + ccs_stop_streaming(sensor); + + /* save state for resume */ + sensor->streaming = streaming; + + return 0; +} + +static int __maybe_unused ccs_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + int rval = 0; + + pm_runtime_put(dev); + + if (sensor->streaming) + rval = ccs_start_streaming(sensor); + + return rval; +} + +static struct ccs_hwconfig *ccs_get_hwconfig(struct device *dev) +{ + struct ccs_hwconfig *hwcfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); + u32 rotation; + int i; + int rval; + + if (!fwnode) + return dev->platform_data; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return NULL; + + bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY; + rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + if (rval == -ENXIO) { + bus_cfg = (struct v4l2_fwnode_endpoint) + { .bus_type = V4L2_MBUS_CCP2 }; + rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + } + if (rval) + goto out_err; + + hwcfg = devm_kzalloc(dev, sizeof(*hwcfg), GFP_KERNEL); + if (!hwcfg) + goto out_err; + + switch (bus_cfg.bus_type) { + case V4L2_MBUS_CSI2_DPHY: + hwcfg->csi_signalling_mode = CCS_CSI_SIGNALING_MODE_CSI_2_DPHY; + hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + break; + case V4L2_MBUS_CCP2: + hwcfg->csi_signalling_mode = (bus_cfg.bus.mipi_csi1.strobe) ? + SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE : + SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK; + hwcfg->lanes = 1; + break; + default: + dev_err(dev, "unsupported bus %u\n", bus_cfg.bus_type); + goto out_err; + } + + dev_dbg(dev, "lanes %u\n", hwcfg->lanes); + + rval = fwnode_property_read_u32(fwnode, "rotation", &rotation); + if (!rval) { + switch (rotation) { + case 180: + hwcfg->module_board_orient = + CCS_MODULE_BOARD_ORIENT_180; + fallthrough; + case 0: + break; + default: + dev_err(dev, "invalid rotation %u\n", rotation); + goto out_err; + } + } + + rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", + &hwcfg->ext_clk); + if (rval) + dev_info(dev, "can't get clock-frequency\n"); + + dev_dbg(dev, "clk %d, mode %d\n", hwcfg->ext_clk, + hwcfg->csi_signalling_mode); + + if (!bus_cfg.nr_of_link_frequencies) { + dev_warn(dev, "no link frequencies defined\n"); + goto out_err; + } + + hwcfg->op_sys_clock = devm_kcalloc( + dev, bus_cfg.nr_of_link_frequencies + 1 /* guardian */, + sizeof(*hwcfg->op_sys_clock), GFP_KERNEL); + if (!hwcfg->op_sys_clock) + goto out_err; + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i]; + dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]); + } + + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return hwcfg; + +out_err: + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return NULL; +} + +static int ccs_probe(struct i2c_client *client) +{ + struct ccs_sensor *sensor; + struct ccs_hwconfig *hwcfg = ccs_get_hwconfig(&client->dev); + unsigned int i; + int rval; + + if (hwcfg == NULL) + return -ENODEV; + + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); + if (sensor == NULL) + return -ENOMEM; + + sensor->hwcfg = hwcfg; + sensor->src = &sensor->ssds[sensor->ssds_used]; + + v4l2_i2c_subdev_init(&sensor->src->sd, client, &ccs_ops); + sensor->src->sd.internal_ops = &ccs_internal_src_ops; + + sensor->vana = devm_regulator_get(&client->dev, "vana"); + if (IS_ERR(sensor->vana)) { + dev_err(&client->dev, "could not get regulator for vana\n"); + return PTR_ERR(sensor->vana); + } + + sensor->ext_clk = devm_clk_get(&client->dev, NULL); + if (PTR_ERR(sensor->ext_clk) == -ENOENT) { + dev_info(&client->dev, "no clock defined, continuing...\n"); + sensor->ext_clk = NULL; + } else if (IS_ERR(sensor->ext_clk)) { + dev_err(&client->dev, "could not get clock (%ld)\n", + PTR_ERR(sensor->ext_clk)); + return -EPROBE_DEFER; + } + + if (sensor->ext_clk) { + if (sensor->hwcfg->ext_clk) { + unsigned long rate; + + rval = clk_set_rate(sensor->ext_clk, + sensor->hwcfg->ext_clk); + if (rval < 0) { + dev_err(&client->dev, + "unable to set clock freq to %u\n", + sensor->hwcfg->ext_clk); + return rval; + } + + rate = clk_get_rate(sensor->ext_clk); + if (rate != sensor->hwcfg->ext_clk) { + dev_err(&client->dev, + "can't set clock freq, asked for %u but got %lu\n", + sensor->hwcfg->ext_clk, rate); + return rval; + } + } else { + sensor->hwcfg->ext_clk = clk_get_rate(sensor->ext_clk); + dev_dbg(&client->dev, "obtained clock freq %u\n", + sensor->hwcfg->ext_clk); + } + } else if (sensor->hwcfg->ext_clk) { + dev_dbg(&client->dev, "assuming clock freq %u\n", + sensor->hwcfg->ext_clk); + } else { + dev_err(&client->dev, "unable to obtain clock freq\n"); + return -EINVAL; + } + + sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown", + GPIOD_OUT_LOW); + if (IS_ERR(sensor->xshutdown)) + return PTR_ERR(sensor->xshutdown); + + rval = ccs_power_on(&client->dev); + if (rval < 0) + return rval; + + mutex_init(&sensor->mutex); + + rval = ccs_identify_module(sensor); + if (rval) { + rval = -ENODEV; + goto out_power_off; + } + + rval = ccs_read_all_limits(sensor); + if (rval) + goto out_power_off; + + rval = ccs_read_frame_fmt(sensor); + if (rval) { + rval = -ENODEV; + goto out_free_ccs_limits; + } + + /* + * Handle Sensor Module orientation on the board. + * + * The application of H-FLIP and V-FLIP on the sensor is modified by + * the sensor orientation on the board. + * + * For CCS_BOARD_SENSOR_ORIENT_180 the default behaviour is to set + * both H-FLIP and V-FLIP for normal operation which also implies + * that a set/unset operation for user space HFLIP and VFLIP v4l2 + * controls will need to be internally inverted. + * + * Rotation also changes the bayer pattern. + */ + if (sensor->hwcfg->module_board_orient == + CCS_MODULE_BOARD_ORIENT_180) + sensor->hvflip_inv_mask = + CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR | + CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; + + rval = ccs_call_quirk(sensor, limits); + if (rval) { + dev_err(&client->dev, "limits quirks failed\n"); + goto out_free_ccs_limits; + } + + if (CCS_LIM(sensor, BINNING_CAPABILITY)) { + sensor->nbinning_subtypes = + min_t(u8, CCS_LIM(sensor, BINNING_SUB_TYPES), + CCS_LIM_BINNING_SUB_TYPE_MAX_N); + + for (i = 0; i < sensor->nbinning_subtypes; i++) { + sensor->binning_subtypes[i].horizontal = + CCS_LIM_AT(sensor, BINNING_SUB_TYPE, i) >> + CCS_BINNING_SUB_TYPE_COLUMN_SHIFT; + sensor->binning_subtypes[i].vertical = + CCS_LIM_AT(sensor, BINNING_SUB_TYPE, i) & + CCS_BINNING_SUB_TYPE_ROW_MASK; + + dev_dbg(&client->dev, "binning %xx%x\n", + sensor->binning_subtypes[i].horizontal, + sensor->binning_subtypes[i].vertical); + } + } + sensor->binning_horizontal = 1; + sensor->binning_vertical = 1; + + if (device_create_file(&client->dev, &dev_attr_ident) != 0) { + dev_err(&client->dev, "sysfs ident entry creation failed\n"); + rval = -ENOENT; + goto out_free_ccs_limits; + } + + if (sensor->minfo.smiapp_version && + CCS_LIM(sensor, DATA_TRANSFER_IF_CAPABILITY) & + CCS_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED) { + if (device_create_file(&client->dev, &dev_attr_nvm) != 0) { + dev_err(&client->dev, "sysfs nvm entry failed\n"); + rval = -EBUSY; + goto out_cleanup; + } + } + + /* We consider this as profile 0 sensor if any of these are zero. */ + if (!CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV) || + !CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV) || + !CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV) || + !CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV)) { + sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0; + } else if (CCS_LIM(sensor, SCALING_CAPABILITY) + != CCS_SCALING_CAPABILITY_NONE) { + if (CCS_LIM(sensor, SCALING_CAPABILITY) + == CCS_SCALING_CAPABILITY_HORIZONTAL) + sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1; + else + sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2; + sensor->scaler = &sensor->ssds[sensor->ssds_used]; + sensor->ssds_used++; + } else if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) + == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { + sensor->scaler = &sensor->ssds[sensor->ssds_used]; + sensor->ssds_used++; + } + sensor->binner = &sensor->ssds[sensor->ssds_used]; + sensor->ssds_used++; + sensor->pixel_array = &sensor->ssds[sensor->ssds_used]; + sensor->ssds_used++; + + sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); + + /* prepare PLL configuration input values */ + sensor->pll.bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; + sensor->pll.csi2.lanes = sensor->hwcfg->lanes; + sensor->pll.ext_clk_freq_hz = sensor->hwcfg->ext_clk; + sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); + /* Profile 0 sensors have no separate OP clock branch. */ + if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) + sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; + + ccs_create_subdev(sensor, sensor->scaler, " scaler", 2); + ccs_create_subdev(sensor, sensor->binner, " binner", 2); + ccs_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1); + + dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); + + sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + rval = ccs_init_controls(sensor); + if (rval < 0) + goto out_cleanup; + + rval = ccs_call_quirk(sensor, init); + if (rval) + goto out_cleanup; + + rval = ccs_get_mbus_formats(sensor); + if (rval) { + rval = -ENODEV; + goto out_cleanup; + } + + rval = ccs_init_late_controls(sensor); + if (rval) { + rval = -ENODEV; + goto out_cleanup; + } + + mutex_lock(&sensor->mutex); + rval = ccs_pll_blanking_update(sensor); + mutex_unlock(&sensor->mutex); + if (rval) { + dev_err(&client->dev, "update mode failed\n"); + goto out_cleanup; + } + + sensor->streaming = false; + sensor->dev_init_done = true; + + rval = media_entity_pads_init(&sensor->src->sd.entity, 2, + sensor->src->pads); + if (rval < 0) + goto out_media_entity_cleanup; + + pm_runtime_set_active(&client->dev); + pm_runtime_get_noresume(&client->dev); + pm_runtime_enable(&client->dev); + + rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd); + if (rval < 0) + goto out_disable_runtime_pm; + + pm_runtime_set_autosuspend_delay(&client->dev, 1000); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_put_autosuspend(&client->dev); + + return 0; + +out_disable_runtime_pm: + pm_runtime_put_noidle(&client->dev); + pm_runtime_disable(&client->dev); + +out_media_entity_cleanup: + media_entity_cleanup(&sensor->src->sd.entity); + +out_cleanup: + ccs_cleanup(sensor); + +out_free_ccs_limits: + kfree(sensor->ccs_limits); + +out_power_off: + ccs_power_off(&client->dev); + mutex_destroy(&sensor->mutex); + + return rval; +} + +static int ccs_remove(struct i2c_client *client) +{ + struct v4l2_subdev *subdev = i2c_get_clientdata(client); + struct ccs_sensor *sensor = to_ccs_sensor(subdev); + unsigned int i; + + v4l2_async_unregister_subdev(subdev); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + ccs_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + + for (i = 0; i < sensor->ssds_used; i++) { + v4l2_device_unregister_subdev(&sensor->ssds[i].sd); + media_entity_cleanup(&sensor->ssds[i].sd.entity); + } + ccs_cleanup(sensor); + mutex_destroy(&sensor->mutex); + kfree(sensor->ccs_limits); + + return 0; +} + +static const struct of_device_id ccs_of_table[] = { + { .compatible = "nokia,smia" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ccs_of_table); + +static const struct i2c_device_id ccs_id_table[] = { + { SMIAPP_NAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, ccs_id_table); + +static const struct dev_pm_ops ccs_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ccs_suspend, ccs_resume) + SET_RUNTIME_PM_OPS(ccs_power_off, ccs_power_on, NULL) +}; + +static struct i2c_driver ccs_i2c_driver = { + .driver = { + .of_match_table = ccs_of_table, + .name = CCS_NAME, + .pm = &ccs_pm_ops, + }, + .probe_new = ccs_probe, + .remove = ccs_remove, + .id_table = ccs_id_table, +}; + +static int ccs_module_init(void) +{ + unsigned int i, l; + + for (i = 0, l = 0; ccs_limits[i].size && l < CCS_L_LAST; i++) { + if (!(ccs_limits[i].flags & CCS_L_FL_SAME_REG)) { + ccs_limit_offsets[l + 1].lim = + ALIGN(ccs_limit_offsets[l].lim + + ccs_limits[i].size, + ccs_reg_width(ccs_limits[i + 1].reg)); + ccs_limit_offsets[l].info = i; + l++; + } else { + ccs_limit_offsets[l].lim += ccs_limits[i].size; + } + } + + if (WARN_ON(ccs_limits[i].size)) + return -EINVAL; + + if (WARN_ON(l != CCS_L_LAST)) + return -EINVAL; + + return i2c_register_driver(THIS_MODULE, &ccs_i2c_driver); +} + +static void ccs_module_cleanup(void) +{ + i2c_del_driver(&ccs_i2c_driver); +} + +module_init(ccs_module_init); +module_exit(ccs_module_cleanup); + +MODULE_AUTHOR("Sakari Ailus "); +MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ camera sensor driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("smiapp"); diff --git a/drivers/media/i2c/ccs/ccs-limits.c b/drivers/media/i2c/ccs/ccs-limits.c new file mode 100644 index 000000000000..f5511789ac83 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-limits.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause +/* Copyright (C) 2019--2020 Intel Corporation */ + +#include "ccs-limits.h" +#include "ccs-regs.h" + +const struct ccs_limit ccs_limits[] = { + { CCS_R_FRAME_FORMAT_MODEL_TYPE, 1, 0, "frame_format_model_type" }, + { CCS_R_FRAME_FORMAT_MODEL_SUBTYPE, 1, 0, "frame_format_model_subtype" }, + { CCS_R_FRAME_FORMAT_DESCRIPTOR(0), 30, 0, "frame_format_descriptor" }, + { CCS_R_FRAME_FORMAT_DESCRIPTOR_4(0), 32, 0, "frame_format_descriptor_4" }, + { CCS_R_ANALOG_GAIN_CAPABILITY, 2, 0, "analog_gain_capability" }, + { CCS_R_ANALOG_GAIN_CODE_MIN, 2, 0, "analog_gain_code_min" }, + { CCS_R_ANALOG_GAIN_CODE_MAX, 2, 0, "analog_gain_code_max" }, + { CCS_R_ANALOG_GAIN_CODE_STEP, 2, 0, "analog_gain_code_step" }, + { CCS_R_ANALOG_GAIN_TYPE, 2, 0, "analog_gain_type" }, + { CCS_R_ANALOG_GAIN_M0, 2, 0, "analog_gain_m0" }, + { CCS_R_ANALOG_GAIN_C0, 2, 0, "analog_gain_c0" }, + { CCS_R_ANALOG_GAIN_M1, 2, 0, "analog_gain_m1" }, + { CCS_R_ANALOG_GAIN_C1, 2, 0, "analog_gain_c1" }, + { CCS_R_ANALOG_LINEAR_GAIN_MIN, 2, 0, "analog_linear_gain_min" }, + { CCS_R_ANALOG_LINEAR_GAIN_MAX, 2, 0, "analog_linear_gain_max" }, + { CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE, 2, 0, "analog_linear_gain_step_size" }, + { CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN, 2, 0, "analog_exponential_gain_min" }, + { CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX, 2, 0, "analog_exponential_gain_max" }, + { CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE, 2, 0, "analog_exponential_gain_step_size" }, + { CCS_R_DATA_FORMAT_MODEL_TYPE, 1, 0, "data_format_model_type" }, + { CCS_R_DATA_FORMAT_MODEL_SUBTYPE, 1, 0, "data_format_model_subtype" }, + { CCS_R_DATA_FORMAT_DESCRIPTOR(0), 32, 0, "data_format_descriptor" }, + { CCS_R_INTEGRATION_TIME_CAPABILITY, 2, 0, "integration_time_capability" }, + { CCS_R_COARSE_INTEGRATION_TIME_MIN, 2, 0, "coarse_integration_time_min" }, + { CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN, 2, 0, "coarse_integration_time_max_margin" }, + { CCS_R_FINE_INTEGRATION_TIME_MIN, 2, 0, "fine_integration_time_min" }, + { CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN, 2, 0, "fine_integration_time_max_margin" }, + { CCS_R_DIGITAL_GAIN_CAPABILITY, 1, 0, "digital_gain_capability" }, + { CCS_R_DIGITAL_GAIN_MIN, 2, 0, "digital_gain_min" }, + { CCS_R_DIGITAL_GAIN_MAX, 2, 0, "digital_gain_max" }, + { CCS_R_DIGITAL_GAIN_STEP_SIZE, 2, 0, "digital_gain_step_size" }, + { CCS_R_PEDESTAL_CAPABILITY, 1, 0, "Pedestal_capability" }, + { CCS_R_ADC_CAPABILITY, 1, 0, "ADC_capability" }, + { CCS_R_ADC_BIT_DEPTH_CAPABILITY, 4, 0, "ADC_bit_depth_capability" }, + { CCS_R_MIN_EXT_CLK_FREQ_MHZ, 4, 0, "min_ext_clk_freq_mhz" }, + { CCS_R_MAX_EXT_CLK_FREQ_MHZ, 4, 0, "max_ext_clk_freq_mhz" }, + { CCS_R_MIN_PRE_PLL_CLK_DIV, 2, 0, "min_pre_pll_clk_div" }, + { CCS_R_MAX_PRE_PLL_CLK_DIV, 2, 0, "max_pre_pll_clk_div" }, + { CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ, 4, 0, "min_pll_ip_clk_freq_mhz" }, + { CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ, 4, 0, "max_pll_ip_clk_freq_mhz" }, + { CCS_R_MIN_PLL_MULTIPLIER, 2, 0, "min_pll_multiplier" }, + { CCS_R_MAX_PLL_MULTIPLIER, 2, 0, "max_pll_multiplier" }, + { CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ, 4, 0, "min_pll_op_clk_freq_mhz" }, + { CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ, 4, 0, "max_pll_op_clk_freq_mhz" }, + { CCS_R_MIN_VT_SYS_CLK_DIV, 2, 0, "min_vt_sys_clk_div" }, + { CCS_R_MAX_VT_SYS_CLK_DIV, 2, 0, "max_vt_sys_clk_div" }, + { CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ, 4, 0, "min_vt_sys_clk_freq_mhz" }, + { CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ, 4, 0, "max_vt_sys_clk_freq_mhz" }, + { CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ, 4, 0, "min_vt_pix_clk_freq_mhz" }, + { CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ, 4, 0, "max_vt_pix_clk_freq_mhz" }, + { CCS_R_MIN_VT_PIX_CLK_DIV, 2, 0, "min_vt_pix_clk_div" }, + { CCS_R_MAX_VT_PIX_CLK_DIV, 2, 0, "max_vt_pix_clk_div" }, + { CCS_R_CLOCK_CALCULATION, 1, 0, "clock_calculation" }, + { CCS_R_NUM_OF_VT_LANES, 1, 0, "num_of_vt_lanes" }, + { CCS_R_NUM_OF_OP_LANES, 1, 0, "num_of_op_lanes" }, + { CCS_R_OP_BITS_PER_LANE, 1, 0, "op_bits_per_lane" }, + { CCS_R_MIN_FRAME_LENGTH_LINES, 2, 0, "min_frame_length_lines" }, + { CCS_R_MAX_FRAME_LENGTH_LINES, 2, 0, "max_frame_length_lines" }, + { CCS_R_MIN_LINE_LENGTH_PCK, 2, 0, "min_line_length_pck" }, + { CCS_R_MAX_LINE_LENGTH_PCK, 2, 0, "max_line_length_pck" }, + { CCS_R_MIN_LINE_BLANKING_PCK, 2, 0, "min_line_blanking_pck" }, + { CCS_R_MIN_FRAME_BLANKING_LINES, 2, 0, "min_frame_blanking_lines" }, + { CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE, 1, 0, "min_line_length_pck_step_size" }, + { CCS_R_TIMING_MODE_CAPABILITY, 1, 0, "timing_mode_capability" }, + { CCS_R_FRAME_MARGIN_MAX_VALUE, 2, 0, "frame_margin_max_value" }, + { CCS_R_FRAME_MARGIN_MIN_VALUE, 1, 0, "frame_margin_min_value" }, + { CCS_R_GAIN_DELAY_TYPE, 1, 0, "gain_delay_type" }, + { CCS_R_MIN_OP_SYS_CLK_DIV, 2, 0, "min_op_sys_clk_div" }, + { CCS_R_MAX_OP_SYS_CLK_DIV, 2, 0, "max_op_sys_clk_div" }, + { CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ, 4, 0, "min_op_sys_clk_freq_mhz" }, + { CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ, 4, 0, "max_op_sys_clk_freq_mhz" }, + { CCS_R_MIN_OP_PIX_CLK_DIV, 2, 0, "min_op_pix_clk_div" }, + { CCS_R_MAX_OP_PIX_CLK_DIV, 2, 0, "max_op_pix_clk_div" }, + { CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ, 4, 0, "min_op_pix_clk_freq_mhz" }, + { CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ, 4, 0, "max_op_pix_clk_freq_mhz" }, + { CCS_R_X_ADDR_MIN, 2, 0, "x_addr_min" }, + { CCS_R_Y_ADDR_MIN, 2, 0, "y_addr_min" }, + { CCS_R_X_ADDR_MAX, 2, 0, "x_addr_max" }, + { CCS_R_Y_ADDR_MAX, 2, 0, "y_addr_max" }, + { CCS_R_MIN_X_OUTPUT_SIZE, 2, 0, "min_x_output_size" }, + { CCS_R_MIN_Y_OUTPUT_SIZE, 2, 0, "min_y_output_size" }, + { CCS_R_MAX_X_OUTPUT_SIZE, 2, 0, "max_x_output_size" }, + { CCS_R_MAX_Y_OUTPUT_SIZE, 2, 0, "max_y_output_size" }, + { CCS_R_X_ADDR_START_DIV_CONSTANT, 1, 0, "x_addr_start_div_constant" }, + { CCS_R_Y_ADDR_START_DIV_CONSTANT, 1, 0, "y_addr_start_div_constant" }, + { CCS_R_X_ADDR_END_DIV_CONSTANT, 1, 0, "x_addr_end_div_constant" }, + { CCS_R_Y_ADDR_END_DIV_CONSTANT, 1, 0, "y_addr_end_div_constant" }, + { CCS_R_X_SIZE_DIV, 1, 0, "x_size_div" }, + { CCS_R_Y_SIZE_DIV, 1, 0, "y_size_div" }, + { CCS_R_X_OUTPUT_DIV, 1, 0, "x_output_div" }, + { CCS_R_Y_OUTPUT_DIV, 1, 0, "y_output_div" }, + { CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT, 1, 0, "non_flexible_resolution_support" }, + { CCS_R_MIN_OP_PRE_PLL_CLK_DIV, 2, 0, "min_op_pre_pll_clk_div" }, + { CCS_R_MAX_OP_PRE_PLL_CLK_DIV, 2, 0, "max_op_pre_pll_clk_div" }, + { CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ, 4, 0, "min_op_pll_ip_clk_freq_mhz" }, + { CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ, 4, 0, "max_op_pll_ip_clk_freq_mhz" }, + { CCS_R_MIN_OP_PLL_MULTIPLIER, 2, 0, "min_op_pll_multiplier" }, + { CCS_R_MAX_OP_PLL_MULTIPLIER, 2, 0, "max_op_pll_multiplier" }, + { CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ, 4, 0, "min_op_pll_op_clk_freq_mhz" }, + { CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ, 4, 0, "max_op_pll_op_clk_freq_mhz" }, + { CCS_R_CLOCK_TREE_PLL_CAPABILITY, 1, 0, "clock_tree_pll_capability" }, + { CCS_R_CLOCK_CAPA_TYPE_CAPABILITY, 1, 0, "clock_capa_type_capability" }, + { CCS_R_MIN_EVEN_INC, 2, 0, "min_even_inc" }, + { CCS_R_MIN_ODD_INC, 2, 0, "min_odd_inc" }, + { CCS_R_MAX_EVEN_INC, 2, 0, "max_even_inc" }, + { CCS_R_MAX_ODD_INC, 2, 0, "max_odd_inc" }, + { CCS_R_AUX_SUBSAMP_CAPABILITY, 1, 0, "aux_subsamp_capability" }, + { CCS_R_AUX_SUBSAMP_MONO_CAPABILITY, 1, 0, "aux_subsamp_mono_capability" }, + { CCS_R_MONOCHROME_CAPABILITY, 1, 0, "monochrome_capability" }, + { CCS_R_PIXEL_READOUT_CAPABILITY, 1, 0, "pixel_readout_capability" }, + { CCS_R_MIN_EVEN_INC_MONO, 2, 0, "min_even_inc_mono" }, + { CCS_R_MAX_EVEN_INC_MONO, 2, 0, "max_even_inc_mono" }, + { CCS_R_MIN_ODD_INC_MONO, 2, 0, "min_odd_inc_mono" }, + { CCS_R_MAX_ODD_INC_MONO, 2, 0, "max_odd_inc_mono" }, + { CCS_R_MIN_EVEN_INC_BC2, 2, 0, "min_even_inc_bc2" }, + { CCS_R_MAX_EVEN_INC_BC2, 2, 0, "max_even_inc_bc2" }, + { CCS_R_MIN_ODD_INC_BC2, 2, 0, "min_odd_inc_bc2" }, + { CCS_R_MAX_ODD_INC_BC2, 2, 0, "max_odd_inc_bc2" }, + { CCS_R_MIN_EVEN_INC_MONO_BC2, 2, 0, "min_even_inc_mono_bc2" }, + { CCS_R_MAX_EVEN_INC_MONO_BC2, 2, 0, "max_even_inc_mono_bc2" }, + { CCS_R_MIN_ODD_INC_MONO_BC2, 2, 0, "min_odd_inc_mono_bc2" }, + { CCS_R_MAX_ODD_INC_MONO_BC2, 2, 0, "max_odd_inc_mono_bc2" }, + { CCS_R_SCALING_CAPABILITY, 2, 0, "scaling_capability" }, + { CCS_R_SCALER_M_MIN, 2, 0, "scaler_m_min" }, + { CCS_R_SCALER_M_MAX, 2, 0, "scaler_m_max" }, + { CCS_R_SCALER_N_MIN, 2, 0, "scaler_n_min" }, + { CCS_R_SCALER_N_MAX, 2, 0, "scaler_n_max" }, + { CCS_R_DIGITAL_CROP_CAPABILITY, 1, 0, "digital_crop_capability" }, + { CCS_R_HDR_CAPABILITY_1, 1, 0, "hdr_capability_1" }, + { CCS_R_MIN_HDR_BIT_DEPTH, 1, 0, "min_hdr_bit_depth" }, + { CCS_R_HDR_RESOLUTION_SUB_TYPES, 1, 0, "hdr_resolution_sub_types" }, + { CCS_R_HDR_RESOLUTION_SUB_TYPE(0), 2, 0, "hdr_resolution_sub_type" }, + { CCS_R_HDR_CAPABILITY_2, 1, 0, "hdr_capability_2" }, + { CCS_R_MAX_HDR_BIT_DEPTH, 1, 0, "max_hdr_bit_depth" }, + { CCS_R_USL_SUPPORT_CAPABILITY, 1, 0, "usl_support_capability" }, + { CCS_R_USL_CLOCK_MODE_D_CAPABILITY, 1, 0, "usl_clock_mode_d_capability" }, + { CCS_R_MIN_OP_SYS_CLK_DIV_REV, 1, 0, "min_op_sys_clk_div_rev" }, + { CCS_R_MAX_OP_SYS_CLK_DIV_REV, 1, 0, "max_op_sys_clk_div_rev" }, + { CCS_R_MIN_OP_PIX_CLK_DIV_REV, 1, 0, "min_op_pix_clk_div_rev" }, + { CCS_R_MAX_OP_PIX_CLK_DIV_REV, 1, 0, "max_op_pix_clk_div_rev" }, + { CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ, 4, 0, "min_op_sys_clk_freq_rev_mhz" }, + { CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ, 4, 0, "max_op_sys_clk_freq_rev_mhz" }, + { CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ, 4, 0, "min_op_pix_clk_freq_rev_mhz" }, + { CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ, 4, 0, "max_op_pix_clk_freq_rev_mhz" }, + { CCS_R_MAX_BITRATE_REV_D_MODE_MBPS, 4, 0, "max_bitrate_rev_d_mode_mbps" }, + { CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS, 4, 0, "max_symrate_rev_c_mode_msps" }, + { CCS_R_COMPRESSION_CAPABILITY, 1, 0, "compression_capability" }, + { CCS_R_TEST_MODE_CAPABILITY, 2, 0, "test_mode_capability" }, + { CCS_R_PN9_DATA_FORMAT1, 1, 0, "pn9_data_format1" }, + { CCS_R_PN9_DATA_FORMAT2, 1, 0, "pn9_data_format2" }, + { CCS_R_PN9_DATA_FORMAT3, 1, 0, "pn9_data_format3" }, + { CCS_R_PN9_DATA_FORMAT4, 1, 0, "pn9_data_format4" }, + { CCS_R_PN9_MISC_CAPABILITY, 1, 0, "pn9_misc_capability" }, + { CCS_R_TEST_PATTERN_CAPABILITY, 1, 0, "test_pattern_capability" }, + { CCS_R_PATTERN_SIZE_DIV_M1, 1, 0, "pattern_size_div_m1" }, + { CCS_R_FIFO_SUPPORT_CAPABILITY, 1, 0, "fifo_support_capability" }, + { CCS_R_PHY_CTRL_CAPABILITY, 1, 0, "phy_ctrl_capability" }, + { CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY, 1, 0, "csi_dphy_lane_mode_capability" }, + { CCS_R_CSI_SIGNALING_MODE_CAPABILITY, 1, 0, "csi_signaling_mode_capability" }, + { CCS_R_FAST_STANDBY_CAPABILITY, 1, 0, "fast_standby_capability" }, + { CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY, 1, 0, "csi_address_control_capability" }, + { CCS_R_DATA_TYPE_CAPABILITY, 1, 0, "data_type_capability" }, + { CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY, 1, 0, "csi_cphy_lane_mode_capability" }, + { CCS_R_EMB_DATA_CAPABILITY, 1, 0, "emb_data_capability" }, + { CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(0), 16, 0, "max_per_lane_bitrate_lane_d_mode_mbps 0" }, + { CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(4), 16, CCS_L_FL_SAME_REG, "max_per_lane_bitrate_lane_d_mode_mbps 4" }, + { CCS_R_TEMP_SENSOR_CAPABILITY, 1, 0, "temp_sensor_capability" }, + { CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(0), 16, 0, "max_per_lane_bitrate_lane_c_mode_mbps 0" }, + { CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(4), 16, CCS_L_FL_SAME_REG, "max_per_lane_bitrate_lane_c_mode_mbps 4" }, + { CCS_R_DPHY_EQUALIZATION_CAPABILITY, 1, 0, "dphy_equalization_capability" }, + { CCS_R_CPHY_EQUALIZATION_CAPABILITY, 1, 0, "cphy_equalization_capability" }, + { CCS_R_DPHY_PREAMBLE_CAPABILITY, 1, 0, "dphy_preamble_capability" }, + { CCS_R_DPHY_SSC_CAPABILITY, 1, 0, "dphy_ssc_capability" }, + { CCS_R_CPHY_CALIBRATION_CAPABILITY, 1, 0, "cphy_calibration_capability" }, + { CCS_R_DPHY_CALIBRATION_CAPABILITY, 1, 0, "dphy_calibration_capability" }, + { CCS_R_PHY_CTRL_CAPABILITY_2, 1, 0, "phy_ctrl_capability_2" }, + { CCS_R_LRTE_CPHY_CAPABILITY, 1, 0, "lrte_cphy_capability" }, + { CCS_R_LRTE_DPHY_CAPABILITY, 1, 0, "lrte_dphy_capability" }, + { CCS_R_ALPS_CAPABILITY_DPHY, 1, 0, "alps_capability_dphy" }, + { CCS_R_ALPS_CAPABILITY_CPHY, 1, 0, "alps_capability_cphy" }, + { CCS_R_SCRAMBLING_CAPABILITY, 1, 0, "scrambling_capability" }, + { CCS_R_DPHY_MANUAL_CONSTANT, 1, 0, "dphy_manual_constant" }, + { CCS_R_CPHY_MANUAL_CONSTANT, 1, 0, "cphy_manual_constant" }, + { CCS_R_CSI2_INTERFACE_CAPABILITY_MISC, 1, 0, "CSI2_interface_capability_misc" }, + { CCS_R_PHY_CTRL_CAPABILITY_3, 1, 0, "PHY_ctrl_capability_3" }, + { CCS_R_DPHY_SF, 1, 0, "dphy_sf" }, + { CCS_R_CPHY_SF, 1, 0, "cphy_sf" }, + { CCS_R_DPHY_LIMITS_1, 1, 0, "dphy_limits_1" }, + { CCS_R_DPHY_LIMITS_2, 1, 0, "dphy_limits_2" }, + { CCS_R_DPHY_LIMITS_3, 1, 0, "dphy_limits_3" }, + { CCS_R_DPHY_LIMITS_4, 1, 0, "dphy_limits_4" }, + { CCS_R_DPHY_LIMITS_5, 1, 0, "dphy_limits_5" }, + { CCS_R_DPHY_LIMITS_6, 1, 0, "dphy_limits_6" }, + { CCS_R_CPHY_LIMITS_1, 1, 0, "cphy_limits_1" }, + { CCS_R_CPHY_LIMITS_2, 1, 0, "cphy_limits_2" }, + { CCS_R_CPHY_LIMITS_3, 1, 0, "cphy_limits_3" }, + { CCS_R_MIN_FRAME_LENGTH_LINES_BIN, 2, 0, "min_frame_length_lines_bin" }, + { CCS_R_MAX_FRAME_LENGTH_LINES_BIN, 2, 0, "max_frame_length_lines_bin" }, + { CCS_R_MIN_LINE_LENGTH_PCK_BIN, 2, 0, "min_line_length_pck_bin" }, + { CCS_R_MAX_LINE_LENGTH_PCK_BIN, 2, 0, "max_line_length_pck_bin" }, + { CCS_R_MIN_LINE_BLANKING_PCK_BIN, 2, 0, "min_line_blanking_pck_bin" }, + { CCS_R_FINE_INTEGRATION_TIME_MIN_BIN, 2, 0, "fine_integration_time_min_bin" }, + { CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN, 2, 0, "fine_integration_time_max_margin_bin" }, + { CCS_R_BINNING_CAPABILITY, 1, 0, "binning_capability" }, + { CCS_R_BINNING_WEIGHTING_CAPABILITY, 1, 0, "binning_weighting_capability" }, + { CCS_R_BINNING_SUB_TYPES, 1, 0, "binning_sub_types" }, + { CCS_R_BINNING_SUB_TYPE(0), 64, 0, "binning_sub_type" }, + { CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY, 1, 0, "binning_weighting_mono_capability" }, + { CCS_R_BINNING_SUB_TYPES_MONO, 1, 0, "binning_sub_types_mono" }, + { CCS_R_BINNING_SUB_TYPE_MONO(0), 64, 0, "binning_sub_type_mono" }, + { CCS_R_DATA_TRANSFER_IF_CAPABILITY, 1, 0, "data_transfer_if_capability" }, + { CCS_R_SHADING_CORRECTION_CAPABILITY, 1, 0, "shading_correction_capability" }, + { CCS_R_GREEN_IMBALANCE_CAPABILITY, 1, 0, "green_imbalance_capability" }, + { CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY, 1, 0, "module_specific_correction_capability" }, + { CCS_R_DEFECT_CORRECTION_CAPABILITY, 2, 0, "defect_correction_capability" }, + { CCS_R_DEFECT_CORRECTION_CAPABILITY_2, 2, 0, "defect_correction_capability_2" }, + { CCS_R_NF_CAPABILITY, 1, 0, "nf_capability" }, + { CCS_R_OB_READOUT_CAPABILITY, 1, 0, "ob_readout_capability" }, + { CCS_R_COLOR_FEEDBACK_CAPABILITY, 1, 0, "color_feedback_capability" }, + { CCS_R_CFA_PATTERN_CAPABILITY, 1, 0, "CFA_pattern_capability" }, + { CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY, 1, 0, "CFA_pattern_conversion_capability" }, + { CCS_R_FLASH_MODE_CAPABILITY, 1, 0, "flash_mode_capability" }, + { CCS_R_SA_STROBE_MODE_CAPABILITY, 1, 0, "sa_strobe_mode_capability" }, + { CCS_R_RESET_MAX_DELAY, 1, 0, "reset_max_delay" }, + { CCS_R_RESET_MIN_TIME, 1, 0, "reset_min_time" }, + { CCS_R_PDAF_CAPABILITY_1, 1, 0, "pdaf_capability_1" }, + { CCS_R_PDAF_CAPABILITY_2, 1, 0, "pdaf_capability_2" }, + { CCS_R_BRACKETING_LUT_CAPABILITY_1, 1, 0, "bracketing_lut_capability_1" }, + { CCS_R_BRACKETING_LUT_CAPABILITY_2, 1, 0, "bracketing_lut_capability_2" }, + { CCS_R_BRACKETING_LUT_SIZE, 1, 0, "bracketing_lut_size" }, + { 0 } /* Guardian */ +}; diff --git a/drivers/media/i2c/ccs/ccs-limits.h b/drivers/media/i2c/ccs/ccs-limits.h new file mode 100644 index 000000000000..1efa43c23a2e --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-limits.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ +/* Copyright (C) 2019--2020 Intel Corporation */ + +#ifndef __CCS_LIMITS_H__ +#define __CCS_LIMITS_H__ + +#include +#include + +struct ccs_limit { + u32 reg; + u16 size; + u16 flags; + const char *name; +}; + +#define CCS_L_FL_SAME_REG BIT(0) + +extern const struct ccs_limit ccs_limits[]; + +#define CCS_L_FRAME_FORMAT_MODEL_TYPE 0 +#define CCS_L_FRAME_FORMAT_MODEL_SUBTYPE 1 +#define CCS_L_FRAME_FORMAT_DESCRIPTOR 2 +#define CCS_L_FRAME_FORMAT_DESCRIPTOR_OFFSET(n) ((n) * 2) +#define CCS_L_FRAME_FORMAT_DESCRIPTOR_4 3 +#define CCS_L_FRAME_FORMAT_DESCRIPTOR_4_OFFSET(n) ((n) * 4) +#define CCS_L_ANALOG_GAIN_CAPABILITY 4 +#define CCS_L_ANALOG_GAIN_CODE_MIN 5 +#define CCS_L_ANALOG_GAIN_CODE_MAX 6 +#define CCS_L_ANALOG_GAIN_CODE_STEP 7 +#define CCS_L_ANALOG_GAIN_TYPE 8 +#define CCS_L_ANALOG_GAIN_M0 9 +#define CCS_L_ANALOG_GAIN_C0 10 +#define CCS_L_ANALOG_GAIN_M1 11 +#define CCS_L_ANALOG_GAIN_C1 12 +#define CCS_L_ANALOG_LINEAR_GAIN_MIN 13 +#define CCS_L_ANALOG_LINEAR_GAIN_MAX 14 +#define CCS_L_ANALOG_LINEAR_GAIN_STEP_SIZE 15 +#define CCS_L_ANALOG_EXPONENTIAL_GAIN_MIN 16 +#define CCS_L_ANALOG_EXPONENTIAL_GAIN_MAX 17 +#define CCS_L_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE 18 +#define CCS_L_DATA_FORMAT_MODEL_TYPE 19 +#define CCS_L_DATA_FORMAT_MODEL_SUBTYPE 20 +#define CCS_L_DATA_FORMAT_DESCRIPTOR 21 +#define CCS_L_DATA_FORMAT_DESCRIPTOR_OFFSET(n) ((n) * 2) +#define CCS_L_INTEGRATION_TIME_CAPABILITY 22 +#define CCS_L_COARSE_INTEGRATION_TIME_MIN 23 +#define CCS_L_COARSE_INTEGRATION_TIME_MAX_MARGIN 24 +#define CCS_L_FINE_INTEGRATION_TIME_MIN 25 +#define CCS_L_FINE_INTEGRATION_TIME_MAX_MARGIN 26 +#define CCS_L_DIGITAL_GAIN_CAPABILITY 27 +#define CCS_L_DIGITAL_GAIN_MIN 28 +#define CCS_L_DIGITAL_GAIN_MAX 29 +#define CCS_L_DIGITAL_GAIN_STEP_SIZE 30 +#define CCS_L_PEDESTAL_CAPABILITY 31 +#define CCS_L_ADC_CAPABILITY 32 +#define CCS_L_ADC_BIT_DEPTH_CAPABILITY 33 +#define CCS_L_MIN_EXT_CLK_FREQ_MHZ 34 +#define CCS_L_MAX_EXT_CLK_FREQ_MHZ 35 +#define CCS_L_MIN_PRE_PLL_CLK_DIV 36 +#define CCS_L_MAX_PRE_PLL_CLK_DIV 37 +#define CCS_L_MIN_PLL_IP_CLK_FREQ_MHZ 38 +#define CCS_L_MAX_PLL_IP_CLK_FREQ_MHZ 39 +#define CCS_L_MIN_PLL_MULTIPLIER 40 +#define CCS_L_MAX_PLL_MULTIPLIER 41 +#define CCS_L_MIN_PLL_OP_CLK_FREQ_MHZ 42 +#define CCS_L_MAX_PLL_OP_CLK_FREQ_MHZ 43 +#define CCS_L_MIN_VT_SYS_CLK_DIV 44 +#define CCS_L_MAX_VT_SYS_CLK_DIV 45 +#define CCS_L_MIN_VT_SYS_CLK_FREQ_MHZ 46 +#define CCS_L_MAX_VT_SYS_CLK_FREQ_MHZ 47 +#define CCS_L_MIN_VT_PIX_CLK_FREQ_MHZ 48 +#define CCS_L_MAX_VT_PIX_CLK_FREQ_MHZ 49 +#define CCS_L_MIN_VT_PIX_CLK_DIV 50 +#define CCS_L_MAX_VT_PIX_CLK_DIV 51 +#define CCS_L_CLOCK_CALCULATION 52 +#define CCS_L_NUM_OF_VT_LANES 53 +#define CCS_L_NUM_OF_OP_LANES 54 +#define CCS_L_OP_BITS_PER_LANE 55 +#define CCS_L_MIN_FRAME_LENGTH_LINES 56 +#define CCS_L_MAX_FRAME_LENGTH_LINES 57 +#define CCS_L_MIN_LINE_LENGTH_PCK 58 +#define CCS_L_MAX_LINE_LENGTH_PCK 59 +#define CCS_L_MIN_LINE_BLANKING_PCK 60 +#define CCS_L_MIN_FRAME_BLANKING_LINES 61 +#define CCS_L_MIN_LINE_LENGTH_PCK_STEP_SIZE 62 +#define CCS_L_TIMING_MODE_CAPABILITY 63 +#define CCS_L_FRAME_MARGIN_MAX_VALUE 64 +#define CCS_L_FRAME_MARGIN_MIN_VALUE 65 +#define CCS_L_GAIN_DELAY_TYPE 66 +#define CCS_L_MIN_OP_SYS_CLK_DIV 67 +#define CCS_L_MAX_OP_SYS_CLK_DIV 68 +#define CCS_L_MIN_OP_SYS_CLK_FREQ_MHZ 69 +#define CCS_L_MAX_OP_SYS_CLK_FREQ_MHZ 70 +#define CCS_L_MIN_OP_PIX_CLK_DIV 71 +#define CCS_L_MAX_OP_PIX_CLK_DIV 72 +#define CCS_L_MIN_OP_PIX_CLK_FREQ_MHZ 73 +#define CCS_L_MAX_OP_PIX_CLK_FREQ_MHZ 74 +#define CCS_L_X_ADDR_MIN 75 +#define CCS_L_Y_ADDR_MIN 76 +#define CCS_L_X_ADDR_MAX 77 +#define CCS_L_Y_ADDR_MAX 78 +#define CCS_L_MIN_X_OUTPUT_SIZE 79 +#define CCS_L_MIN_Y_OUTPUT_SIZE 80 +#define CCS_L_MAX_X_OUTPUT_SIZE 81 +#define CCS_L_MAX_Y_OUTPUT_SIZE 82 +#define CCS_L_X_ADDR_START_DIV_CONSTANT 83 +#define CCS_L_Y_ADDR_START_DIV_CONSTANT 84 +#define CCS_L_X_ADDR_END_DIV_CONSTANT 85 +#define CCS_L_Y_ADDR_END_DIV_CONSTANT 86 +#define CCS_L_X_SIZE_DIV 87 +#define CCS_L_Y_SIZE_DIV 88 +#define CCS_L_X_OUTPUT_DIV 89 +#define CCS_L_Y_OUTPUT_DIV 90 +#define CCS_L_NON_FLEXIBLE_RESOLUTION_SUPPORT 91 +#define CCS_L_MIN_OP_PRE_PLL_CLK_DIV 92 +#define CCS_L_MAX_OP_PRE_PLL_CLK_DIV 93 +#define CCS_L_MIN_OP_PLL_IP_CLK_FREQ_MHZ 94 +#define CCS_L_MAX_OP_PLL_IP_CLK_FREQ_MHZ 95 +#define CCS_L_MIN_OP_PLL_MULTIPLIER 96 +#define CCS_L_MAX_OP_PLL_MULTIPLIER 97 +#define CCS_L_MIN_OP_PLL_OP_CLK_FREQ_MHZ 98 +#define CCS_L_MAX_OP_PLL_OP_CLK_FREQ_MHZ 99 +#define CCS_L_CLOCK_TREE_PLL_CAPABILITY 100 +#define CCS_L_CLOCK_CAPA_TYPE_CAPABILITY 101 +#define CCS_L_MIN_EVEN_INC 102 +#define CCS_L_MIN_ODD_INC 103 +#define CCS_L_MAX_EVEN_INC 104 +#define CCS_L_MAX_ODD_INC 105 +#define CCS_L_AUX_SUBSAMP_CAPABILITY 106 +#define CCS_L_AUX_SUBSAMP_MONO_CAPABILITY 107 +#define CCS_L_MONOCHROME_CAPABILITY 108 +#define CCS_L_PIXEL_READOUT_CAPABILITY 109 +#define CCS_L_MIN_EVEN_INC_MONO 110 +#define CCS_L_MAX_EVEN_INC_MONO 111 +#define CCS_L_MIN_ODD_INC_MONO 112 +#define CCS_L_MAX_ODD_INC_MONO 113 +#define CCS_L_MIN_EVEN_INC_BC2 114 +#define CCS_L_MAX_EVEN_INC_BC2 115 +#define CCS_L_MIN_ODD_INC_BC2 116 +#define CCS_L_MAX_ODD_INC_BC2 117 +#define CCS_L_MIN_EVEN_INC_MONO_BC2 118 +#define CCS_L_MAX_EVEN_INC_MONO_BC2 119 +#define CCS_L_MIN_ODD_INC_MONO_BC2 120 +#define CCS_L_MAX_ODD_INC_MONO_BC2 121 +#define CCS_L_SCALING_CAPABILITY 122 +#define CCS_L_SCALER_M_MIN 123 +#define CCS_L_SCALER_M_MAX 124 +#define CCS_L_SCALER_N_MIN 125 +#define CCS_L_SCALER_N_MAX 126 +#define CCS_L_DIGITAL_CROP_CAPABILITY 127 +#define CCS_L_HDR_CAPABILITY_1 128 +#define CCS_L_MIN_HDR_BIT_DEPTH 129 +#define CCS_L_HDR_RESOLUTION_SUB_TYPES 130 +#define CCS_L_HDR_RESOLUTION_SUB_TYPE 131 +#define CCS_L_HDR_RESOLUTION_SUB_TYPE_OFFSET(n) (n) +#define CCS_L_HDR_CAPABILITY_2 132 +#define CCS_L_MAX_HDR_BIT_DEPTH 133 +#define CCS_L_USL_SUPPORT_CAPABILITY 134 +#define CCS_L_USL_CLOCK_MODE_D_CAPABILITY 135 +#define CCS_L_MIN_OP_SYS_CLK_DIV_REV 136 +#define CCS_L_MAX_OP_SYS_CLK_DIV_REV 137 +#define CCS_L_MIN_OP_PIX_CLK_DIV_REV 138 +#define CCS_L_MAX_OP_PIX_CLK_DIV_REV 139 +#define CCS_L_MIN_OP_SYS_CLK_FREQ_REV_MHZ 140 +#define CCS_L_MAX_OP_SYS_CLK_FREQ_REV_MHZ 141 +#define CCS_L_MIN_OP_PIX_CLK_FREQ_REV_MHZ 142 +#define CCS_L_MAX_OP_PIX_CLK_FREQ_REV_MHZ 143 +#define CCS_L_MAX_BITRATE_REV_D_MODE_MBPS 144 +#define CCS_L_MAX_SYMRATE_REV_C_MODE_MSPS 145 +#define CCS_L_COMPRESSION_CAPABILITY 146 +#define CCS_L_TEST_MODE_CAPABILITY 147 +#define CCS_L_PN9_DATA_FORMAT1 148 +#define CCS_L_PN9_DATA_FORMAT2 149 +#define CCS_L_PN9_DATA_FORMAT3 150 +#define CCS_L_PN9_DATA_FORMAT4 151 +#define CCS_L_PN9_MISC_CAPABILITY 152 +#define CCS_L_TEST_PATTERN_CAPABILITY 153 +#define CCS_L_PATTERN_SIZE_DIV_M1 154 +#define CCS_L_FIFO_SUPPORT_CAPABILITY 155 +#define CCS_L_PHY_CTRL_CAPABILITY 156 +#define CCS_L_CSI_DPHY_LANE_MODE_CAPABILITY 157 +#define CCS_L_CSI_SIGNALING_MODE_CAPABILITY 158 +#define CCS_L_FAST_STANDBY_CAPABILITY 159 +#define CCS_L_CSI_ADDRESS_CONTROL_CAPABILITY 160 +#define CCS_L_DATA_TYPE_CAPABILITY 161 +#define CCS_L_CSI_CPHY_LANE_MODE_CAPABILITY 162 +#define CCS_L_EMB_DATA_CAPABILITY 163 +#define CCS_L_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS 164 +#define CCS_L_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_OFFSET(n) ((n) * 4) +#define CCS_L_TEMP_SENSOR_CAPABILITY 165 +#define CCS_L_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS 166 +#define CCS_L_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_OFFSET(n) ((n) * 4) +#define CCS_L_DPHY_EQUALIZATION_CAPABILITY 167 +#define CCS_L_CPHY_EQUALIZATION_CAPABILITY 168 +#define CCS_L_DPHY_PREAMBLE_CAPABILITY 169 +#define CCS_L_DPHY_SSC_CAPABILITY 170 +#define CCS_L_CPHY_CALIBRATION_CAPABILITY 171 +#define CCS_L_DPHY_CALIBRATION_CAPABILITY 172 +#define CCS_L_PHY_CTRL_CAPABILITY_2 173 +#define CCS_L_LRTE_CPHY_CAPABILITY 174 +#define CCS_L_LRTE_DPHY_CAPABILITY 175 +#define CCS_L_ALPS_CAPABILITY_DPHY 176 +#define CCS_L_ALPS_CAPABILITY_CPHY 177 +#define CCS_L_SCRAMBLING_CAPABILITY 178 +#define CCS_L_DPHY_MANUAL_CONSTANT 179 +#define CCS_L_CPHY_MANUAL_CONSTANT 180 +#define CCS_L_CSI2_INTERFACE_CAPABILITY_MISC 181 +#define CCS_L_PHY_CTRL_CAPABILITY_3 182 +#define CCS_L_DPHY_SF 183 +#define CCS_L_CPHY_SF 184 +#define CCS_L_DPHY_LIMITS_1 185 +#define CCS_L_DPHY_LIMITS_2 186 +#define CCS_L_DPHY_LIMITS_3 187 +#define CCS_L_DPHY_LIMITS_4 188 +#define CCS_L_DPHY_LIMITS_5 189 +#define CCS_L_DPHY_LIMITS_6 190 +#define CCS_L_CPHY_LIMITS_1 191 +#define CCS_L_CPHY_LIMITS_2 192 +#define CCS_L_CPHY_LIMITS_3 193 +#define CCS_L_MIN_FRAME_LENGTH_LINES_BIN 194 +#define CCS_L_MAX_FRAME_LENGTH_LINES_BIN 195 +#define CCS_L_MIN_LINE_LENGTH_PCK_BIN 196 +#define CCS_L_MAX_LINE_LENGTH_PCK_BIN 197 +#define CCS_L_MIN_LINE_BLANKING_PCK_BIN 198 +#define CCS_L_FINE_INTEGRATION_TIME_MIN_BIN 199 +#define CCS_L_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN 200 +#define CCS_L_BINNING_CAPABILITY 201 +#define CCS_L_BINNING_WEIGHTING_CAPABILITY 202 +#define CCS_L_BINNING_SUB_TYPES 203 +#define CCS_L_BINNING_SUB_TYPE 204 +#define CCS_L_BINNING_SUB_TYPE_OFFSET(n) (n) +#define CCS_L_BINNING_WEIGHTING_MONO_CAPABILITY 205 +#define CCS_L_BINNING_SUB_TYPES_MONO 206 +#define CCS_L_BINNING_SUB_TYPE_MONO 207 +#define CCS_L_BINNING_SUB_TYPE_MONO_OFFSET(n) (n) +#define CCS_L_DATA_TRANSFER_IF_CAPABILITY 208 +#define CCS_L_SHADING_CORRECTION_CAPABILITY 209 +#define CCS_L_GREEN_IMBALANCE_CAPABILITY 210 +#define CCS_L_MODULE_SPECIFIC_CORRECTION_CAPABILITY 211 +#define CCS_L_DEFECT_CORRECTION_CAPABILITY 212 +#define CCS_L_DEFECT_CORRECTION_CAPABILITY_2 213 +#define CCS_L_NF_CAPABILITY 214 +#define CCS_L_OB_READOUT_CAPABILITY 215 +#define CCS_L_COLOR_FEEDBACK_CAPABILITY 216 +#define CCS_L_CFA_PATTERN_CAPABILITY 217 +#define CCS_L_CFA_PATTERN_CONVERSION_CAPABILITY 218 +#define CCS_L_FLASH_MODE_CAPABILITY 219 +#define CCS_L_SA_STROBE_MODE_CAPABILITY 220 +#define CCS_L_RESET_MAX_DELAY 221 +#define CCS_L_RESET_MIN_TIME 222 +#define CCS_L_PDAF_CAPABILITY_1 223 +#define CCS_L_PDAF_CAPABILITY_2 224 +#define CCS_L_BRACKETING_LUT_CAPABILITY_1 225 +#define CCS_L_BRACKETING_LUT_CAPABILITY_2 226 +#define CCS_L_BRACKETING_LUT_SIZE 227 +#define CCS_L_LAST 228 + +#endif /* __CCS_LIMITS_H__ */ diff --git a/drivers/media/i2c/ccs/ccs-quirk.c b/drivers/media/i2c/ccs/ccs-quirk.c new file mode 100644 index 000000000000..5a24da1d7aa9 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-quirk.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * drivers/media/i2c/ccs/ccs-quirk.c + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#include + +#include "ccs.h" +#include "ccs-limits.h" + +static int ccs_write_addr_8s(struct ccs_sensor *sensor, + const struct ccs_reg_8 *regs, int len) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + + for (; len > 0; len--, regs++) { + rval = ccs_write_addr(sensor, regs->reg, regs->val); + if (rval < 0) { + dev_err(&client->dev, + "error %d writing reg 0x%4.4x, val 0x%2.2x", + rval, regs->reg, regs->val); + return rval; + } + } + + return 0; +} + +static int jt8ew9_limits(struct ccs_sensor *sensor) +{ + if (sensor->minfo.revision_number_major < 0x03) + sensor->frame_skip = 1; + + /* Below 24 gain doesn't have effect at all, */ + /* but ~59 is needed for full dynamic range */ + ccs_replace_limit(sensor, CCS_L_ANALOG_GAIN_CODE_MIN, 0, 59); + ccs_replace_limit(sensor, CCS_L_ANALOG_GAIN_CODE_MAX, 0, 6000); + + return 0; +} + +static int jt8ew9_post_poweron(struct ccs_sensor *sensor) +{ + static const struct ccs_reg_8 regs[] = { + { 0x30a3, 0xd8 }, /* Output port control : LVDS ports only */ + { 0x30ae, 0x00 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */ + { 0x30af, 0xd0 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */ + { 0x322d, 0x04 }, /* Adjusting Processing Image Size to Scaler Toshiba Recommendation Setting */ + { 0x3255, 0x0f }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ + { 0x3256, 0x15 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ + { 0x3258, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */ + { 0x3259, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */ + { 0x325f, 0x7c }, /* Analog Gain Control Toshiba Recommendation Setting */ + { 0x3302, 0x06 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ + { 0x3304, 0x00 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ + { 0x3307, 0x22 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ + { 0x3308, 0x8d }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ + { 0x331e, 0x0f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x3320, 0x30 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x3321, 0x11 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x3322, 0x98 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x3323, 0x64 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x3325, 0x83 }, /* Read Out Timing Control Toshiba Recommendation Setting */ + { 0x3330, 0x18 }, /* Read Out Timing Control Toshiba Recommendation Setting */ + { 0x333c, 0x01 }, /* Read Out Timing Control Toshiba Recommendation Setting */ + { 0x3345, 0x2f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ + { 0x33de, 0x38 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ + /* Taken from v03. No idea what the rest are. */ + { 0x32e0, 0x05 }, + { 0x32e1, 0x05 }, + { 0x32e2, 0x04 }, + { 0x32e5, 0x04 }, + { 0x32e6, 0x04 }, + + }; + + return ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); +} + +const struct ccs_quirk smiapp_jt8ew9_quirk = { + .limits = jt8ew9_limits, + .post_poweron = jt8ew9_post_poweron, +}; + +static int imx125es_post_poweron(struct ccs_sensor *sensor) +{ + /* Taken from v02. No idea what the other two are. */ + static const struct ccs_reg_8 regs[] = { + /* + * 0x3302: clk during frame blanking: + * 0x00 - HS mode, 0x01 - LP11 + */ + { 0x3302, 0x01 }, + { 0x302d, 0x00 }, + { 0x3b08, 0x8c }, + }; + + return ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); +} + +const struct ccs_quirk smiapp_imx125es_quirk = { + .post_poweron = imx125es_post_poweron, +}; + +static int jt8ev1_limits(struct ccs_sensor *sensor) +{ + ccs_replace_limit(sensor, CCS_L_X_ADDR_MAX, 0, 4271); + ccs_replace_limit(sensor, CCS_L_MIN_LINE_BLANKING_PCK_BIN, 0, 184); + + return 0; +} + +static int jt8ev1_post_poweron(struct ccs_sensor *sensor) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + int rval; + static const struct ccs_reg_8 regs[] = { + { 0x3031, 0xcd }, /* For digital binning (EQ_MONI) */ + { 0x30a3, 0xd0 }, /* FLASH STROBE enable */ + { 0x3237, 0x00 }, /* For control of pulse timing for ADC */ + { 0x3238, 0x43 }, + { 0x3301, 0x06 }, /* For analog bias for sensor */ + { 0x3302, 0x06 }, + { 0x3304, 0x00 }, + { 0x3305, 0x88 }, + { 0x332a, 0x14 }, + { 0x332c, 0x6b }, + { 0x3336, 0x01 }, + { 0x333f, 0x1f }, + { 0x3355, 0x00 }, + { 0x3356, 0x20 }, + { 0x33bf, 0x20 }, /* Adjust the FBC speed */ + { 0x33c9, 0x20 }, + { 0x33ce, 0x30 }, /* Adjust the parameter for logic function */ + { 0x33cf, 0xec }, /* For Black sun */ + { 0x3328, 0x80 }, /* Ugh. No idea what's this. */ + }; + static const struct ccs_reg_8 regs_96[] = { + { 0x30ae, 0x00 }, /* For control of ADC clock */ + { 0x30af, 0xd0 }, + { 0x30b0, 0x01 }, + }; + + rval = ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); + if (rval < 0) + return rval; + + switch (sensor->hwcfg->ext_clk) { + case 9600000: + return ccs_write_addr_8s(sensor, regs_96, + ARRAY_SIZE(regs_96)); + default: + dev_warn(&client->dev, "no MSRs for %d Hz ext_clk\n", + sensor->hwcfg->ext_clk); + return 0; + } +} + +static int jt8ev1_pre_streamon(struct ccs_sensor *sensor) +{ + return ccs_write_addr(sensor, 0x3328, 0x00); +} + +static int jt8ev1_post_streamoff(struct ccs_sensor *sensor) +{ + int rval; + + /* Workaround: allows fast standby to work properly */ + rval = ccs_write_addr(sensor, 0x3205, 0x04); + if (rval < 0) + return rval; + + /* Wait for 1 ms + one line => 2 ms is likely enough */ + usleep_range(2000, 2050); + + /* Restore it */ + rval = ccs_write_addr(sensor, 0x3205, 0x00); + if (rval < 0) + return rval; + + return ccs_write_addr(sensor, 0x3328, 0x80); +} + +static int jt8ev1_init(struct ccs_sensor *sensor) +{ + sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + + return 0; +} + +const struct ccs_quirk smiapp_jt8ev1_quirk = { + .limits = jt8ev1_limits, + .post_poweron = jt8ev1_post_poweron, + .pre_streamon = jt8ev1_pre_streamon, + .post_streamoff = jt8ev1_post_streamoff, + .init = jt8ev1_init, +}; + +static int tcm8500md_limits(struct ccs_sensor *sensor) +{ + ccs_replace_limit(sensor, CCS_L_MIN_PLL_IP_CLK_FREQ_MHZ, 0, 2700000); + + return 0; +} + +const struct ccs_quirk smiapp_tcm8500md_quirk = { + .limits = tcm8500md_limits, +}; diff --git a/drivers/media/i2c/ccs/ccs-quirk.h b/drivers/media/i2c/ccs/ccs-quirk.h new file mode 100644 index 000000000000..3e7779e2fc4b --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-quirk.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * drivers/media/i2c/ccs/ccs-quirk.h + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#ifndef __CCS_QUIRK__ +#define __CCS_QUIRK__ + +struct ccs_sensor; + +/** + * struct ccs_quirk - quirks for sensors that deviate from SMIA++ standard + * + * @limits: Replace sensor->limits with values which can't be read from + * sensor registers. Called the first time the sensor is powered up. + * @post_poweron: Called always after the sensor has been fully powered on. + * @pre_streamon: Called just before streaming is enabled. + * @post_streamon: Called right after stopping streaming. + * @pll_flags: Return flags for the PLL calculator. + * @init: Quirk initialisation, called the last in probe(). This is + * also appropriate for adding sensor specific controls, for instance. + * @reg_access: Register access quirk. The quirk may divert the access + * to another register, or no register at all. + * + * @write: Is this read (false) or write (true) access? + * @reg: Pointer to the register to access + * @value: Register value, set by the caller on write, or + * by the quirk on read + * + * @return: 0 on success, -ENOIOCTLCMD if no register + * access may be done by the caller (default read + * value is zero), else negative error code on error + */ +struct ccs_quirk { + int (*limits)(struct ccs_sensor *sensor); + int (*post_poweron)(struct ccs_sensor *sensor); + int (*pre_streamon)(struct ccs_sensor *sensor); + int (*post_streamoff)(struct ccs_sensor *sensor); + unsigned long (*pll_flags)(struct ccs_sensor *sensor); + int (*init)(struct ccs_sensor *sensor); + int (*reg_access)(struct ccs_sensor *sensor, bool write, u32 *reg, + u32 *val); + unsigned long flags; +}; + +#define CCS_QUIRK_FLAG_8BIT_READ_ONLY (1 << 0) + +struct ccs_reg_8 { + u16 reg; + u8 val; +}; + +#define CCS_MK_QUIRK_REG_8(_reg, _val) \ + { \ + .reg = (u16)_reg, \ + .val = _val, \ + } + +#define ccs_call_quirk(sensor, _quirk, ...) \ + ((sensor)->minfo.quirk && \ + (sensor)->minfo.quirk->_quirk ? \ + (sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0) + +#define ccs_needs_quirk(sensor, _quirk) \ + ((sensor)->minfo.quirk ? \ + (sensor)->minfo.quirk->flags & _quirk : 0) + +extern const struct ccs_quirk smiapp_jt8ev1_quirk; +extern const struct ccs_quirk smiapp_imx125es_quirk; +extern const struct ccs_quirk smiapp_jt8ew9_quirk; +extern const struct ccs_quirk smiapp_tcm8500md_quirk; + +#endif /* __CCS_QUIRK__ */ diff --git a/drivers/media/i2c/ccs/ccs-reg-access.c b/drivers/media/i2c/ccs/ccs-reg-access.c new file mode 100644 index 000000000000..a8e9a235bfb3 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-reg-access.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * drivers/media/i2c/ccs/ccs-reg-access.c + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#include + +#include +#include + +#include "ccs.h" + +static uint32_t float_to_u32_mul_1000000(struct i2c_client *client, + uint32_t phloat) +{ + int32_t exp; + uint64_t man; + + if (phloat >= 0x80000000) { + dev_err(&client->dev, "this is a negative number\n"); + return 0; + } + + if (phloat == 0x7f800000) + return ~0; /* Inf. */ + + if ((phloat & 0x7f800000) == 0x7f800000) { + dev_err(&client->dev, "NaN or other special number\n"); + return 0; + } + + /* Valid cases begin here */ + if (phloat == 0) + return 0; /* Valid zero */ + + if (phloat > 0x4f800000) + return ~0; /* larger than 4294967295 */ + + /* + * Unbias exponent (note how phloat is now guaranteed to + * have 0 in the high bit) + */ + exp = ((int32_t)phloat >> 23) - 127; + + /* Extract mantissa, add missing '1' bit and it's in MHz */ + man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL; + + if (exp < 0) + man >>= -exp; + else + man <<= exp; + + man >>= 23; /* Remove mantissa bias */ + + return man & 0xffffffff; +} + + +/* + * Read a 8/16/32-bit i2c register. The value is returned in 'val'. + * Returns zero if successful, or non-zero otherwise. + */ +static int ____ccs_read_addr(struct ccs_sensor *sensor, u16 reg, u16 len, + u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct i2c_msg msg; + unsigned char data_buf[sizeof(u32)] = { 0 }; + unsigned char offset_buf[sizeof(u16)]; + int r; + + if (len > sizeof(data_buf)) + return -EINVAL; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = sizeof(offset_buf); + msg.buf = offset_buf; + put_unaligned_be16(reg, offset_buf); + + r = i2c_transfer(client->adapter, &msg, 1); + if (r != 1) { + if (r >= 0) + r = -EBUSY; + goto err; + } + + msg.len = len; + msg.flags = I2C_M_RD; + msg.buf = &data_buf[sizeof(data_buf) - len]; + + r = i2c_transfer(client->adapter, &msg, 1); + if (r != 1) { + if (r >= 0) + r = -EBUSY; + goto err; + } + + *val = get_unaligned_be32(data_buf); + + return 0; + +err: + dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r); + + return r; +} + +/* Read a register using 8-bit access only. */ +static int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg, + u16 len, u32 *val) +{ + unsigned int i; + int rval; + + *val = 0; + + for (i = 0; i < len; i++) { + u32 val8; + + rval = ____ccs_read_addr(sensor, reg + i, 1, &val8); + if (rval < 0) + return rval; + *val |= val8 << ((len - i - 1) << 3); + } + + return 0; +} + +unsigned int ccs_reg_width(u32 reg) +{ + if (reg & CCS_FL_16BIT) + return sizeof(uint16_t); + if (reg & CCS_FL_32BIT) + return sizeof(uint32_t); + + return sizeof(uint8_t); +} + +/* + * Read a 8/16/32-bit i2c register. The value is returned in 'val'. + * Returns zero if successful, or non-zero otherwise. + */ +static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val, + bool only8) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + unsigned int len = ccs_reg_width(reg); + int rval; + + if (!only8) + rval = ____ccs_read_addr(sensor, CCS_REG_ADDR(reg), len, val); + else + rval = ____ccs_read_addr_8only(sensor, CCS_REG_ADDR(reg), len, + val); + if (rval < 0) + return rval; + + if (reg & CCS_FL_FLOAT_IREAL) + *val = float_to_u32_mul_1000000(client, *val); + + return 0; +} + +int ccs_read_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val) +{ + return __ccs_read_addr( + sensor, reg, val, + ccs_needs_quirk(sensor, CCS_QUIRK_FLAG_8BIT_READ_ONLY)); +} + +static int ccs_read_addr_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val, + bool force8) +{ + int rval; + + *val = 0; + rval = ccs_call_quirk(sensor, reg_access, false, ®, val); + if (rval == -ENOIOCTLCMD) + return 0; + if (rval < 0) + return rval; + + if (force8) + return __ccs_read_addr(sensor, reg, val, true); + + return ccs_read_addr_no_quirk(sensor, reg, val); +} + +int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val) +{ + return ccs_read_addr_quirk(sensor, reg, val, false); +} + +int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val) +{ + return ccs_read_addr_quirk(sensor, reg, val, true); +} + +int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); + struct i2c_msg msg; + unsigned char data[6]; + unsigned int retries; + unsigned int len = ccs_reg_width(reg); + int r; + + if (len > sizeof(data) - 2) + return -EINVAL; + + msg.addr = client->addr; + msg.flags = 0; /* Write */ + msg.len = 2 + len; + msg.buf = data; + + put_unaligned_be16(CCS_REG_ADDR(reg), data); + put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2); + + for (retries = 0; retries < 5; retries++) { + /* + * Due to unknown reason sensor stops responding. This + * loop is a temporaty solution until the root cause + * is found. + */ + r = i2c_transfer(client->adapter, &msg, 1); + if (r == 1) { + if (retries) + dev_err(&client->dev, + "sensor i2c stall encountered. retries: %d\n", + retries); + return 0; + } + + usleep_range(2000, 2000); + } + + dev_err(&client->dev, + "wrote 0x%x to offset 0x%x error %d\n", val, + CCS_REG_ADDR(reg), r); + + return r; +} + +/* + * Write to a 8/16-bit register. + * Returns zero if successful, or non-zero otherwise. + */ +int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val) +{ + int rval; + + rval = ccs_call_quirk(sensor, reg_access, true, ®, &val); + if (rval == -ENOIOCTLCMD) + return 0; + if (rval < 0) + return rval; + + return ccs_write_addr_no_quirk(sensor, reg, val); +} diff --git a/drivers/media/i2c/ccs/ccs-reg-access.h b/drivers/media/i2c/ccs/ccs-reg-access.h new file mode 100644 index 000000000000..9fdf5659ed09 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-reg-access.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * include/media/ccs/ccs-reg-access.h + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#ifndef SMIAPP_REGS_H +#define SMIAPP_REGS_H + +#include +#include + +#include "ccs-regs.h" + +#define CCS_REG_ADDR(reg) ((u16)reg) + +struct ccs_sensor; + +int ccs_read_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val); +int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val); +int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val); +int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val); +int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val); + +unsigned int ccs_reg_width(u32 reg); + +#define ccs_read(sensor, reg_name, val) \ + ccs_read_addr(sensor, CCS_R_##reg_name, val) + +#define ccs_write(sensor, reg_name, val) \ + ccs_write_addr(sensor, CCS_R_##reg_name, val) + +#endif diff --git a/drivers/media/i2c/ccs/ccs-regs.h b/drivers/media/i2c/ccs/ccs-regs.h new file mode 100644 index 000000000000..4b3e5df2121f --- /dev/null +++ b/drivers/media/i2c/ccs/ccs-regs.h @@ -0,0 +1,954 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ +/* Copyright (C) 2019--2020 Intel Corporation */ + +#ifndef __CCS_REGS_H__ +#define __CCS_REGS_H__ + +#include + +#define CCS_FL_BASE 16 +#define CCS_FL_16BIT BIT(CCS_FL_BASE) +#define CCS_FL_32BIT BIT(CCS_FL_BASE + 1) +#define CCS_FL_FLOAT_IREAL BIT(CCS_FL_BASE + 2) +#define CCS_FL_IREAL BIT(CCS_FL_BASE + 3) +#define CCS_R_ADDR(r) ((r) & 0xffff) + +#define CCS_R_MODULE_MODEL_ID (0x0000 | CCS_FL_16BIT) +#define CCS_R_MODULE_REVISION_NUMBER_MAJOR 0x0002 +#define CCS_R_FRAME_COUNT 0x0005 +#define CCS_R_PIXEL_ORDER 0x0006 +#define CCS_PIXEL_ORDER_GRBG 0U +#define CCS_PIXEL_ORDER_RGGB 1U +#define CCS_PIXEL_ORDER_BGGR 2U +#define CCS_PIXEL_ORDER_GBRG 3U +#define CCS_R_MIPI_CCS_VERSION 0x0007 +#define CCS_MIPI_CCS_VERSION_V1_0 0x10 +#define CCS_MIPI_CCS_VERSION_V1_1 0x11 +#define CCS_MIPI_CCS_VERSION_MAJOR_SHIFT 4U +#define CCS_MIPI_CCS_VERSION_MAJOR_MASK 0xf0 +#define CCS_MIPI_CCS_VERSION_MINOR_SHIFT 0U +#define CCS_MIPI_CCS_VERSION_MINOR_MASK 0xf +#define CCS_R_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT) +#define CCS_R_MODULE_MANUFACTURER_ID (0x000e | CCS_FL_16BIT) +#define CCS_R_MODULE_REVISION_NUMBER_MINOR 0x0010 +#define CCS_R_MODULE_DATE_YEAR 0x0012 +#define CCS_R_MODULE_DATE_MONTH 0x0013 +#define CCS_R_MODULE_DATE_DAY 0x0014 +#define CCS_R_MODULE_DATE_PHASE 0x0015 +#define CCS_MODULE_DATE_PHASE_SHIFT 0U +#define CCS_MODULE_DATE_PHASE_MASK 0x7 +#define CCS_MODULE_DATE_PHASE_TS 0U +#define CCS_MODULE_DATE_PHASE_ES 1U +#define CCS_MODULE_DATE_PHASE_CS 2U +#define CCS_MODULE_DATE_PHASE_MP 3U +#define CCS_R_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT) +#define CCS_R_SENSOR_REVISION_NUMBER 0x0018 +#define CCS_R_SENSOR_FIRMWARE_VERSION 0x001a +#define CCS_R_SERIAL_NUMBER (0x001c | CCS_FL_32BIT) +#define CCS_R_SENSOR_MANUFACTURER_ID (0x0020 | CCS_FL_16BIT) +#define CCS_R_SENSOR_REVISION_NUMBER_16 (0x0022 | CCS_FL_16BIT) +#define CCS_R_FRAME_FORMAT_MODEL_TYPE 0x0040 +#define CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE 1U +#define CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE 2U +#define CCS_R_FRAME_FORMAT_MODEL_SUBTYPE 0x0041 +#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U +#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf +#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U +#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0 +#define CCS_R_FRAME_FORMAT_DESCRIPTOR(n) ((0x0042 | CCS_FL_16BIT) + (n) * 2) +#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MIN_N 0U +#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MAX_N 14U +#define CCS_R_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 | CCS_FL_32BIT) + (n) * 4) +#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_SHIFT 0U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_MASK 0xfff +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_SHIFT 12U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MASK 0xf000 +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED 1U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DUMMY_PIXEL 2U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_BLACK_PIXEL 3U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DARK_PIXEL 4U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL 5U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_0 8U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_1 9U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_2 10U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_3 11U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_4 12U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_5 13U +#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_6 14U +#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_4_MIN_N 0U +#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_4_MAX_N 7U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_SHIFT 0U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK 0xffff +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_SHIFT 28U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MASK 0xf0000000 +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_EMBEDDED 1U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_DUMMY_PIXEL 2U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_BLACK_PIXEL 3U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_DARK_PIXEL 4U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_VISIBLE_PIXEL 5U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_0 8U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_1 9U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_2 10U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_3 11U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_4 12U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_5 13U +#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_6 14U +#define CCS_R_ANALOG_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT) +#define CCS_ANALOG_GAIN_CAPABILITY_GLOBAL 0U +#define CCS_ANALOG_GAIN_CAPABILITY_ALTERNATE_GLOBAL 2U +#define CCS_R_ANALOG_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_TYPE (0x008a | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_M0 (0x008c | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_C0 (0x008e | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_M1 (0x0090 | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_C1 (0x0092 | CCS_FL_16BIT) +#define CCS_R_ANALOG_LINEAR_GAIN_MIN (0x0094 | CCS_FL_16BIT) +#define CCS_R_ANALOG_LINEAR_GAIN_MAX (0x0096 | CCS_FL_16BIT) +#define CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE (0x0098 | CCS_FL_16BIT) +#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN (0x009a | CCS_FL_16BIT) +#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX (0x009c | CCS_FL_16BIT) +#define CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE (0x009e | CCS_FL_16BIT) +#define CCS_R_DATA_FORMAT_MODEL_TYPE 0x00c0 +#define CCS_DATA_FORMAT_MODEL_TYPE_NORMAL 1U +#define CCS_DATA_FORMAT_MODEL_TYPE_EXTENDED 2U +#define CCS_R_DATA_FORMAT_MODEL_SUBTYPE 0x00c1 +#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U +#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf +#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U +#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0 +#define CCS_R_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 | CCS_FL_16BIT) + (n) * 2) +#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MIN_N 0U +#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MAX_N 15U +#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_SHIFT 0U +#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK 0xff +#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT 8U +#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_MASK 0xff00 +#define CCS_R_MODE_SELECT 0x0100 +#define CCS_MODE_SELECT_SOFTWARE_STANDBY 0U +#define CCS_MODE_SELECT_STREAMING 1U +#define CCS_R_IMAGE_ORIENTATION 0x0101 +#define CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR BIT(0) +#define CCS_IMAGE_ORIENTATION_VERTICAL_FLIP BIT(1) +#define CCS_R_SOFTWARE_RESET 0x0103 +#define CCS_SOFTWARE_RESET_OFF 0U +#define CCS_SOFTWARE_RESET_ON 1U +#define CCS_R_GROUPED_PARAMETER_HOLD 0x0104 +#define CCS_R_MASK_CORRUPTED_FRAMES 0x0105 +#define CCS_MASK_CORRUPTED_FRAMES_ALLOW 0U +#define CCS_MASK_CORRUPTED_FRAMES_MASK 1U +#define CCS_R_FAST_STANDBY_CTRL 0x0106 +#define CCS_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0U +#define CCS_FAST_STANDBY_CTRL_FRAME_TRUNCATION 1U +#define CCS_R_CCI_ADDRESS_CTRL 0x0107 +#define CCS_R_2ND_CCI_IF_CTRL 0x0108 +#define CCS_2ND_CCI_IF_CTRL_ENABLE BIT(0) +#define CCS_2ND_CCI_IF_CTRL_ACK BIT(1) +#define CCS_R_2ND_CCI_ADDRESS_CTRL 0x0109 +#define CCS_R_CSI_CHANNEL_IDENTIFIER 0x0110 +#define CCS_R_CSI_SIGNALING_MODE 0x0111 +#define CCS_CSI_SIGNALING_MODE_CSI_2_DPHY 2U +#define CCS_CSI_SIGNALING_MODE_CSI_2_CPHY 3U +#define CCS_R_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT) +#define CCS_R_CSI_LANE_MODE 0x0114 +#define CCS_R_DPCM_FRAME_DT 0x011d +#define CCS_R_BOTTOM_EMBEDDED_DATA_DT 0x011e +#define CCS_R_BOTTOM_EMBEDDED_DATA_VC 0x011f +#define CCS_R_GAIN_MODE 0x0120 +#define CCS_GAIN_MODE_GLOBAL 0U +#define CCS_GAIN_MODE_ALTERNATE 1U +#define CCS_R_ADC_BIT_DEPTH 0x0121 +#define CCS_R_EMB_DATA_CTRL 0x0122 +#define CCS_EMB_DATA_CTRL_RAW8_PACKING_FOR_RAW16 BIT(0) +#define CCS_EMB_DATA_CTRL_RAW10_PACKING_FOR_RAW20 BIT(1) +#define CCS_EMB_DATA_CTRL_RAW12_PACKING_FOR_RAW24 BIT(2) +#define CCS_R_GPIO_TRIG_MODE 0x0130 +#define CCS_R_EXTCLK_FREQUENCY_MHZ (0x0136 | (CCS_FL_16BIT | CCS_FL_IREAL)) +#define CCS_R_TEMP_SENSOR_CTRL 0x0138 +#define CCS_TEMP_SENSOR_CTRL_ENABLE BIT(0) +#define CCS_R_TEMP_SENSOR_MODE 0x0139 +#define CCS_R_TEMP_SENSOR_OUTPUT 0x013a +#define CCS_R_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT) +#define CCS_R_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT) +#define CCS_R_ANALOG_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT) +#define CCS_R_ANALOG_LINEAR_GAIN_GLOBAL (0x0206 | CCS_FL_16BIT) +#define CCS_R_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0208 | CCS_FL_16BIT) +#define CCS_R_DIGITAL_GAIN_GLOBAL (0x020e | CCS_FL_16BIT) +#define CCS_R_SHORT_ANALOG_GAIN_GLOBAL (0x0216 | CCS_FL_16BIT) +#define CCS_R_SHORT_DIGITAL_GAIN_GLOBAL (0x0218 | CCS_FL_16BIT) +#define CCS_R_HDR_MODE 0x0220 +#define CCS_HDR_MODE_ENABLED BIT(0) +#define CCS_HDR_MODE_SEPARATE_ANALOG_GAIN BIT(1) +#define CCS_HDR_MODE_UPSCALING BIT(2) +#define CCS_HDR_MODE_RESET_SYNC BIT(3) +#define CCS_HDR_MODE_TIMING_MODE BIT(4) +#define CCS_HDR_MODE_EXPOSURE_CTRL_DIRECT BIT(5) +#define CCS_HDR_MODE_SEPARATE_DIGITAL_GAIN BIT(6) +#define CCS_R_HDR_RESOLUTION_REDUCTION 0x0221 +#define CCS_HDR_RESOLUTION_REDUCTION_ROW_SHIFT 0U +#define CCS_HDR_RESOLUTION_REDUCTION_ROW_MASK 0xf +#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_SHIFT 4U +#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_MASK 0xf0 +#define CCS_R_EXPOSURE_RATIO 0x0222 +#define CCS_R_HDR_INTERNAL_BIT_DEPTH 0x0223 +#define CCS_R_DIRECT_SHORT_INTEGRATION_TIME (0x0224 | CCS_FL_16BIT) +#define CCS_R_SHORT_ANALOG_LINEAR_GAIN_GLOBAL (0x0226 | CCS_FL_16BIT) +#define CCS_R_SHORT_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0228 | CCS_FL_16BIT) +#define CCS_R_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT) +#define CCS_R_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT) +#define CCS_R_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT) +#define CCS_R_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT) +#define CCS_R_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT) +#define CCS_R_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT) +#define CCS_R_OP_PRE_PLL_CLK_DIV (0x030c | CCS_FL_16BIT) +#define CCS_R_OP_PLL_MULTIPLIER (0x031e | CCS_FL_16BIT) +#define CCS_R_PLL_MODE 0x0310 +#define CCS_PLL_MODE_SHIFT 0U +#define CCS_PLL_MODE_MASK 0x1 +#define CCS_PLL_MODE_SINGLE 0U +#define CCS_PLL_MODE_DUAL 1U +#define CCS_R_OP_PIX_CLK_DIV_REV (0x0312 | CCS_FL_16BIT) +#define CCS_R_OP_SYS_CLK_DIV_REV (0x0314 | CCS_FL_16BIT) +#define CCS_R_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT) +#define CCS_R_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT) +#define CCS_R_X_ADDR_START (0x0344 | CCS_FL_16BIT) +#define CCS_R_Y_ADDR_START (0x0346 | CCS_FL_16BIT) +#define CCS_R_X_ADDR_END (0x0348 | CCS_FL_16BIT) +#define CCS_R_Y_ADDR_END (0x034a | CCS_FL_16BIT) +#define CCS_R_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT) +#define CCS_R_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT) +#define CCS_R_FRAME_LENGTH_CTRL 0x0350 +#define CCS_FRAME_LENGTH_CTRL_AUTOMATIC BIT(0) +#define CCS_R_TIMING_MODE_CTRL 0x0352 +#define CCS_TIMING_MODE_CTRL_MANUAL_READOUT BIT(0) +#define CCS_TIMING_MODE_CTRL_DELAYED_EXPOSURE BIT(1) +#define CCS_R_START_READOUT_RS 0x0353 +#define CCS_START_READOUT_RS_MANUAL_READOUT_START BIT(0) +#define CCS_R_FRAME_MARGIN (0x0354 | CCS_FL_16BIT) +#define CCS_R_X_EVEN_INC (0x0380 | CCS_FL_16BIT) +#define CCS_R_X_ODD_INC (0x0382 | CCS_FL_16BIT) +#define CCS_R_Y_EVEN_INC (0x0384 | CCS_FL_16BIT) +#define CCS_R_Y_ODD_INC (0x0386 | CCS_FL_16BIT) +#define CCS_R_MONOCHROME_EN 0x0390 +#define CCS_MONOCHROME_EN_ENABLED 0U +#define CCS_R_SCALING_MODE (0x0400 | CCS_FL_16BIT) +#define CCS_SCALING_MODE_NO_SCALING 0U +#define CCS_SCALING_MODE_HORIZONTAL 1U +#define CCS_R_SCALE_M (0x0404 | CCS_FL_16BIT) +#define CCS_R_SCALE_N (0x0406 | CCS_FL_16BIT) +#define CCS_R_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT) +#define CCS_R_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT) +#define CCS_R_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT) +#define CCS_R_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT) +#define CCS_R_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT) +#define CCS_COMPRESSION_MODE_NONE 0U +#define CCS_COMPRESSION_MODE_DPCM_PCM_SIMPLE 1U +#define CCS_R_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT) +#define CCS_TEST_PATTERN_MODE_NONE 0U +#define CCS_TEST_PATTERN_MODE_SOLID_COLOR 1U +#define CCS_TEST_PATTERN_MODE_COLOR_BARS 2U +#define CCS_TEST_PATTERN_MODE_FADE_TO_GREY 3U +#define CCS_TEST_PATTERN_MODE_PN9 4U +#define CCS_TEST_PATTERN_MODE_COLOR_TILE 5U +#define CCS_R_TEST_DATA_RED (0x0602 | CCS_FL_16BIT) +#define CCS_R_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT) +#define CCS_R_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT) +#define CCS_R_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT) +#define CCS_R_VALUE_STEP_SIZE_SMOOTH 0x060a +#define CCS_R_VALUE_STEP_SIZE_QUANTISED 0x060b +#define CCS_R_TCLK_POST 0x0800 +#define CCS_R_THS_PREPARE 0x0801 +#define CCS_R_THS_ZERO_MIN 0x0802 +#define CCS_R_THS_TRAIL 0x0803 +#define CCS_R_TCLK_TRAIL_MIN 0x0804 +#define CCS_R_TCLK_PREPARE 0x0805 +#define CCS_R_TCLK_ZERO 0x0806 +#define CCS_R_TLPX 0x0807 +#define CCS_R_PHY_CTRL 0x0808 +#define CCS_PHY_CTRL_AUTO 0U +#define CCS_PHY_CTRL_UI 1U +#define CCS_PHY_CTRL_MANUAL 2U +#define CCS_R_TCLK_POST_EX (0x080a | CCS_FL_16BIT) +#define CCS_R_THS_PREPARE_EX (0x080c | CCS_FL_16BIT) +#define CCS_R_THS_ZERO_MIN_EX (0x080e | CCS_FL_16BIT) +#define CCS_R_THS_TRAIL_EX (0x0810 | CCS_FL_16BIT) +#define CCS_R_TCLK_TRAIL_MIN_EX (0x0812 | CCS_FL_16BIT) +#define CCS_R_TCLK_PREPARE_EX (0x0814 | CCS_FL_16BIT) +#define CCS_R_TCLK_ZERO_EX (0x0816 | CCS_FL_16BIT) +#define CCS_R_TLPX_EX (0x0818 | CCS_FL_16BIT) +#define CCS_R_REQUESTED_LINK_RATE (0x0820 | CCS_FL_32BIT) +#define CCS_R_DPHY_EQUALIZATION_MODE 0x0824 +#define CCS_DPHY_EQUALIZATION_MODE_EQ2 BIT(0) +#define CCS_R_PHY_EQUALIZATION_CTRL 0x0825 +#define CCS_PHY_EQUALIZATION_CTRL_ENABLE BIT(0) +#define CCS_R_DPHY_PREAMBLE_CTRL 0x0826 +#define CCS_DPHY_PREAMBLE_CTRL_ENABLE BIT(0) +#define CCS_R_DPHY_PREAMBLE_LENGTH 0x0826 +#define CCS_R_PHY_SSC_CTRL 0x0828 +#define CCS_PHY_SSC_CTRL_ENABLE BIT(0) +#define CCS_R_MANUAL_LP_CTRL 0x0829 +#define CCS_MANUAL_LP_CTRL_ENABLE BIT(0) +#define CCS_R_TWAKEUP 0x082a +#define CCS_R_TINIT 0x082b +#define CCS_R_THS_EXIT 0x082c +#define CCS_R_THS_EXIT_EX (0x082e | CCS_FL_16BIT) +#define CCS_R_PHY_PERIODIC_CALIBRATION_CTRL 0x0830 +#define CCS_PHY_PERIODIC_CALIBRATION_CTRL_FRAME_BLANKING BIT(0) +#define CCS_R_PHY_PERIODIC_CALIBRATION_INTERVAL 0x0831 +#define CCS_R_PHY_INIT_CALIBRATION_CTRL 0x0832 +#define CCS_PHY_INIT_CALIBRATION_CTRL_STREAM_START BIT(0) +#define CCS_R_DPHY_CALIBRATION_MODE 0x0833 +#define CCS_DPHY_CALIBRATION_MODE_ALSO_ALTERNATE BIT(0) +#define CCS_R_CPHY_CALIBRATION_MODE 0x0834 +#define CCS_CPHY_CALIBRATION_MODE_FORMAT_1 0U +#define CCS_CPHY_CALIBRATION_MODE_FORMAT_2 1U +#define CCS_CPHY_CALIBRATION_MODE_FORMAT_3 2U +#define CCS_R_T3_CALPREAMBLE_LENGTH 0x0835 +#define CCS_R_T3_CALPREAMBLE_LENGTH_PER 0x0836 +#define CCS_R_T3_CALALTSEQ_LENGTH 0x0837 +#define CCS_R_T3_CALALTSEQ_LENGTH_PER 0x0838 +#define CCS_R_FM2_INIT_SEED (0x083a | CCS_FL_16BIT) +#define CCS_R_T3_CALUDEFSEQ_LENGTH (0x083c | CCS_FL_16BIT) +#define CCS_R_T3_CALUDEFSEQ_LENGTH_PER (0x083e | CCS_FL_16BIT) +#define CCS_R_TGR_PREAMBLE_LENGTH 0x0841 +#define CCS_TGR_PREAMBLE_LENGTH_PREAMABLE_PROG_SEQ BIT(7) +#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_SHIFT 0U +#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_MASK 0x3f +#define CCS_R_TGR_POST_LENGTH 0x0842 +#define CCS_TGR_POST_LENGTH_POST_LENGTH_SHIFT 0U +#define CCS_TGR_POST_LENGTH_POST_LENGTH_MASK 0x1f +#define CCS_R_TGR_PREAMBLE_PROG_SEQUENCE(n2) (0x0843 + (n2)) +#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MIN_N2 0U +#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MAX_N2 6U +#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_SHIFT 3U +#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_MASK 0x38 +#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_SHIFT 0U +#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_MASK 0x7 +#define CCS_R_T3_PREPARE (0x084e | CCS_FL_16BIT) +#define CCS_R_T3_LPX (0x0850 | CCS_FL_16BIT) +#define CCS_R_ALPS_CTRL 0x085a +#define CCS_ALPS_CTRL_LVLP_DPHY BIT(0) +#define CCS_ALPS_CTRL_LVLP_CPHY BIT(1) +#define CCS_ALPS_CTRL_ALP_CPHY BIT(2) +#define CCS_R_TX_REG_CSI_EPD_EN_SSP_CPHY (0x0860 | CCS_FL_16BIT) +#define CCS_R_TX_REG_CSI_EPD_OP_SLP_CPHY (0x0862 | CCS_FL_16BIT) +#define CCS_R_TX_REG_CSI_EPD_EN_SSP_DPHY (0x0864 | CCS_FL_16BIT) +#define CCS_R_TX_REG_CSI_EPD_OP_SLP_DPHY (0x0866 | CCS_FL_16BIT) +#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_CPHY 0x0868 +#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_DPHY 0x0869 +#define CCS_R_SCRAMBLING_CTRL 0x0870 +#define CCS_SCRAMBLING_CTRL_ENABLED BIT(0) +#define CCS_SCRAMBLING_CTRL_SHIFT 2U +#define CCS_SCRAMBLING_CTRL_MASK 0xc +#define CCS_SCRAMBLING_CTRL_1_SEED_CPHY 0U +#define CCS_SCRAMBLING_CTRL_4_SEED_CPHY 3U +#define CCS_R_LANE_SEED_VALUE(seed, lane) ((0x0872 | CCS_FL_16BIT) + (seed) * 16 + (lane) * 2) +#define CCS_LIM_LANE_SEED_VALUE_MIN_SEED 0U +#define CCS_LIM_LANE_SEED_VALUE_MAX_SEED 3U +#define CCS_LIM_LANE_SEED_VALUE_MIN_LANE 0U +#define CCS_LIM_LANE_SEED_VALUE_MAX_LANE 7U +#define CCS_R_TX_USL_REV_ENTRY (0x08c0 | CCS_FL_16BIT) +#define CCS_R_TX_USL_REV_CLOCK_COUNTER (0x08c2 | CCS_FL_16BIT) +#define CCS_R_TX_USL_REV_LP_COUNTER (0x08c4 | CCS_FL_16BIT) +#define CCS_R_TX_USL_REV_FRAME_COUNTER (0x08c6 | CCS_FL_16BIT) +#define CCS_R_TX_USL_REV_CHRONOLOGICAL_TIMER (0x08c8 | CCS_FL_16BIT) +#define CCS_R_TX_USL_FWD_ENTRY (0x08ca | CCS_FL_16BIT) +#define CCS_R_TX_USL_GPIO (0x08cc | CCS_FL_16BIT) +#define CCS_R_TX_USL_OPERATION (0x08ce | CCS_FL_16BIT) +#define CCS_TX_USL_OPERATION_RESET BIT(0) +#define CCS_R_TX_USL_ALP_CTRL (0x08d0 | CCS_FL_16BIT) +#define CCS_TX_USL_ALP_CTRL_CLOCK_PAUSE BIT(0) +#define CCS_R_TX_USL_APP_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT) +#define CCS_R_TX_USL_SNS_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT) +#define CCS_R_USL_CLOCK_MODE_D_CTRL 0x08d2 +#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_STANDBY BIT(0) +#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_VBLANK BIT(1) +#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_HBLANK BIT(2) +#define CCS_R_BINNING_MODE 0x0900 +#define CCS_R_BINNING_TYPE 0x0901 +#define CCS_R_BINNING_WEIGHTING 0x0902 +#define CCS_R_DATA_TRANSFER_IF_1_CTRL 0x0a00 +#define CCS_DATA_TRANSFER_IF_1_CTRL_ENABLE BIT(0) +#define CCS_DATA_TRANSFER_IF_1_CTRL_WRITE BIT(1) +#define CCS_DATA_TRANSFER_IF_1_CTRL_CLEAR_ERROR BIT(2) +#define CCS_R_DATA_TRANSFER_IF_1_STATUS 0x0a01 +#define CCS_DATA_TRANSFER_IF_1_STATUS_READ_IF_READY BIT(0) +#define CCS_DATA_TRANSFER_IF_1_STATUS_WRITE_IF_READY BIT(1) +#define CCS_DATA_TRANSFER_IF_1_STATUS_DATA_CORRUPTED BIT(2) +#define CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE BIT(3) +#define CCS_R_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02 +#define CCS_R_DATA_TRANSFER_IF_1_DATA(p) (0x0a04 + (p)) +#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MIN_P 0U +#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P 63U +#define CCS_R_SHADING_CORRECTION_EN 0x0b00 +#define CCS_SHADING_CORRECTION_EN_ENABLE BIT(0) +#define CCS_R_LUMINANCE_CORRECTION_LEVEL 0x0b01 +#define CCS_R_GREEN_IMBALANCE_FILTER_EN 0x0b02 +#define CCS_GREEN_IMBALANCE_FILTER_EN_ENABLE BIT(0) +#define CCS_R_MAPPED_DEFECT_CORRECT_EN 0x0b05 +#define CCS_MAPPED_DEFECT_CORRECT_EN_ENABLE BIT(0) +#define CCS_R_SINGLE_DEFECT_CORRECT_EN 0x0b06 +#define CCS_SINGLE_DEFECT_CORRECT_EN_ENABLE BIT(0) +#define CCS_R_DYNAMIC_COUPLET_CORRECT_EN 0x0b08 +#define CCS_DYNAMIC_COUPLET_CORRECT_EN_ENABLE BIT(0) +#define CCS_R_COMBINED_DEFECT_CORRECT_EN 0x0b0a +#define CCS_COMBINED_DEFECT_CORRECT_EN_ENABLE BIT(0) +#define CCS_R_MODULE_SPECIFIC_CORRECTION_EN 0x0b0c +#define CCS_MODULE_SPECIFIC_CORRECTION_EN_ENABLE BIT(0) +#define CCS_R_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN 0x0b13 +#define CCS_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN_ENABLE BIT(0) +#define CCS_R_NF_CTRL 0x0b15 +#define CCS_NF_CTRL_LUMA BIT(0) +#define CCS_NF_CTRL_CHROMA BIT(1) +#define CCS_NF_CTRL_COMBINED BIT(2) +#define CCS_R_OB_READOUT_CONTROL 0x0b30 +#define CCS_OB_READOUT_CONTROL_ENABLE BIT(0) +#define CCS_OB_READOUT_CONTROL_INTERLEAVING BIT(1) +#define CCS_R_OB_VIRTUAL_CHANNEL 0x0b31 +#define CCS_R_OB_DT 0x0b32 +#define CCS_R_OB_DATA_FORMAT 0x0b33 +#define CCS_R_COLOR_TEMPERATURE (0x0b8c | CCS_FL_16BIT) +#define CCS_R_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT) +#define CCS_R_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT) +#define CCS_R_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT) +#define CCS_R_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT) +#define CCS_R_CFA_CONVERSION_CTRL 0x0ba0 +#define CCS_CFA_CONVERSION_CTRL_BAYER_CONVERSION_ENABLE BIT(0) +#define CCS_R_FLASH_STROBE_ADJUSTMENT 0x0c12 +#define CCS_R_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT) +#define CCS_R_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT) +#define CCS_R_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT) +#define CCS_R_FLASH_MODE_RS 0x0c1a +#define CCS_FLASH_MODE_RS_CONTINUOUS BIT(0) +#define CCS_FLASH_MODE_RS_TRUNCATE BIT(1) +#define CCS_FLASH_MODE_RS_ASYNC BIT(3) +#define CCS_R_FLASH_TRIGGER_RS 0x0c1b +#define CCS_R_FLASH_STATUS 0x0c1c +#define CCS_FLASH_STATUS_RETIMED BIT(0) +#define CCS_R_SA_STROBE_MODE 0x0c1d +#define CCS_SA_STROBE_MODE_CONTINUOUS BIT(0) +#define CCS_SA_STROBE_MODE_TRUNCATE BIT(1) +#define CCS_SA_STROBE_MODE_ASYNC BIT(3) +#define CCS_SA_STROBE_MODE_ADJUST_EDGE BIT(4) +#define CCS_R_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT) +#define CCS_R_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT) +#define CCS_R_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT) +#define CCS_R_SA_STROBE_TRIGGER 0x0c24 +#define CCS_R_SA_STROBE_STATUS 0x0c25 +#define CCS_SA_STROBE_STATUS_RETIMED BIT(0) +#define CCS_R_TSA_STROBE_RE_DELAY_CTRL (0x0c30 | CCS_FL_16BIT) +#define CCS_R_TSA_STROBE_FE_DELAY_CTRL (0x0c32 | CCS_FL_16BIT) +#define CCS_R_PDAF_CTRL (0x0d00 | CCS_FL_16BIT) +#define CCS_PDAF_CTRL_ENABLE BIT(0) +#define CCS_PDAF_CTRL_PROCESSED BIT(1) +#define CCS_PDAF_CTRL_INTERLEAVED BIT(2) +#define CCS_PDAF_CTRL_VISIBLE_PDAF_CORRECTION BIT(3) +#define CCS_R_PDAF_VC 0x0d02 +#define CCS_R_PDAF_DT 0x0d03 +#define CCS_R_PD_X_ADDR_START (0x0d04 | CCS_FL_16BIT) +#define CCS_R_PD_Y_ADDR_START (0x0d06 | CCS_FL_16BIT) +#define CCS_R_PD_X_ADDR_END (0x0d08 | CCS_FL_16BIT) +#define CCS_R_PD_Y_ADDR_END (0x0d0a | CCS_FL_16BIT) +#define CCS_R_BRACKETING_LUT_CTRL 0x0e00 +#define CCS_R_BRACKETING_LUT_MODE 0x0e01 +#define CCS_BRACKETING_LUT_MODE_CONTINUE_STREAMING BIT(0) +#define CCS_BRACKETING_LUT_MODE_LOOP_MODE BIT(1) +#define CCS_R_BRACKETING_LUT_ENTRY_CTRL 0x0e02 +#define CCS_R_BRACKETING_LUT_FRAME(n) (0x0e10 + (n)) +#define CCS_LIM_BRACKETING_LUT_FRAME_MIN_N 0U +#define CCS_LIM_BRACKETING_LUT_FRAME_MAX_N 239U +#define CCS_R_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT) +#define CCS_INTEGRATION_TIME_CAPABILITY_FINE BIT(0) +#define CCS_R_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT) +#define CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT) +#define CCS_R_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT) +#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT) +#define CCS_R_DIGITAL_GAIN_CAPABILITY 0x1081 +#define CCS_DIGITAL_GAIN_CAPABILITY_NONE 0U +#define CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL 2U +#define CCS_R_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT) +#define CCS_R_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT) +#define CCS_R_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT) +#define CCS_R_PEDESTAL_CAPABILITY 0x10e0 +#define CCS_R_ADC_CAPABILITY 0x10f0 +#define CCS_ADC_CAPABILITY_BIT_DEPTH_CTRL BIT(0) +#define CCS_R_ADC_BIT_DEPTH_CAPABILITY (0x10f4 | CCS_FL_32BIT) +#define CCS_R_MIN_EXT_CLK_FREQ_MHZ (0x1100 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_EXT_CLK_FREQ_MHZ (0x1104 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT) +#define CCS_R_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT) +#define CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ (0x110c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ (0x1110 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT) +#define CCS_R_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT) +#define CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ (0x1118 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ (0x111c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT) +#define CCS_R_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT) +#define CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ (0x1124 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ (0x1128 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ (0x112c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ (0x1130 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT) +#define CCS_R_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT) +#define CCS_R_CLOCK_CALCULATION 0x1138 +#define CCS_CLOCK_CALCULATION_LANE_SPEED BIT(0) +#define CCS_CLOCK_CALCULATION_LINK_DECOUPLED BIT(1) +#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_SYS_DDR BIT(2) +#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_PIX_DDR BIT(3) +#define CCS_R_NUM_OF_VT_LANES 0x1139 +#define CCS_R_NUM_OF_OP_LANES 0x113a +#define CCS_R_OP_BITS_PER_LANE 0x113b +#define CCS_R_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT) +#define CCS_R_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT) +#define CCS_R_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT) +#define CCS_R_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT) +#define CCS_R_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT) +#define CCS_R_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT) +#define CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c +#define CCS_R_TIMING_MODE_CAPABILITY 0x114d +#define CCS_TIMING_MODE_CAPABILITY_AUTO_FRAME_LENGTH BIT(0) +#define CCS_TIMING_MODE_CAPABILITY_ROLLING_SHUTTER_MANUAL_READOUT BIT(2) +#define CCS_TIMING_MODE_CAPABILITY_DELAYED_EXPOSURE_START BIT(3) +#define CCS_TIMING_MODE_CAPABILITY_MANUAL_EXPOSURE_EMBEDDED_DATA BIT(4) +#define CCS_R_FRAME_MARGIN_MAX_VALUE (0x114e | CCS_FL_16BIT) +#define CCS_R_FRAME_MARGIN_MIN_VALUE 0x1150 +#define CCS_R_GAIN_DELAY_TYPE 0x1151 +#define CCS_GAIN_DELAY_TYPE_FIXED 0U +#define CCS_GAIN_DELAY_TYPE_VARIABLE 1U +#define CCS_R_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT) +#define CCS_R_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT) +#define CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ (0x1164 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ (0x1168 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT) +#define CCS_R_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT) +#define CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ (0x1170 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ (0x1174 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_X_ADDR_MIN (0x1180 | CCS_FL_16BIT) +#define CCS_R_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT) +#define CCS_R_X_ADDR_MAX (0x1184 | CCS_FL_16BIT) +#define CCS_R_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT) +#define CCS_R_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT) +#define CCS_R_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT) +#define CCS_R_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT) +#define CCS_R_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT) +#define CCS_R_X_ADDR_START_DIV_CONSTANT 0x1190 +#define CCS_R_Y_ADDR_START_DIV_CONSTANT 0x1191 +#define CCS_R_X_ADDR_END_DIV_CONSTANT 0x1192 +#define CCS_R_Y_ADDR_END_DIV_CONSTANT 0x1193 +#define CCS_R_X_SIZE_DIV 0x1194 +#define CCS_R_Y_SIZE_DIV 0x1195 +#define CCS_R_X_OUTPUT_DIV 0x1196 +#define CCS_R_Y_OUTPUT_DIV 0x1197 +#define CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT 0x1198 +#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_PIX_ADDR BIT(0) +#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_OUTPUT_RES BIT(1) +#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_CROP_NO_PAD BIT(2) +#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_SIZE_LANE_DEP BIT(3) +#define CCS_R_MIN_OP_PRE_PLL_CLK_DIV (0x11a0 | CCS_FL_16BIT) +#define CCS_R_MAX_OP_PRE_PLL_CLK_DIV (0x11a2 | CCS_FL_16BIT) +#define CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ (0x11a4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ (0x11a8 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_OP_PLL_MULTIPLIER (0x11ac | CCS_FL_16BIT) +#define CCS_R_MAX_OP_PLL_MULTIPLIER (0x11ae | CCS_FL_16BIT) +#define CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ (0x11b0 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ (0x11b4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_CLOCK_TREE_PLL_CAPABILITY 0x11b8 +#define CCS_CLOCK_TREE_PLL_CAPABILITY_DUAL_PLL BIT(0) +#define CCS_CLOCK_TREE_PLL_CAPABILITY_SINGLE_PLL BIT(1) +#define CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER BIT(2) +#define CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV BIT(3) +#define CCS_R_CLOCK_CAPA_TYPE_CAPABILITY 0x11b9 +#define CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL BIT(0) +#define CCS_R_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT) +#define CCS_R_MIN_ODD_INC (0x11c2 | CCS_FL_16BIT) +#define CCS_R_MAX_EVEN_INC (0x11c4 | CCS_FL_16BIT) +#define CCS_R_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT) +#define CCS_R_AUX_SUBSAMP_CAPABILITY 0x11c8 +#define CCS_AUX_SUBSAMP_CAPABILITY_FACTOR_POWER_OF_2 BIT(1) +#define CCS_R_AUX_SUBSAMP_MONO_CAPABILITY 0x11c9 +#define CCS_AUX_SUBSAMP_MONO_CAPABILITY_FACTOR_POWER_OF_2 BIT(1) +#define CCS_R_MONOCHROME_CAPABILITY 0x11ca +#define CCS_MONOCHROME_CAPABILITY_INC_ODD 0U +#define CCS_MONOCHROME_CAPABILITY_INC_EVEN 1U +#define CCS_R_PIXEL_READOUT_CAPABILITY 0x11cb +#define CCS_PIXEL_READOUT_CAPABILITY_BAYER 0U +#define CCS_PIXEL_READOUT_CAPABILITY_MONOCHROME 1U +#define CCS_PIXEL_READOUT_CAPABILITY_BAYER_AND_MONO 2U +#define CCS_R_MIN_EVEN_INC_MONO (0x11cc | CCS_FL_16BIT) +#define CCS_R_MAX_EVEN_INC_MONO (0x11ce | CCS_FL_16BIT) +#define CCS_R_MIN_ODD_INC_MONO (0x11d0 | CCS_FL_16BIT) +#define CCS_R_MAX_ODD_INC_MONO (0x11d2 | CCS_FL_16BIT) +#define CCS_R_MIN_EVEN_INC_BC2 (0x11d4 | CCS_FL_16BIT) +#define CCS_R_MAX_EVEN_INC_BC2 (0x11d6 | CCS_FL_16BIT) +#define CCS_R_MIN_ODD_INC_BC2 (0x11d8 | CCS_FL_16BIT) +#define CCS_R_MAX_ODD_INC_BC2 (0x11da | CCS_FL_16BIT) +#define CCS_R_MIN_EVEN_INC_MONO_BC2 (0x11dc | CCS_FL_16BIT) +#define CCS_R_MAX_EVEN_INC_MONO_BC2 (0x11de | CCS_FL_16BIT) +#define CCS_R_MIN_ODD_INC_MONO_BC2 (0x11f0 | CCS_FL_16BIT) +#define CCS_R_MAX_ODD_INC_MONO_BC2 (0x11f2 | CCS_FL_16BIT) +#define CCS_R_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT) +#define CCS_SCALING_CAPABILITY_NONE 0U +#define CCS_SCALING_CAPABILITY_HORIZONTAL 1U +#define CCS_SCALING_CAPABILITY_RESERVED 2U +#define CCS_R_SCALER_M_MIN (0x1204 | CCS_FL_16BIT) +#define CCS_R_SCALER_M_MAX (0x1206 | CCS_FL_16BIT) +#define CCS_R_SCALER_N_MIN (0x1208 | CCS_FL_16BIT) +#define CCS_R_SCALER_N_MAX (0x120a | CCS_FL_16BIT) +#define CCS_R_DIGITAL_CROP_CAPABILITY 0x120e +#define CCS_DIGITAL_CROP_CAPABILITY_NONE 0U +#define CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1U +#define CCS_R_HDR_CAPABILITY_1 0x1210 +#define CCS_HDR_CAPABILITY_1_2X2_BINNING BIT(0) +#define CCS_HDR_CAPABILITY_1_COMBINED_ANALOG_GAIN BIT(1) +#define CCS_HDR_CAPABILITY_1_SEPARATE_ANALOG_GAIN BIT(2) +#define CCS_HDR_CAPABILITY_1_UPSCALING BIT(3) +#define CCS_HDR_CAPABILITY_1_RESET_SYNC BIT(4) +#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_TIMING BIT(5) +#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_SYNTHESIS BIT(6) +#define CCS_R_MIN_HDR_BIT_DEPTH 0x1211 +#define CCS_R_HDR_RESOLUTION_SUB_TYPES 0x1212 +#define CCS_R_HDR_RESOLUTION_SUB_TYPE(n) (0x1213 + (n)) +#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MIN_N 0U +#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MAX_N 1U +#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_SHIFT 0U +#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_MASK 0xf +#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_SHIFT 4U +#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_MASK 0xf0 +#define CCS_R_HDR_CAPABILITY_2 0x121b +#define CCS_HDR_CAPABILITY_2_COMBINED_DIGITAL_GAIN BIT(0) +#define CCS_HDR_CAPABILITY_2_SEPARATE_DIGITAL_GAIN BIT(1) +#define CCS_HDR_CAPABILITY_2_TIMING_MODE BIT(3) +#define CCS_HDR_CAPABILITY_2_SYNTHESIS_MODE BIT(4) +#define CCS_R_MAX_HDR_BIT_DEPTH 0x121c +#define CCS_R_USL_SUPPORT_CAPABILITY 0x1230 +#define CCS_USL_SUPPORT_CAPABILITY_CLOCK_TREE BIT(0) +#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_TREE BIT(1) +#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_CALC BIT(2) +#define CCS_R_USL_CLOCK_MODE_D_CAPABILITY 0x1231 +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_STANDBY BIT(0) +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_VBLANK BIT(1) +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_HBLANK BIT(2) +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_STANDBY BIT(3) +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_VBLANK BIT(4) +#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_HBLANK BIT(5) +#define CCS_R_MIN_OP_SYS_CLK_DIV_REV 0x1234 +#define CCS_R_MAX_OP_SYS_CLK_DIV_REV 0x1236 +#define CCS_R_MIN_OP_PIX_CLK_DIV_REV 0x1238 +#define CCS_R_MAX_OP_PIX_CLK_DIV_REV 0x123a +#define CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ (0x123c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ (0x1240 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ (0x1244 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ (0x1248 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) +#define CCS_R_MAX_BITRATE_REV_D_MODE_MBPS (0x124c | (CCS_FL_32BIT | CCS_FL_IREAL)) +#define CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS (0x1250 | (CCS_FL_32BIT | CCS_FL_IREAL)) +#define CCS_R_COMPRESSION_CAPABILITY 0x1300 +#define CCS_COMPRESSION_CAPABILITY_DPCM_PCM_SIMPLE BIT(0) +#define CCS_R_TEST_MODE_CAPABILITY (0x1310 | CCS_FL_16BIT) +#define CCS_TEST_MODE_CAPABILITY_SOLID_COLOR BIT(0) +#define CCS_TEST_MODE_CAPABILITY_COLOR_BARS BIT(1) +#define CCS_TEST_MODE_CAPABILITY_FADE_TO_GREY BIT(2) +#define CCS_TEST_MODE_CAPABILITY_PN9 BIT(3) +#define CCS_TEST_MODE_CAPABILITY_COLOR_TILE BIT(5) +#define CCS_R_PN9_DATA_FORMAT1 0x1312 +#define CCS_R_PN9_DATA_FORMAT2 0x1313 +#define CCS_R_PN9_DATA_FORMAT3 0x1314 +#define CCS_R_PN9_DATA_FORMAT4 0x1315 +#define CCS_R_PN9_MISC_CAPABILITY 0x1316 +#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_SHIFT 0U +#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_MASK 0x7 +#define CCS_PN9_MISC_CAPABILITY_COMPRESSION BIT(3) +#define CCS_R_TEST_PATTERN_CAPABILITY 0x1317 +#define CCS_TEST_PATTERN_CAPABILITY_NO_REPEAT BIT(1) +#define CCS_R_PATTERN_SIZE_DIV_M1 0x1318 +#define CCS_R_FIFO_SUPPORT_CAPABILITY 0x1502 +#define CCS_FIFO_SUPPORT_CAPABILITY_NONE 0U +#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING 1U +#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING_OVERRATING 2U +#define CCS_R_PHY_CTRL_CAPABILITY 0x1600 +#define CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL BIT(0) +#define CCS_PHY_CTRL_CAPABILITY_UI_PHY_CTL BIT(1) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_UI_REG_1_CTL BIT(2) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_UI_REG_2_CTL BIT(3) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_CTL BIT(4) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_1_CTL BIT(5) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_2_CTL BIT(6) +#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_CTL BIT(7) +#define CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY 0x1601 +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_4_LANE BIT(3) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_5_LANE BIT(4) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6) +#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7) +#define CCS_R_CSI_SIGNALING_MODE_CAPABILITY 0x1602 +#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_DPHY BIT(2) +#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_CPHY BIT(3) +#define CCS_R_FAST_STANDBY_CAPABILITY 0x1603 +#define CCS_FAST_STANDBY_CAPABILITY_NO_FRAME_TRUNCATION 0U +#define CCS_FAST_STANDBY_CAPABILITY_FRAME_TRUNCATION 1U +#define CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY 0x1604 +#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_CCI_ADDR_CHANGE BIT(0) +#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_2ND_CCI_ADDR BIT(1) +#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_SW_CHANGEABLE_2ND_CCI_ADDR BIT(2) +#define CCS_R_DATA_TYPE_CAPABILITY 0x1605 +#define CCS_DATA_TYPE_CAPABILITY_DPCM_PROGRAMMABLE BIT(0) +#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_DT_PROGRAMMABLE BIT(1) +#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_VC_PROGRAMMABLE BIT(2) +#define CCS_DATA_TYPE_CAPABILITY_EXT_VC_RANGE BIT(3) +#define CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY 0x1606 +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_4_LANE BIT(3) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_5_LANE BIT(4) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6) +#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7) +#define CCS_R_EMB_DATA_CAPABILITY 0x1607 +#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW16 BIT(0) +#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW20 BIT(1) +#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW24 BIT(2) +#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW16 BIT(3) +#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW20 BIT(4) +#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW24 BIT(5) +#define CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(n) ((0x1608 | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x32 + ((n) - 4) * 4)) +#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MIN_N 0U +#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MAX_N 7U +#define CCS_R_TEMP_SENSOR_CAPABILITY 0x1618 +#define CCS_TEMP_SENSOR_CAPABILITY_SUPPORTED BIT(0) +#define CCS_TEMP_SENSOR_CAPABILITY_CCS_FORMAT BIT(1) +#define CCS_TEMP_SENSOR_CAPABILITY_RESET_0X80 BIT(2) +#define CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(n) ((0x161a | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x30 + ((n) - 4) * 4)) +#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MIN_N 0U +#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MAX_N 7U +#define CCS_R_DPHY_EQUALIZATION_CAPABILITY 0x162b +#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0) +#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ1 BIT(1) +#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ2 BIT(2) +#define CCS_R_CPHY_EQUALIZATION_CAPABILITY 0x162c +#define CCS_CPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0) +#define CCS_R_DPHY_PREAMBLE_CAPABILITY 0x162d +#define CCS_DPHY_PREAMBLE_CAPABILITY_PREAMBLE_SEQ_CTRL BIT(0) +#define CCS_R_DPHY_SSC_CAPABILITY 0x162e +#define CCS_DPHY_SSC_CAPABILITY_SUPPORTED BIT(0) +#define CCS_R_CPHY_CALIBRATION_CAPABILITY 0x162f +#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0) +#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1) +#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_1_CTRL BIT(2) +#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_2_CTRL BIT(3) +#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_3_CTRL BIT(4) +#define CCS_R_DPHY_CALIBRATION_CAPABILITY 0x1630 +#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0) +#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1) +#define CCS_DPHY_CALIBRATION_CAPABILITY_ALTERNATE_SEQ BIT(2) +#define CCS_R_PHY_CTRL_CAPABILITY_2 0x1631 +#define CCS_PHY_CTRL_CAPABILITY_2_TGR_LENGTH BIT(0) +#define CCS_PHY_CTRL_CAPABILITY_2_TGR_PREAMBLE_PROG_SEQ BIT(1) +#define CCS_PHY_CTRL_CAPABILITY_2_EXTRA_CPHY_MANUAL_TIMING BIT(2) +#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_CDPHY BIT(3) +#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_DPHY BIT(4) +#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_CPHY BIT(5) +#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY BIT(6) +#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY BIT(7) +#define CCS_R_LRTE_CPHY_CAPABILITY 0x1632 +#define CCS_LRTE_CPHY_CAPABILITY_PDQ_SHORT BIT(0) +#define CCS_LRTE_CPHY_CAPABILITY_SPACER_SHORT BIT(1) +#define CCS_LRTE_CPHY_CAPABILITY_PDQ_LONG BIT(2) +#define CCS_LRTE_CPHY_CAPABILITY_SPACER_LONG BIT(3) +#define CCS_LRTE_CPHY_CAPABILITY_SPACER_NO_PDQ BIT(4) +#define CCS_R_LRTE_DPHY_CAPABILITY 0x1633 +#define CCS_LRTE_DPHY_CAPABILITY_PDQ_SHORT_OPT1 BIT(0) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_SHORT_OPT1 BIT(1) +#define CCS_LRTE_DPHY_CAPABILITY_PDQ_LONG_OPT1 BIT(2) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_LONG_OPT1 BIT(3) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_SHORT_OPT2 BIT(4) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_LONG_OPT2 BIT(5) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_NO_PDQ_OPT1 BIT(6) +#define CCS_LRTE_DPHY_CAPABILITY_SPACER_VARIABLE_OPT2 BIT(7) +#define CCS_R_ALPS_CAPABILITY_DPHY 0x1634 +#define CCS_ALPS_CAPABILITY_DPHY_LVLP_NOT_SUPPORTED 0U +#define CCS_ALPS_CAPABILITY_DPHY_LVLP_SUPPORTED 1U +#define CCS_ALPS_CAPABILITY_DPHY_CONTROLLABLE_LVLP 2U +#define CCS_R_ALPS_CAPABILITY_CPHY 0x1635 +#define CCS_ALPS_CAPABILITY_CPHY_LVLP_NOT_SUPPORTED 0U +#define CCS_ALPS_CAPABILITY_CPHY_LVLP_SUPPORTED 1U +#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_LVLP 2U +#define CCS_ALPS_CAPABILITY_CPHY_ALP_NOT_SUPPORTED 0xc +#define CCS_ALPS_CAPABILITY_CPHY_ALP_SUPPORTED 0xd +#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_ALP 0xe +#define CCS_R_SCRAMBLING_CAPABILITY 0x1636 +#define CCS_SCRAMBLING_CAPABILITY_SCRAMBLING_SUPPORTED BIT(0) +#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_SHIFT 1U +#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_MASK 0x6 +#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_1 0U +#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_4 3U +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_SHIFT 3U +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_MASK 0x38 +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_0 0U +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_1 1U +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_4 4U +#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_PER_LANE BIT(6) +#define CCS_R_DPHY_MANUAL_CONSTANT 0x1637 +#define CCS_R_CPHY_MANUAL_CONSTANT 0x1638 +#define CCS_R_CSI2_INTERFACE_CAPABILITY_MISC 0x1639 +#define CCS_CSI2_INTERFACE_CAPABILITY_MISC_EOTP_SHORT_PKT_OPT2 BIT(0) +#define CCS_R_PHY_CTRL_CAPABILITY_3 0x165c +#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_TIMING_NOT_MULTIPLE BIT(0) +#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_MIN_TIMING_VALUE_1 BIT(1) +#define CCS_PHY_CTRL_CAPABILITY_3_TWAKEUP_SUPPORTED BIT(2) +#define CCS_PHY_CTRL_CAPABILITY_3_TINIT_SUPPORTED BIT(3) +#define CCS_PHY_CTRL_CAPABILITY_3_THS_EXIT_SUPPORTED BIT(4) +#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_TIMING_NOT_MULTIPLE BIT(5) +#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_MIN_TIMING_VALUE_1 BIT(6) +#define CCS_R_DPHY_SF 0x165d +#define CCS_R_CPHY_SF 0x165e +#define CCS_CPHY_SF_TWAKEUP_SHIFT 0U +#define CCS_CPHY_SF_TWAKEUP_MASK 0xf +#define CCS_CPHY_SF_TINIT_SHIFT 4U +#define CCS_CPHY_SF_TINIT_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_1 0x165f +#define CCS_DPHY_LIMITS_1_THS_PREPARE_SHIFT 0U +#define CCS_DPHY_LIMITS_1_THS_PREPARE_MASK 0xf +#define CCS_DPHY_LIMITS_1_THS_ZERO_SHIFT 4U +#define CCS_DPHY_LIMITS_1_THS_ZERO_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_2 0x1660 +#define CCS_DPHY_LIMITS_2_THS_TRAIL_SHIFT 0U +#define CCS_DPHY_LIMITS_2_THS_TRAIL_MASK 0xf +#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_SHIFT 4U +#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_3 0x1661 +#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_SHIFT 0U +#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_MASK 0xf +#define CCS_DPHY_LIMITS_3_TCLK_ZERO_SHIFT 4U +#define CCS_DPHY_LIMITS_3_TCLK_ZERO_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_4 0x1662 +#define CCS_DPHY_LIMITS_4_TCLK_POST_SHIFT 0U +#define CCS_DPHY_LIMITS_4_TCLK_POST_MASK 0xf +#define CCS_DPHY_LIMITS_4_TLPX_SHIFT 4U +#define CCS_DPHY_LIMITS_4_TLPX_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_5 0x1663 +#define CCS_DPHY_LIMITS_5_THS_EXIT_SHIFT 0U +#define CCS_DPHY_LIMITS_5_THS_EXIT_MASK 0xf +#define CCS_DPHY_LIMITS_5_TWAKEUP_SHIFT 4U +#define CCS_DPHY_LIMITS_5_TWAKEUP_MASK 0xf0 +#define CCS_R_DPHY_LIMITS_6 0x1664 +#define CCS_DPHY_LIMITS_6_TINIT_SHIFT 0U +#define CCS_DPHY_LIMITS_6_TINIT_MASK 0xf +#define CCS_R_CPHY_LIMITS_1 0x1665 +#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_SHIFT 0U +#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_MASK 0xf +#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_SHIFT 4U +#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_MASK 0xf0 +#define CCS_R_CPHY_LIMITS_2 0x1666 +#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_SHIFT 0U +#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_MASK 0xf +#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_SHIFT 4U +#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_MASK 0xf0 +#define CCS_R_CPHY_LIMITS_3 0x1667 +#define CCS_CPHY_LIMITS_3_TINIT_MAX_SHIFT 0U +#define CCS_CPHY_LIMITS_3_TINIT_MAX_MASK 0xf +#define CCS_R_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT) +#define CCS_R_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT) +#define CCS_R_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT) +#define CCS_R_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT) +#define CCS_R_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT) +#define CCS_R_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT) +#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT) +#define CCS_R_BINNING_CAPABILITY 0x1710 +#define CCS_BINNING_CAPABILITY_UNSUPPORTED 0U +#define CCS_BINNING_CAPABILITY_BINNING_THEN_SUBSAMPLING 1U +#define CCS_BINNING_CAPABILITY_SUBSAMPLING_THEN_BINNING 2U +#define CCS_R_BINNING_WEIGHTING_CAPABILITY 0x1711 +#define CCS_BINNING_WEIGHTING_CAPABILITY_AVERAGED BIT(0) +#define CCS_BINNING_WEIGHTING_CAPABILITY_SUMMED BIT(1) +#define CCS_BINNING_WEIGHTING_CAPABILITY_BAYER_CORRECTED BIT(2) +#define CCS_BINNING_WEIGHTING_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3) +#define CCS_R_BINNING_SUB_TYPES 0x1712 +#define CCS_R_BINNING_SUB_TYPE(n) (0x1713 + (n)) +#define CCS_LIM_BINNING_SUB_TYPE_MIN_N 0U +#define CCS_LIM_BINNING_SUB_TYPE_MAX_N 63U +#define CCS_BINNING_SUB_TYPE_ROW_SHIFT 0U +#define CCS_BINNING_SUB_TYPE_ROW_MASK 0xf +#define CCS_BINNING_SUB_TYPE_COLUMN_SHIFT 4U +#define CCS_BINNING_SUB_TYPE_COLUMN_MASK 0xf0 +#define CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY 0x1771 +#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_AVERAGED BIT(0) +#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_SUMMED BIT(1) +#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_BAYER_CORRECTED BIT(2) +#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3) +#define CCS_R_BINNING_SUB_TYPES_MONO 0x1772 +#define CCS_R_BINNING_SUB_TYPE_MONO(n) (0x1773 + (n)) +#define CCS_LIM_BINNING_SUB_TYPE_MONO_MIN_N 0U +#define CCS_LIM_BINNING_SUB_TYPE_MONO_MAX_N 63U +#define CCS_R_DATA_TRANSFER_IF_CAPABILITY 0x1800 +#define CCS_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED BIT(0) +#define CCS_DATA_TRANSFER_IF_CAPABILITY_POLLING BIT(2) +#define CCS_R_SHADING_CORRECTION_CAPABILITY 0x1900 +#define CCS_SHADING_CORRECTION_CAPABILITY_COLOR_SHADING BIT(0) +#define CCS_SHADING_CORRECTION_CAPABILITY_LUMINANCE_CORRECTION BIT(1) +#define CCS_R_GREEN_IMBALANCE_CAPABILITY 0x1901 +#define CCS_GREEN_IMBALANCE_CAPABILITY_SUPPORTED BIT(0) +#define CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903 +#define CCS_R_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT) +#define CCS_DEFECT_CORRECTION_CAPABILITY_MAPPED_DEFECT BIT(0) +#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_COUPLET BIT(2) +#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_SINGLE BIT(5) +#define CCS_DEFECT_CORRECTION_CAPABILITY_COMBINED_DYNAMIC BIT(8) +#define CCS_R_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT) +#define CCS_DEFECT_CORRECTION_CAPABILITY_2_DYNAMIC_TRIPLET BIT(3) +#define CCS_R_NF_CAPABILITY 0x1908 +#define CCS_NF_CAPABILITY_LUMA BIT(0) +#define CCS_NF_CAPABILITY_CHROMA BIT(1) +#define CCS_NF_CAPABILITY_COMBINED BIT(2) +#define CCS_R_OB_READOUT_CAPABILITY 0x1980 +#define CCS_OB_READOUT_CAPABILITY_CONTROLLABLE_READOUT BIT(0) +#define CCS_OB_READOUT_CAPABILITY_VISIBLE_PIXEL_READOUT BIT(1) +#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_VC_READOUT BIT(2) +#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_DT_READOUT BIT(3) +#define CCS_OB_READOUT_CAPABILITY_PROG_DATA_FORMAT BIT(4) +#define CCS_R_COLOR_FEEDBACK_CAPABILITY 0x1987 +#define CCS_COLOR_FEEDBACK_CAPABILITY_KELVIN BIT(0) +#define CCS_COLOR_FEEDBACK_CAPABILITY_AWB_GAIN BIT(1) +#define CCS_R_CFA_PATTERN_CAPABILITY 0x1990 +#define CCS_CFA_PATTERN_CAPABILITY_BAYER 0U +#define CCS_CFA_PATTERN_CAPABILITY_MONOCHROME 1U +#define CCS_CFA_PATTERN_CAPABILITY_4X4_QUAD_BAYER 2U +#define CCS_CFA_PATTERN_CAPABILITY_VENDOR_SPECIFIC 3U +#define CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY 0x1991 +#define CCS_CFA_PATTERN_CONVERSION_CAPABILITY_BAYER BIT(0) +#define CCS_R_FLASH_MODE_CAPABILITY 0x1a02 +#define CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE BIT(0) +#define CCS_R_SA_STROBE_MODE_CAPABILITY 0x1a03 +#define CCS_SA_STROBE_MODE_CAPABILITY_FIXED_WIDTH BIT(0) +#define CCS_SA_STROBE_MODE_CAPABILITY_EDGE_CTRL BIT(1) +#define CCS_R_RESET_MAX_DELAY 0x1a10 +#define CCS_R_RESET_MIN_TIME 0x1a11 +#define CCS_R_PDAF_CAPABILITY_1 0x1b80 +#define CCS_PDAF_CAPABILITY_1_SUPPORTED BIT(0) +#define CCS_PDAF_CAPABILITY_1_PROCESSED_BOTTOM_EMBEDDED BIT(1) +#define CCS_PDAF_CAPABILITY_1_PROCESSED_INTERLEAVED BIT(2) +#define CCS_PDAF_CAPABILITY_1_RAW_BOTTOM_EMBEDDED BIT(3) +#define CCS_PDAF_CAPABILITY_1_RAW_INTERLEAVED BIT(4) +#define CCS_PDAF_CAPABILITY_1_VISIBLE_PDAF_CORRECTION BIT(5) +#define CCS_PDAF_CAPABILITY_1_VC_INTERLEAVING BIT(6) +#define CCS_PDAF_CAPABILITY_1_DT_INTERLEAVING BIT(7) +#define CCS_R_PDAF_CAPABILITY_2 0x1b81 +#define CCS_PDAF_CAPABILITY_2_ROI BIT(0) +#define CCS_PDAF_CAPABILITY_2_AFTER_DIGITAL_CROP BIT(1) +#define CCS_PDAF_CAPABILITY_2_CTRL_RETIMED BIT(2) +#define CCS_R_BRACKETING_LUT_CAPABILITY_1 0x1c00 +#define CCS_BRACKETING_LUT_CAPABILITY_1_COARSE_INTEGRATION BIT(0) +#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_ANALOG_GAIN BIT(1) +#define CCS_BRACKETING_LUT_CAPABILITY_1_FLASH BIT(4) +#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_DIGITAL_GAIN BIT(5) +#define CCS_BRACKETING_LUT_CAPABILITY_1_ALTERNATE_GLOBAL_ANALOG_GAIN BIT(6) +#define CCS_R_BRACKETING_LUT_CAPABILITY_2 0x1c01 +#define CCS_BRACKETING_LUT_CAPABILITY_2_SINGLE_BRACKETING_MODE BIT(0) +#define CCS_BRACKETING_LUT_CAPABILITY_2_LOOPED_BRACKETING_MODE BIT(1) +#define CCS_R_BRACKETING_LUT_SIZE 0x1c02 + +#endif /* __CCS_REGS_H__ */ diff --git a/drivers/media/i2c/ccs/ccs.h b/drivers/media/i2c/ccs/ccs.h new file mode 100644 index 000000000000..7f6ed95b7b78 --- /dev/null +++ b/drivers/media/i2c/ccs/ccs.h @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * drivers/media/i2c/smiapp/ccs.h + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2010--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#ifndef __CCS_H__ +#define __CCS_H__ + +#include +#include +#include + +#include "ccs-quirk.h" +#include "ccs-regs.h" +#include "ccs-reg-access.h" +#include "../smiapp-pll.h" +#include "smiapp-reg-defs.h" + +/* + * Standard SMIA++ constants + */ +#define SMIA_VERSION_1 10 +#define SMIAPP_VERSION_0_8 8 /* Draft 0.8 */ +#define SMIAPP_VERSION_0_9 9 /* Draft 0.9 */ +#define SMIAPP_VERSION_1 10 + +#define SMIAPP_PROFILE_0 0 +#define SMIAPP_PROFILE_1 1 +#define SMIAPP_PROFILE_2 2 + +#define SMIAPP_NVM_PAGE_SIZE 64 /* bytes */ + +#define SMIAPP_RESET_DELAY_CLOCKS 2400 +#define SMIAPP_RESET_DELAY(clk) \ + (1000 + (SMIAPP_RESET_DELAY_CLOCKS * 1000 \ + + (clk) / 1000 - 1) / ((clk) / 1000)) + +#define CCS_COLOUR_COMPONENTS 4 + +#define SMIAPP_NAME "smiapp" +#define CCS_NAME "ccs" + +#define CCS_DFL_I2C_ADDR (0x20 >> 1) /* Default I2C Address */ +#define CCS_ALT_I2C_ADDR (0x6e >> 1) /* Alternate I2C Address */ + +/* + * Sometimes due to board layout considerations the camera module can be + * mounted rotated. The typical rotation used is 180 degrees which can be + * corrected by giving a default H-FLIP and V-FLIP in the sensor readout. + * FIXME: rotation also changes the bayer pattern. + */ +enum ccs_module_board_orient { + CCS_MODULE_BOARD_ORIENT_0 = 0, + CCS_MODULE_BOARD_ORIENT_180, +}; + +struct ccs_flash_strobe_parms { + u8 mode; + u32 strobe_width_high_us; + u16 strobe_delay; + u16 stobe_start_point; + u8 trigger; +}; + +struct ccs_hwconfig { + /* + * Change the cci address if i2c_addr_alt is set. + * Both default and alternate cci addr need to be present + */ + unsigned short i2c_addr_dfl; /* Default i2c addr */ + unsigned short i2c_addr_alt; /* Alternate i2c addr */ + + uint32_t ext_clk; /* sensor external clk */ + + unsigned int lanes; /* Number of CSI-2 lanes */ + uint32_t csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */ + uint64_t *op_sys_clock; + + enum ccs_module_board_orient module_board_orient; + + struct ccs_flash_strobe_parms *strobe_setup; +}; + +struct ccs_quirk; + +#define CCS_MODULE_IDENT_FLAG_REV_LE (1 << 0) + +struct ccs_module_ident { + u16 mipi_manufacturer_id; + u16 model_id; + u8 smia_manufacturer_id; + u8 revision_number_major; + + u8 flags; + + char *name; + const struct ccs_quirk *quirk; +}; + +struct ccs_module_info { + u32 smia_manufacturer_id; + u32 mipi_manufacturer_id; + u32 model_id; + u32 revision_number_major; + u32 revision_number_minor; + + u32 module_year; + u32 module_month; + u32 module_day; + + u32 sensor_smia_manufacturer_id; + u32 sensor_mipi_manufacturer_id; + u32 sensor_model_id; + u32 sensor_revision_number; + u32 sensor_firmware_version; + + u32 smia_version; + u32 smiapp_version; + u32 ccs_version; + + u32 smiapp_profile; + + char *name; + const struct ccs_quirk *quirk; +}; + +#define CCS_IDENT_FQ(manufacturer, model, rev, fl, _name, _quirk) \ + { .smia_manufacturer_id = manufacturer, \ + .model_id = model, \ + .revision_number_major = rev, \ + .flags = fl, \ + .name = _name, \ + .quirk = _quirk, } + +#define CCS_IDENT_LQ(manufacturer, model, rev, _name, _quirk) \ + { .smia_manufacturer_id = manufacturer, \ + .model_id = model, \ + .revision_number_major = rev, \ + .flags = CCS_MODULE_IDENT_FLAG_REV_LE, \ + .name = _name, \ + .quirk = _quirk, } + +#define CCS_IDENT_L(manufacturer, model, rev, _name) \ + { .smia_manufacturer_id = manufacturer, \ + .model_id = model, \ + .revision_number_major = rev, \ + .flags = CCS_MODULE_IDENT_FLAG_REV_LE, \ + .name = _name, } + +#define CCS_IDENT_Q(manufacturer, model, rev, _name, _quirk) \ + { .smia_manufacturer_id = manufacturer, \ + .model_id = model, \ + .revision_number_major = rev, \ + .flags = 0, \ + .name = _name, \ + .quirk = _quirk, } + +#define CCS_IDENT(manufacturer, model, rev, _name) \ + { .smia_manufacturer_id = manufacturer, \ + .model_id = model, \ + .revision_number_major = rev, \ + .flags = 0, \ + .name = _name, } + +struct ccs_csi_data_format { + u32 code; + u8 width; + u8 compressed; + u8 pixel_order; +}; + +#define CCS_SUBDEVS 3 + +#define CCS_PA_PAD_SRC 0 +#define CCS_PAD_SINK 0 +#define CCS_PAD_SRC 1 +#define CCS_PADS 2 + +struct ccs_binning_subtype { + u8 horizontal:4; + u8 vertical:4; +} __packed; + +struct ccs_subdev { + struct v4l2_subdev sd; + struct media_pad pads[CCS_PADS]; + struct v4l2_rect sink_fmt; + struct v4l2_rect crop[CCS_PADS]; + struct v4l2_rect compose; /* compose on sink */ + unsigned short sink_pad; + unsigned short source_pad; + int npads; + struct ccs_sensor *sensor; + struct v4l2_ctrl_handler ctrl_handler; +}; + +/* + * struct ccs_sensor - Main device structure + */ +struct ccs_sensor { + /* + * "mutex" is used to serialise access to all fields here + * except v4l2_ctrls at the end of the struct. "mutex" is also + * used to serialise access to file handle specific + * information. + */ + struct mutex mutex; + struct ccs_subdev ssds[CCS_SUBDEVS]; + u32 ssds_used; + struct ccs_subdev *src; + struct ccs_subdev *binner; + struct ccs_subdev *scaler; + struct ccs_subdev *pixel_array; + struct ccs_hwconfig *hwcfg; + struct regulator *vana; + struct clk *ext_clk; + struct gpio_desc *xshutdown; + void *ccs_limits; + u8 nbinning_subtypes; + struct ccs_binning_subtype binning_subtypes[CCS_LIM_BINNING_SUB_TYPE_MAX_N + 1]; + u32 mbus_frame_fmts; + const struct ccs_csi_data_format *csi_format; + const struct ccs_csi_data_format *internal_csi_format; + u32 default_mbus_frame_fmts; + int default_pixel_order; + + u8 binning_horizontal; + u8 binning_vertical; + + u8 scale_m; + u8 scaling_mode; + + u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ + u8 frame_skip; + u16 embedded_start; /* embedded data start line */ + u16 embedded_end; + u16 image_start; /* image data start line */ + u16 visible_pixel_start; /* start pixel of the visible image */ + + bool streaming; + bool dev_init_done; + u8 compressed_min_bpp; + + struct ccs_module_info minfo; + + struct smiapp_pll pll; + + /* Is a default format supported for a given BPP? */ + unsigned long *valid_link_freqs; + + /* Pixel array controls */ + struct v4l2_ctrl *analog_gain; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *pixel_rate_parray; + /* src controls */ + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate_csi; + /* test pattern colour components */ + struct v4l2_ctrl *test_data[CCS_COLOUR_COMPONENTS]; +}; + +#define to_ccs_subdev(_sd) \ + container_of(_sd, struct ccs_subdev, sd) + +#define to_ccs_sensor(_sd) \ + (to_ccs_subdev(_sd)->sensor) + +void ccs_replace_limit(struct ccs_sensor *sensor, + unsigned int limit, unsigned int offset, u32 val); + +#endif /* __CCS_H__ */ diff --git a/drivers/media/i2c/ccs/smiapp-reg-defs.h b/drivers/media/i2c/ccs/smiapp-reg-defs.h new file mode 100644 index 000000000000..e80c110ebf3a --- /dev/null +++ b/drivers/media/i2c/ccs/smiapp-reg-defs.h @@ -0,0 +1,580 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * drivers/media/i2c/smiapp/smiapp-reg-defs.h + * + * Generic driver for MIPI CCS/SMIA/SMIA++ compliant camera sensors + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#ifndef __SMIAPP_REG_DEFS_H__ +#define __SMIAPP_REG_DEFS_H__ + +/* Register addresses */ +#define SMIAPP_REG_U16_MODEL_ID (0x0000 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR 0x0002 +#define SMIAPP_REG_U8_MANUFACTURER_ID 0x0003 +#define SMIAPP_REG_U8_SMIA_VERSION 0x0004 +#define SMIAPP_REG_U8_FRAME_COUNT 0x0005 +#define SMIAPP_REG_U8_PIXEL_ORDER 0x0006 +#define SMIAPP_REG_U16_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_PIXEL_DEPTH 0x000c +#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR 0x0010 +#define SMIAPP_REG_U8_SMIAPP_VERSION 0x0011 +#define SMIAPP_REG_U8_MODULE_DATE_YEAR 0x0012 +#define SMIAPP_REG_U8_MODULE_DATE_MONTH 0x0013 +#define SMIAPP_REG_U8_MODULE_DATE_DAY 0x0014 +#define SMIAPP_REG_U8_MODULE_DATE_PHASE 0x0015 +#define SMIAPP_REG_U16_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER 0x0018 +#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID 0x0019 +#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION 0x001a +#define SMIAPP_REG_U32_SERIAL_NUMBER (0x001c | CCS_FL_32BIT) +#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE 0x0040 +#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE 0x0041 +#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n) ((0x0042 + ((n) << 1)) | CCS_FL_16BIT) /* 0 <= n <= 14 */ +#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 + ((n) << 2)) | CCS_FL_32BIT) /* 0 <= n <= 7 */ +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE (0x008a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0 (0x008c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0 (0x008e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1 (0x0090 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1 (0x0092 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE 0x00c0 +#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE 0x00c1 +#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 + ((n) << 1)) | CCS_FL_16BIT) +#define SMIAPP_REG_U8_MODE_SELECT 0x0100 +#define SMIAPP_REG_U8_IMAGE_ORIENTATION 0x0101 +#define SMIAPP_REG_U8_SOFTWARE_RESET 0x0103 +#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD 0x0104 +#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES 0x0105 +#define SMIAPP_REG_U8_FAST_STANDBY_CTRL 0x0106 +#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL 0x0107 +#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL 0x0108 +#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL 0x0109 +#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER 0x0110 +#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE 0x0111 +#define SMIAPP_REG_U16_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_CSI_LANE_MODE 0x0114 +#define SMIAPP_REG_U8_CSI2_10_TO_8_DT 0x0115 +#define SMIAPP_REG_U8_CSI2_10_TO_7_DT 0x0116 +#define SMIAPP_REG_U8_CSI2_10_TO_6_DT 0x0117 +#define SMIAPP_REG_U8_CSI2_12_TO_8_DT 0x0118 +#define SMIAPP_REG_U8_CSI2_12_TO_7_DT 0x0119 +#define SMIAPP_REG_U8_CSI2_12_TO_6_DT 0x011a +#define SMIAPP_REG_U8_CSI2_14_TO_10_DT 0x011b +#define SMIAPP_REG_U8_CSI2_14_TO_8_DT 0x011c +#define SMIAPP_REG_U8_CSI2_16_TO_10_DT 0x011d +#define SMIAPP_REG_U8_CSI2_16_TO_8_DT 0x011e +#define SMIAPP_REG_U8_GAIN_MODE 0x0120 +#define SMIAPP_REG_U16_VANA_VOLTAGE (0x0130 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VDIG_VOLTAGE (0x0132 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VIO_VOLTAGE (0x0134 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ (0x0136 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL 0x0138 +#define SMIAPP_REG_U8_TEMP_SENSOR_MODE 0x0139 +#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT 0x013a +#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR (0x0206 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED (0x0208 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE (0x020a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB (0x020c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR (0x020e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_RED (0x0210 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE (0x0212 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB (0x0214 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_ADDR_START (0x0344 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_ADDR_START (0x0346 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_ADDR_END (0x0348 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_ADDR_END (0x034a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_EVEN_INC (0x0380 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_ODD_INC (0x0382 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_EVEN_INC (0x0384 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_ODD_INC (0x0386 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALING_MODE (0x0400 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SPATIAL_SAMPLING (0x0402 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALE_M (0x0404 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALE_N (0x0406 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TEST_DATA_RED (0x0602 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH (0x060a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION (0x060c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH (0x060e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION (0x0610 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS (0x0700 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_TCLK_POST 0x0800 +#define SMIAPP_REG_U8_THS_PREPARE 0x0801 +#define SMIAPP_REG_U8_THS_ZERO_MIN 0x0802 +#define SMIAPP_REG_U8_THS_TRAIL 0x0803 +#define SMIAPP_REG_U8_TCLK_TRAIL_MIN 0x0804 +#define SMIAPP_REG_U8_TCLK_PREPARE 0x0805 +#define SMIAPP_REG_U8_TCLK_ZERO 0x0806 +#define SMIAPP_REG_U8_TLPX 0x0807 +#define SMIAPP_REG_U8_DPHY_CTRL 0x0808 +#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS (0x0820 | CCS_FL_32BIT) +#define SMIAPP_REG_U8_BINNING_MODE 0x0900 +#define SMIAPP_REG_U8_BINNING_TYPE 0x0901 +#define SMIAPP_REG_U8_BINNING_WEIGHTING 0x0902 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL 0x0a00 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS 0x0a01 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 0x0a04 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1 0x0a05 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2 0x0a06 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3 0x0a07 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4 0x0a08 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5 0x0a09 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12 0x0a10 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13 0x0a11 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14 0x0a12 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15 0x0a13 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16 0x0a14 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17 0x0a15 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18 0x0a16 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19 0x0a17 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20 0x0a18 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21 0x0a19 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22 0x0a1a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23 0x0a1b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24 0x0a1c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25 0x0a1d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26 0x0a1e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27 0x0a1f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28 0x0a20 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29 0x0a21 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30 0x0a22 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31 0x0a23 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32 0x0a24 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33 0x0a25 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34 0x0a26 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35 0x0a27 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36 0x0a28 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37 0x0a29 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38 0x0a2a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39 0x0a2b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40 0x0a2c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41 0x0a2d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42 0x0a2e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43 0x0a2f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44 0x0a30 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45 0x0a31 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46 0x0a32 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47 0x0a33 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48 0x0a34 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49 0x0a35 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50 0x0a36 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51 0x0a37 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52 0x0a38 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53 0x0a39 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54 0x0a3a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55 0x0a3b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56 0x0a3c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57 0x0a3d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58 0x0a3e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59 0x0a3f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60 0x0a40 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61 0x0a41 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62 0x0a42 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63 0x0a43 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL 0x0a44 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS 0x0a45 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT 0x0a46 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0 0x0a48 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1 0x0a49 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2 0x0a4a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3 0x0a4b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4 0x0a4c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5 0x0a4d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6 0x0a4e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7 0x0a4f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8 0x0a50 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9 0x0a51 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10 0x0a52 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11 0x0a53 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12 0x0a54 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13 0x0a55 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14 0x0a56 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15 0x0a57 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16 0x0a58 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17 0x0a59 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18 0x0a5a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19 0x0a5b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20 0x0a5c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21 0x0a5d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22 0x0a5e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23 0x0a5f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24 0x0a60 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25 0x0a61 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26 0x0a62 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27 0x0a63 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28 0x0a64 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29 0x0a65 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30 0x0a66 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31 0x0a67 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32 0x0a68 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33 0x0a69 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34 0x0a6a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35 0x0a6b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36 0x0a6c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37 0x0a6d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38 0x0a6e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39 0x0a6f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40 0x0a70 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41 0x0a71 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42 0x0a72 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43 0x0a73 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44 0x0a74 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45 0x0a75 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46 0x0a76 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47 0x0a77 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48 0x0a78 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49 0x0a79 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50 0x0a7a +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51 0x0a7b +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52 0x0a7c +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53 0x0a7d +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54 0x0a7e +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55 0x0a7f +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56 0x0a80 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57 0x0a81 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58 0x0a82 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59 0x0a83 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60 0x0a84 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61 0x0a85 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62 0x0a86 +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63 0x0a87 +#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE 0x0b00 +#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL 0x0b01 +#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE 0x0b02 +#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT 0x0b03 +#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE 0x0b04 +#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE 0x0b05 +#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE 0x0b06 +#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT 0x0b07 +#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE 0x0b08 +#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT 0x0b09 +#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE 0x0b0a +#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT 0x0b0b +#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE 0x0b0c +#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT 0x0b0d +#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE 0x0b0e +#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST 0x0b0f +#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST 0x0b10 +#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b11 +#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b12 +#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b13 +#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b14 +#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE 0x0b15 +#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST 0x0b16 +#define SMIAPP_REG_U8_EDOF_MODE 0x0b80 +#define SMIAPP_REG_U8_SHARPNESS 0x0b83 +#define SMIAPP_REG_U8_DENOISING 0x0b84 +#define SMIAPP_REG_U8_MODULE_SPECIFIC 0x0b85 +#define SMIAPP_REG_U16_DEPTH_OF_FIELD (0x0b86 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FOCUS_DISTANCE (0x0b88 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL 0x0b8a +#define SMIAPP_REG_U16_COLOUR_TEMPERATURE (0x0b8c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE 0x0bc0 +#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING (0x0bc2 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START (0x0bc4 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START (0x0bc6 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH (0x0bc8 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT (0x0bca | CCS_FL_16BIT) +#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1 0x0c00 +#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2 0x0c01 +#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1 0x0c02 +#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2 0x0c03 +#define SMIAPP_REG_U16_TRDY_CTRL (0x0c04 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TRDOUT_CTRL (0x0c06 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL (0x0c08 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL (0x0c0a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL (0x0c0c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL (0x0c0e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL (0x0c10 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT 0x0c12 +#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_FLASH_MODE_RS 0x0c1a +#define SMIAPP_REG_U8_FLASH_TRIGGER_RS 0x0c1b +#define SMIAPP_REG_U8_FLASH_STATUS 0x0c1c +#define SMIAPP_REG_U8_SA_STROBE_MODE 0x0c1d +#define SMIAPP_REG_U16_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_SA_STROBE_TRIGGER 0x0c24 +#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS 0x0c25 +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL (0x0c26 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL (0x0c28 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL 0x0c2a +#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL 0x0c2b +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL (0x0c2c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL (0x0c2e | CCS_FL_16BIT) +#define SMIAPP_REG_U8_LOW_LEVEL_CTRL 0x0c80 +#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT (0x0c82 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAIN_TRIGGER_T3 (0x0c84 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT 0x0c86 +#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3 (0x0c88 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT 0x0c8a +#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3 (0x0c8c | CCS_FL_16BIT) +#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT 0x0c8e +#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL 0x0d00 +#define SMIAPP_REG_U8_OPERATION_MODE 0x0d01 +#define SMIAPP_REG_U8_ACT_STATE1 0x0d02 +#define SMIAPP_REG_U8_ACT_STATE2 0x0d03 +#define SMIAPP_REG_U16_FOCUS_CHANGE (0x0d80 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL (0x0d82 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1 (0x0d84 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2 (0x0d86 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1 0x0d88 +#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2 0x0d89 +#define SMIAPP_REG_U8_POSITION 0x0d8a +#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL 0x0e00 +#define SMIAPP_REG_U8_BRACKETING_LUT_MODE 0x0e01 +#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL 0x0e02 +#define SMIAPP_REG_U8_LUT_PARAMETERS_START 0x0e10 +#define SMIAPP_REG_U8_LUT_PARAMETERS_END 0x0eff +#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY (0x1080 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ (0x1100 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ (0x1104 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ (0x110c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ (0x1110 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ (0x1118 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ (0x111c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ (0x1124 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ (0x1128 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ (0x112c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ (0x1130 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT) +#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c +#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ (0x1164 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ (0x1168 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT) +#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ (0x1170 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ (0x1174 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) +#define SMIAPP_REG_U16_X_ADDR_MIN (0x1180 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_X_ADDR_MAX (0x1184 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_EVEN_INC (0x11c2 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_ODD_INC (0x11c4 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALER_M_MIN (0x1204 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALER_M_MAX (0x1206 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALER_N_MIN (0x1208 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SCALER_N_MAX (0x120a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY (0x120c | CCS_FL_16BIT) +#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY 0x120e +#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY (0x1300 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED (0x1400 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED (0x1402 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED (0x1404 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN (0x1406 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN (0x1408 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN (0x140a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE (0x140c | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE (0x140e | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE (0x1410 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS (0x1500 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY 0x1502 +#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY 0x1600 +#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY 0x1601 +#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY 0x1602 +#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY 0x1603 +#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY 0x1604 +#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS (0x1608 | CCS_FL_32BIT) +#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS (0x160c | CCS_FL_32BIT) +#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS (0x1610 | CCS_FL_32BIT) +#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS (0x1614 | CCS_FL_32BIT) +#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY 0x1618 +#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT) +#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT) +#define SMIAPP_REG_U8_BINNING_CAPABILITY 0x1710 +#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY 0x1711 +#define SMIAPP_REG_U8_BINNING_SUBTYPES 0x1712 +#define SMIAPP_REG_U8_BINNING_TYPE_n(n) (0x1713 + (n)) /* 1 <= n <= 237 */ +#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY 0x1800 +#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY 0x1900 +#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY 0x1901 +#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY 0x1902 +#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903 +#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_EDOF_CAPABILITY 0x1980 +#define SMIAPP_REG_U8_ESTIMATION_FRAMES 0x1981 +#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ 0x1982 +#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ 0x1983 +#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ 0x1984 +#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ 0x1985 +#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ 0x1986 +#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY 0x1987 +#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM 0x1988 +#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY 0x19c0 +#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY 0x19c1 +#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD (0x19c2 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE (0x19c4 | CCS_FL_16BIT) +#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN (0x1a00 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY 0x1a02 +#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR (0x1b02 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY 0x1b04 +#define SMIAPP_REG_U16_ACTUATOR_TYPE (0x1b40 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS 0x1b42 +#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS (0x1b44 | CCS_FL_16BIT) +#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1 0x1c00 +#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2 0x1c01 +#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE 0x1c02 + +/* Register bit definitions */ +#define SMIAPP_IMAGE_ORIENTATION_HFLIP BIT(0) +#define SMIAPP_IMAGE_ORIENTATION_VFLIP BIT(1) + +#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN BIT(0) +#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_WR_EN BIT(1) +#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_ERR_CLEAR BIT(2) +#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY BIT(0) +#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_WR_READY BIT(1) +#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EDATA BIT(2) +#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE BIT(3) + +#define SMIAPP_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED BIT(0) +#define SMIAPP_DATA_TRANSFER_IF_CAPABILITY_POLL BIT(2) + +#define SMIAPP_SOFTWARE_RESET BIT(0) + +#define SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE BIT(0) +#define SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE BIT(1) + +#define SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK 0 +#define SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE 1 +#define SMIAPP_CSI_SIGNALLING_MODE_CSI2 2 + +#define SMIAPP_DPHY_CTRL_AUTOMATIC 0 +/* DPHY control based on REQUESTED_LINK_BIT_RATE_MBPS */ +#define SMIAPP_DPHY_CTRL_UI 1 +#define SMIAPP_DPHY_CTRL_REGISTER 2 + +#define SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR 1 +#define SMIAPP_COMPRESSION_MODE_ADVANCED_PREDICTOR 2 + +#define SMIAPP_MODE_SELECT_SOFTWARE_STANDBY 0 +#define SMIAPP_MODE_SELECT_STREAMING 1 + +#define SMIAPP_SCALING_MODE_NONE 0 +#define SMIAPP_SCALING_MODE_HORIZONTAL 1 +#define SMIAPP_SCALING_MODE_BOTH 2 + +#define SMIAPP_SCALING_CAPABILITY_NONE 0 +#define SMIAPP_SCALING_CAPABILITY_HORIZONTAL 1 +#define SMIAPP_SCALING_CAPABILITY_BOTH 2 /* horizontal/both */ + +/* digital crop right before scaler */ +#define SMIAPP_DIGITAL_CROP_CAPABILITY_NONE 0 +#define SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1 + +#define SMIAPP_BINNING_CAPABILITY_NO 0 +#define SMIAPP_BINNING_CAPABILITY_YES 1 + +/* Maximum number of binning subtypes */ +#define SMIAPP_BINNING_SUBTYPES 253 + +#define SMIAPP_PIXEL_ORDER_GRBG 0 +#define SMIAPP_PIXEL_ORDER_RGGB 1 +#define SMIAPP_PIXEL_ORDER_BGGR 2 +#define SMIAPP_PIXEL_ORDER_GBRG 3 + +#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL 1 +#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED 2 +#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N 8 +#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N 16 + +#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE 0x01 +#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE 0x02 +#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK 0x0f +#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK 0xf0 +#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT 4 + +#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK 0xf000 +#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT 12 +#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK 0x0fff + +#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK 0xf0000000 +#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT 28 +#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK 0x0000ffff + +#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED 1 +#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY 2 +#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK 3 +#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK 4 +#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE 5 + +#define SMIAPP_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0 +#define SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE 1 + +/* Scaling N factor */ +#define SMIAPP_SCALE_N 16 + +#endif /* __SMIAPP_REG_DEFS_H__ */ diff --git a/drivers/media/i2c/smiapp/Kconfig b/drivers/media/i2c/smiapp/Kconfig deleted file mode 100644 index 6893b532824f..000000000000 --- a/drivers/media/i2c/smiapp/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config VIDEO_SMIAPP - tristate "SMIA++/SMIA sensor support" - depends on I2C && VIDEO_V4L2 && HAVE_CLK - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - select VIDEO_SMIAPP_PLL - select V4L2_FWNODE - help - This is a generic driver for SMIA++/SMIA camera modules. diff --git a/drivers/media/i2c/smiapp/Makefile b/drivers/media/i2c/smiapp/Makefile deleted file mode 100644 index c9d300b5d2bc..000000000000 --- a/drivers/media/i2c/smiapp/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -smiapp-objs += ccs-core.o ccs-reg-access.o \ - ccs-quirk.o ccs-limits.o -obj-$(CONFIG_VIDEO_SMIAPP) += smiapp.o - -ccflags-y += -I $(srctree)/drivers/media/i2c diff --git a/drivers/media/i2c/smiapp/ccs-core.c b/drivers/media/i2c/smiapp/ccs-core.c deleted file mode 100644 index 30c4d8edce9d..000000000000 --- a/drivers/media/i2c/smiapp/ccs-core.c +++ /dev/null @@ -1,3300 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/media/i2c/smiapp/ccs-core.c - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2010--2012 Nokia Corporation - * Contact: Sakari Ailus - * - * Based on smiapp driver by Vimarsh Zutshi - * Based on jt8ev1.c by Vimarsh Zutshi - * Based on smia-sensor.c by Tuukka Toivonen - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ccs.h" -#include "ccs-limits.h" - -#define CCS_ALIGN_DIM(dim, flags) \ - ((flags) & V4L2_SEL_FLAG_GE \ - ? ALIGN((dim), 2) \ - : (dim) & ~1) - -static struct ccs_limit_offset { - u16 lim; - u16 info; -} ccs_limit_offsets[CCS_L_LAST + 1]; - -/* - * ccs_module_idents - supported camera modules - */ -static const struct ccs_module_ident ccs_module_idents[] = { - CCS_IDENT_L(0x01, 0x022b, -1, "vs6555"), - CCS_IDENT_L(0x01, 0x022e, -1, "vw6558"), - CCS_IDENT_L(0x07, 0x7698, -1, "ovm7698"), - CCS_IDENT_L(0x0b, 0x4242, -1, "smiapp-003"), - CCS_IDENT_L(0x0c, 0x208a, -1, "tcm8330md"), - CCS_IDENT_LQ(0x0c, 0x2134, -1, "tcm8500md", &smiapp_tcm8500md_quirk), - CCS_IDENT_L(0x0c, 0x213e, -1, "et8en2"), - CCS_IDENT_L(0x0c, 0x2184, -1, "tcm8580md"), - CCS_IDENT_LQ(0x0c, 0x560f, -1, "jt8ew9", &smiapp_jt8ew9_quirk), - CCS_IDENT_LQ(0x10, 0x4141, -1, "jt8ev1", &smiapp_jt8ev1_quirk), - CCS_IDENT_LQ(0x10, 0x4241, -1, "imx125es", &smiapp_imx125es_quirk), -}; - -/* - * - * Dynamic Capability Identification - * - */ - -static void ccs_assign_limit(void *ptr, unsigned int width, u32 val) -{ - switch (width) { - case sizeof(u8): - *(u8 *)ptr = val; - break; - case sizeof(u16): - *(u16 *)ptr = val; - break; - case sizeof(u32): - *(u32 *)ptr = val; - break; - } -} - -static int ccs_limit_ptr(struct ccs_sensor *sensor, unsigned int limit, - unsigned int offset, void **__ptr) -{ - const struct ccs_limit *linfo; - - if (WARN_ON(limit >= CCS_L_LAST)) - return -EINVAL; - - linfo = &ccs_limits[ccs_limit_offsets[limit].info]; - - if (WARN_ON(!sensor->ccs_limits) || - WARN_ON(offset + ccs_reg_width(linfo->reg) > - ccs_limit_offsets[limit + 1].lim)) - return -EINVAL; - - *__ptr = sensor->ccs_limits + ccs_limit_offsets[limit].lim + offset; - - return 0; -} - -void ccs_replace_limit(struct ccs_sensor *sensor, - unsigned int limit, unsigned int offset, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - const struct ccs_limit *linfo; - void *ptr; - int ret; - - ret = ccs_limit_ptr(sensor, limit, offset, &ptr); - if (ret) - return; - - linfo = &ccs_limits[ccs_limit_offsets[limit].info]; - - dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" %u = %d, 0x%x\n", - linfo->reg, linfo->name, offset, val, val); - - ccs_assign_limit(ptr, ccs_reg_width(linfo->reg), val); -} - -static u32 ccs_get_limit(struct ccs_sensor *sensor, - unsigned int limit, unsigned int offset) -{ - void *ptr; - int ret; - - ret = ccs_limit_ptr(sensor, limit, offset, &ptr); - if (ret) - return 0; - - switch (ccs_reg_width(ccs_limits[ccs_limit_offsets[limit].info].reg)) { - case sizeof(u8): - return *(u8 *)ptr; - case sizeof(u16): - return *(u16 *)ptr; - case sizeof(u32): - return *(u32 *)ptr; - } - - WARN_ON(1); - - return 0; -} - -#define CCS_LIM(sensor, limit) \ - ccs_get_limit(sensor, CCS_L_##limit, 0) - -#define CCS_LIM_AT(sensor, limit, offset) \ - ccs_get_limit(sensor, CCS_L_##limit, CCS_L_##limit##_OFFSET(offset)) - -static int ccs_read_all_limits(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - void *ptr, *alloc, *end; - unsigned int i, l; - int ret; - - kfree(sensor->ccs_limits); - sensor->ccs_limits = NULL; - - alloc = kzalloc(ccs_limit_offsets[CCS_L_LAST].lim, GFP_KERNEL); - if (!alloc) - return -ENOMEM; - - end = alloc + ccs_limit_offsets[CCS_L_LAST].lim; - - for (i = 0, l = 0, ptr = alloc; ccs_limits[i].size; i++) { - u32 reg = ccs_limits[i].reg; - unsigned int width = ccs_reg_width(reg); - unsigned int j; - - if (l == CCS_L_LAST) { - dev_err(&client->dev, - "internal error --- end of limit array\n"); - ret = -EINVAL; - goto out_err; - } - - for (j = 0; j < ccs_limits[i].size / width; - j++, reg += width, ptr += width) { - u32 val; - - ret = ccs_read_addr(sensor, reg, &val); - if (ret) - goto out_err; - - if (ptr + width > end) { - dev_err(&client->dev, - "internal error --- no room for regs\n"); - ret = -EINVAL; - goto out_err; - } - - ccs_assign_limit(ptr, width, val); - - dev_dbg(&client->dev, "0x%8.8x \"%s\" = %u, 0x%x\n", - reg, ccs_limits[i].name, val, val); - } - - if (ccs_limits[i].flags & CCS_L_FL_SAME_REG) - continue; - - l++; - ptr = alloc + ccs_limit_offsets[l].lim; - } - - if (l != CCS_L_LAST) { - dev_err(&client->dev, - "internal error --- insufficient limits\n"); - ret = -EINVAL; - goto out_err; - } - - sensor->ccs_limits = alloc; - - if (CCS_LIM(sensor, SCALER_N_MIN) < 16) - ccs_replace_limit(sensor, CCS_L_SCALER_N_MIN, 0, 16); - - return 0; - -out_err: - kfree(alloc); - - return ret; -} - -static int ccs_read_frame_fmt(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - u8 fmt_model_type, fmt_model_subtype, ncol_desc, nrow_desc; - unsigned int i; - int pixel_count = 0; - int line_count = 0; - - fmt_model_type = CCS_LIM(sensor, FRAME_FORMAT_MODEL_TYPE); - fmt_model_subtype = CCS_LIM(sensor, FRAME_FORMAT_MODEL_SUBTYPE); - - ncol_desc = (fmt_model_subtype - & CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK) - >> CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT; - nrow_desc = fmt_model_subtype - & CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_MASK; - - dev_dbg(&client->dev, "format_model_type %s\n", - fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE - ? "2 byte" : - fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE - ? "4 byte" : "is simply bad"); - - dev_dbg(&client->dev, "%u column and %u row descriptors\n", - ncol_desc, nrow_desc); - - for (i = 0; i < ncol_desc + nrow_desc; i++) { - u32 desc; - u32 pixelcode; - u32 pixels; - char *which; - char *what; - u32 reg; - - if (fmt_model_type == CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE) { - desc = CCS_LIM_AT(sensor, FRAME_FORMAT_DESCRIPTOR, i); - - pixelcode = - (desc - & CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MASK) - >> CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_SHIFT; - pixels = desc & CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_MASK; - } else if (fmt_model_type - == CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE) { - desc = CCS_LIM_AT(sensor, FRAME_FORMAT_DESCRIPTOR_4, i); - - pixelcode = - (desc - & CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MASK) - >> CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_SHIFT; - pixels = desc & - CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK; - } else { - dev_dbg(&client->dev, - "invalid frame format model type %d\n", - fmt_model_type); - return -EINVAL; - } - - if (i < ncol_desc) - which = "columns"; - else - which = "rows"; - - switch (pixelcode) { - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED: - what = "embedded"; - break; - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DUMMY_PIXEL: - what = "dummy"; - break; - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_BLACK_PIXEL: - what = "black"; - break; - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DARK_PIXEL: - what = "dark"; - break; - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL: - what = "visible"; - break; - default: - what = "invalid"; - break; - } - - dev_dbg(&client->dev, - "0x%8.8x %s pixels: %d %s (pixelcode %u)\n", reg, - what, pixels, which, pixelcode); - - if (i < ncol_desc) { - if (pixelcode == - CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL) - sensor->visible_pixel_start = pixel_count; - pixel_count += pixels; - continue; - } - - /* Handle row descriptors */ - switch (pixelcode) { - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED: - if (sensor->embedded_end) - break; - sensor->embedded_start = line_count; - sensor->embedded_end = line_count + pixels; - break; - case CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL: - sensor->image_start = line_count; - break; - } - line_count += pixels; - } - - if (sensor->embedded_end > sensor->image_start) { - dev_dbg(&client->dev, - "adjusting image start line to %u (was %u)\n", - sensor->embedded_end, sensor->image_start); - sensor->image_start = sensor->embedded_end; - } - - dev_dbg(&client->dev, "embedded data from lines %d to %d\n", - sensor->embedded_start, sensor->embedded_end); - dev_dbg(&client->dev, "image data starts at line %d\n", - sensor->image_start); - - return 0; -} - -static int ccs_pll_configure(struct ccs_sensor *sensor) -{ - struct smiapp_pll *pll = &sensor->pll; - int rval; - - rval = ccs_write(sensor, VT_PIX_CLK_DIV, pll->vt.pix_clk_div); - if (rval < 0) - return rval; - - rval = ccs_write(sensor, VT_SYS_CLK_DIV, pll->vt.sys_clk_div); - if (rval < 0) - return rval; - - rval = ccs_write(sensor, PRE_PLL_CLK_DIV, pll->pre_pll_clk_div); - if (rval < 0) - return rval; - - rval = ccs_write(sensor, PLL_MULTIPLIER, pll->pll_multiplier); - if (rval < 0) - return rval; - - /* Lane op clock ratio does not apply here. */ - rval = ccs_write(sensor, REQUESTED_LINK_RATE, - DIV_ROUND_UP(pll->op.sys_clk_freq_hz, - 1000000 / 256 / 256)); - if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) - return rval; - - rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op.pix_clk_div); - if (rval < 0) - return rval; - - return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op.sys_clk_div); -} - -static int ccs_pll_try(struct ccs_sensor *sensor, struct smiapp_pll *pll) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct smiapp_pll_limits lim = { - .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_PRE_PLL_CLK_DIV), - .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_PRE_PLL_CLK_DIV), - .min_pll_ip_freq_hz = CCS_LIM(sensor, MIN_PLL_IP_CLK_FREQ_MHZ), - .max_pll_ip_freq_hz = CCS_LIM(sensor, MAX_PLL_IP_CLK_FREQ_MHZ), - .min_pll_multiplier = CCS_LIM(sensor, MIN_PLL_MULTIPLIER), - .max_pll_multiplier = CCS_LIM(sensor, MAX_PLL_MULTIPLIER), - .min_pll_op_freq_hz = CCS_LIM(sensor, MIN_PLL_OP_CLK_FREQ_MHZ), - .max_pll_op_freq_hz = CCS_LIM(sensor, MAX_PLL_OP_CLK_FREQ_MHZ), - - .op.min_sys_clk_div = CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV), - .op.max_sys_clk_div = CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV), - .op.min_pix_clk_div = CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV), - .op.max_pix_clk_div = CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV), - .op.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_OP_SYS_CLK_FREQ_MHZ), - .op.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_OP_SYS_CLK_FREQ_MHZ), - .op.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_OP_PIX_CLK_FREQ_MHZ), - .op.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_OP_PIX_CLK_FREQ_MHZ), - - .vt.min_sys_clk_div = CCS_LIM(sensor, MIN_VT_SYS_CLK_DIV), - .vt.max_sys_clk_div = CCS_LIM(sensor, MAX_VT_SYS_CLK_DIV), - .vt.min_pix_clk_div = CCS_LIM(sensor, MIN_VT_PIX_CLK_DIV), - .vt.max_pix_clk_div = CCS_LIM(sensor, MAX_VT_PIX_CLK_DIV), - .vt.min_sys_clk_freq_hz = CCS_LIM(sensor, MIN_VT_SYS_CLK_FREQ_MHZ), - .vt.max_sys_clk_freq_hz = CCS_LIM(sensor, MAX_VT_SYS_CLK_FREQ_MHZ), - .vt.min_pix_clk_freq_hz = CCS_LIM(sensor, MIN_VT_PIX_CLK_FREQ_MHZ), - .vt.max_pix_clk_freq_hz = CCS_LIM(sensor, MAX_VT_PIX_CLK_FREQ_MHZ), - - .min_line_length_pck_bin = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN), - .min_line_length_pck = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK), - }; - - return smiapp_pll_calculate(&client->dev, &lim, pll); -} - -static int ccs_pll_update(struct ccs_sensor *sensor) -{ - struct smiapp_pll *pll = &sensor->pll; - int rval; - - pll->binning_horizontal = sensor->binning_horizontal; - pll->binning_vertical = sensor->binning_vertical; - pll->link_freq = - sensor->link_freq->qmenu_int[sensor->link_freq->val]; - pll->scale_m = sensor->scale_m; - pll->bits_per_pixel = sensor->csi_format->compressed; - - rval = ccs_pll_try(sensor, pll); - if (rval < 0) - return rval; - - __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray, - pll->pixel_rate_pixel_array); - __v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi); - - return 0; -} - - -/* - * - * V4L2 Controls handling - * - */ - -static void __ccs_update_exposure_limits(struct ccs_sensor *sensor) -{ - struct v4l2_ctrl *ctrl = sensor->exposure; - int max; - - max = sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - + sensor->vblank->val - - CCS_LIM(sensor, COARSE_INTEGRATION_TIME_MAX_MARGIN); - - __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, max, ctrl->step, max); -} - -/* - * Order matters. - * - * 1. Bits-per-pixel, descending. - * 2. Bits-per-pixel compressed, descending. - * 3. Pixel order, same as in pixel_order_str. Formats for all four pixel - * orders must be defined. - */ -static const struct ccs_csi_data_format ccs_csi_data_formats[] = { - { MEDIA_BUS_FMT_SGRBG16_1X16, 16, 16, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB16_1X16, 16, 16, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR16_1X16, 16, 16, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG16_1X16, 16, 16, CCS_PIXEL_ORDER_GBRG, }, - { MEDIA_BUS_FMT_SGRBG14_1X14, 14, 14, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB14_1X14, 14, 14, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR14_1X14, 14, 14, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG14_1X14, 14, 14, CCS_PIXEL_ORDER_GBRG, }, - { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, CCS_PIXEL_ORDER_GBRG, }, - { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, CCS_PIXEL_ORDER_GBRG, }, - { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, CCS_PIXEL_ORDER_GBRG, }, - { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, CCS_PIXEL_ORDER_GRBG, }, - { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, CCS_PIXEL_ORDER_RGGB, }, - { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, CCS_PIXEL_ORDER_BGGR, }, - { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, CCS_PIXEL_ORDER_GBRG, }, -}; - -static const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" }; - -#define to_csi_format_idx(fmt) (((unsigned long)(fmt) \ - - (unsigned long)ccs_csi_data_formats) \ - / sizeof(*ccs_csi_data_formats)) - -static u32 ccs_pixel_order(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int flip = 0; - - if (sensor->hflip) { - if (sensor->hflip->val) - flip |= CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR; - - if (sensor->vflip->val) - flip |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; - } - - flip ^= sensor->hvflip_inv_mask; - - dev_dbg(&client->dev, "flip %d\n", flip); - return sensor->default_pixel_order ^ flip; -} - -static void ccs_update_mbus_formats(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - unsigned int csi_format_idx = - to_csi_format_idx(sensor->csi_format) & ~3; - unsigned int internal_csi_format_idx = - to_csi_format_idx(sensor->internal_csi_format) & ~3; - unsigned int pixel_order = ccs_pixel_order(sensor); - - sensor->mbus_frame_fmts = - sensor->default_mbus_frame_fmts << pixel_order; - sensor->csi_format = - &ccs_csi_data_formats[csi_format_idx + pixel_order]; - sensor->internal_csi_format = - &ccs_csi_data_formats[internal_csi_format_idx - + pixel_order]; - - BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order - >= ARRAY_SIZE(ccs_csi_data_formats)); - - dev_dbg(&client->dev, "new pixel order %s\n", - pixel_order_str[pixel_order]); -} - -static const char * const ccs_test_patterns[] = { - "Disabled", - "Solid Colour", - "Eight Vertical Colour Bars", - "Colour Bars With Fade to Grey", - "Pseudorandom Sequence (PN9)", -}; - -static int ccs_set_ctrl(struct v4l2_ctrl *ctrl) -{ - struct ccs_sensor *sensor = - container_of(ctrl->handler, struct ccs_subdev, ctrl_handler) - ->sensor; - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int pm_status; - u32 orient = 0; - unsigned int i; - int exposure; - int rval; - - switch (ctrl->id) { - case V4L2_CID_HFLIP: - case V4L2_CID_VFLIP: - if (sensor->streaming) - return -EBUSY; - - if (sensor->hflip->val) - orient |= CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR; - - if (sensor->vflip->val) - orient |= CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; - - orient ^= sensor->hvflip_inv_mask; - - ccs_update_mbus_formats(sensor); - - break; - case V4L2_CID_VBLANK: - exposure = sensor->exposure->val; - - __ccs_update_exposure_limits(sensor); - - if (exposure > sensor->exposure->maximum) { - sensor->exposure->val = sensor->exposure->maximum; - rval = ccs_set_ctrl(sensor->exposure); - if (rval < 0) - return rval; - } - - break; - case V4L2_CID_LINK_FREQ: - if (sensor->streaming) - return -EBUSY; - - rval = ccs_pll_update(sensor); - if (rval) - return rval; - - return 0; - case V4L2_CID_TEST_PATTERN: - for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) - v4l2_ctrl_activate( - sensor->test_data[i], - ctrl->val == - V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR); - - break; - } - - pm_status = pm_runtime_get_if_active(&client->dev, true); - if (!pm_status) - return 0; - - switch (ctrl->id) { - case V4L2_CID_ANALOGUE_GAIN: - rval = ccs_write(sensor, ANALOG_GAIN_CODE_GLOBAL, ctrl->val); - - break; - case V4L2_CID_EXPOSURE: - rval = ccs_write(sensor, COARSE_INTEGRATION_TIME, ctrl->val); - - break; - case V4L2_CID_HFLIP: - case V4L2_CID_VFLIP: - rval = ccs_write(sensor, IMAGE_ORIENTATION, orient); - - break; - case V4L2_CID_VBLANK: - rval = ccs_write(sensor, FRAME_LENGTH_LINES, - sensor->pixel_array->crop[ - CCS_PA_PAD_SRC].height - + ctrl->val); - - break; - case V4L2_CID_HBLANK: - rval = ccs_write(sensor, LINE_LENGTH_PCK, - sensor->pixel_array->crop[ - CCS_PA_PAD_SRC].width - + ctrl->val); - - break; - case V4L2_CID_TEST_PATTERN: - rval = ccs_write(sensor, TEST_PATTERN_MODE, ctrl->val); - - break; - case V4L2_CID_TEST_PATTERN_RED: - rval = ccs_write(sensor, TEST_DATA_RED, ctrl->val); - - break; - case V4L2_CID_TEST_PATTERN_GREENR: - rval = ccs_write(sensor, TEST_DATA_GREENR, ctrl->val); - - break; - case V4L2_CID_TEST_PATTERN_BLUE: - rval = ccs_write(sensor, TEST_DATA_BLUE, ctrl->val); - - break; - case V4L2_CID_TEST_PATTERN_GREENB: - rval = ccs_write(sensor, TEST_DATA_GREENB, ctrl->val); - - break; - case V4L2_CID_PIXEL_RATE: - /* For v4l2_ctrl_s_ctrl_int64() used internally. */ - rval = 0; - - break; - default: - rval = -EINVAL; - } - - if (pm_status > 0) { - pm_runtime_mark_last_busy(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - } - - return rval; -} - -static const struct v4l2_ctrl_ops ccs_ctrl_ops = { - .s_ctrl = ccs_set_ctrl, -}; - -static int ccs_init_controls(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12); - if (rval) - return rval; - - sensor->pixel_array->ctrl_handler.lock = &sensor->mutex; - - sensor->analog_gain = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_ANALOGUE_GAIN, - CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN), - CCS_LIM(sensor, ANALOG_GAIN_CODE_MAX), - max(CCS_LIM(sensor, ANALOG_GAIN_CODE_STEP), 1U), - CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN)); - - /* Exposure limits will be updated soon, use just something here. */ - sensor->exposure = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_EXPOSURE, 0, 0, 1, 0); - - sensor->hflip = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_HFLIP, 0, 1, 1, 0); - sensor->vflip = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_VFLIP, 0, 1, 1, 0); - - sensor->vblank = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_VBLANK, 0, 1, 1, 0); - - if (sensor->vblank) - sensor->vblank->flags |= V4L2_CTRL_FLAG_UPDATE; - - sensor->hblank = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_HBLANK, 0, 1, 1, 0); - - if (sensor->hblank) - sensor->hblank->flags |= V4L2_CTRL_FLAG_UPDATE; - - sensor->pixel_rate_parray = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); - - v4l2_ctrl_new_std_menu_items(&sensor->pixel_array->ctrl_handler, - &ccs_ctrl_ops, V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(ccs_test_patterns) - 1, - 0, 0, ccs_test_patterns); - - if (sensor->pixel_array->ctrl_handler.error) { - dev_err(&client->dev, - "pixel array controls initialization failed (%d)\n", - sensor->pixel_array->ctrl_handler.error); - return sensor->pixel_array->ctrl_handler.error; - } - - sensor->pixel_array->sd.ctrl_handler = - &sensor->pixel_array->ctrl_handler; - - v4l2_ctrl_cluster(2, &sensor->hflip); - - rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0); - if (rval) - return rval; - - sensor->src->ctrl_handler.lock = &sensor->mutex; - - sensor->pixel_rate_csi = v4l2_ctrl_new_std( - &sensor->src->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1); - - if (sensor->src->ctrl_handler.error) { - dev_err(&client->dev, - "src controls initialization failed (%d)\n", - sensor->src->ctrl_handler.error); - return sensor->src->ctrl_handler.error; - } - - sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler; - - return 0; -} - -/* - * For controls that require information on available media bus codes - * and linke frequencies. - */ -static int ccs_init_late_controls(struct ccs_sensor *sensor) -{ - unsigned long *valid_link_freqs = &sensor->valid_link_freqs[ - sensor->csi_format->compressed - sensor->compressed_min_bpp]; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { - int max_value = (1 << sensor->csi_format->width) - 1; - - sensor->test_data[i] = v4l2_ctrl_new_std( - &sensor->pixel_array->ctrl_handler, - &ccs_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i, - 0, max_value, 1, max_value); - } - - sensor->link_freq = v4l2_ctrl_new_int_menu( - &sensor->src->ctrl_handler, &ccs_ctrl_ops, - V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), - __ffs(*valid_link_freqs), sensor->hwcfg->op_sys_clock); - - return sensor->src->ctrl_handler.error; -} - -static void ccs_free_controls(struct ccs_sensor *sensor) -{ - unsigned int i; - - for (i = 0; i < sensor->ssds_used; i++) - v4l2_ctrl_handler_free(&sensor->ssds[i].ctrl_handler); -} - -static int ccs_get_mbus_formats(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct smiapp_pll *pll = &sensor->pll; - u8 compressed_max_bpp = 0; - unsigned int type, n; - unsigned int i, pixel_order; - int rval; - - type = CCS_LIM(sensor, DATA_FORMAT_MODEL_TYPE); - - dev_dbg(&client->dev, "data_format_model_type %d\n", type); - - rval = ccs_read(sensor, PIXEL_ORDER, &pixel_order); - if (rval) - return rval; - - if (pixel_order >= ARRAY_SIZE(pixel_order_str)) { - dev_dbg(&client->dev, "bad pixel order %d\n", pixel_order); - return -EINVAL; - } - - dev_dbg(&client->dev, "pixel order %d (%s)\n", pixel_order, - pixel_order_str[pixel_order]); - - switch (type) { - case CCS_DATA_FORMAT_MODEL_TYPE_NORMAL: - n = SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N; - break; - case CCS_DATA_FORMAT_MODEL_TYPE_EXTENDED: - n = CCS_LIM_DATA_FORMAT_DESCRIPTOR_MAX_N + 1; - break; - default: - return -EINVAL; - } - - sensor->default_pixel_order = pixel_order; - sensor->mbus_frame_fmts = 0; - - for (i = 0; i < n; i++) { - unsigned int fmt, j; - - fmt = CCS_LIM_AT(sensor, DATA_FORMAT_DESCRIPTOR, i); - - dev_dbg(&client->dev, "%u: bpp %u, compressed %u\n", - i, fmt >> 8, (u8)fmt); - - for (j = 0; j < ARRAY_SIZE(ccs_csi_data_formats); j++) { - const struct ccs_csi_data_format *f = - &ccs_csi_data_formats[j]; - - if (f->pixel_order != CCS_PIXEL_ORDER_GRBG) - continue; - - if (f->width != fmt >> - CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT || - f->compressed != - (fmt & CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK)) - continue; - - dev_dbg(&client->dev, "jolly good! %d\n", j); - - sensor->default_mbus_frame_fmts |= 1 << j; - } - } - - /* Figure out which BPP values can be used with which formats. */ - pll->binning_horizontal = 1; - pll->binning_vertical = 1; - pll->scale_m = sensor->scale_m; - - for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { - sensor->compressed_min_bpp = - min(ccs_csi_data_formats[i].compressed, - sensor->compressed_min_bpp); - compressed_max_bpp = - max(ccs_csi_data_formats[i].compressed, - compressed_max_bpp); - } - - sensor->valid_link_freqs = devm_kcalloc( - &client->dev, - compressed_max_bpp - sensor->compressed_min_bpp + 1, - sizeof(*sensor->valid_link_freqs), GFP_KERNEL); - if (!sensor->valid_link_freqs) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { - const struct ccs_csi_data_format *f = - &ccs_csi_data_formats[i]; - unsigned long *valid_link_freqs = - &sensor->valid_link_freqs[ - f->compressed - sensor->compressed_min_bpp]; - unsigned int j; - - if (!(sensor->default_mbus_frame_fmts & 1 << i)) - continue; - - pll->bits_per_pixel = f->compressed; - - for (j = 0; sensor->hwcfg->op_sys_clock[j]; j++) { - pll->link_freq = sensor->hwcfg->op_sys_clock[j]; - - rval = ccs_pll_try(sensor, pll); - dev_dbg(&client->dev, "link freq %u Hz, bpp %u %s\n", - pll->link_freq, pll->bits_per_pixel, - rval ? "not ok" : "ok"); - if (rval) - continue; - - set_bit(j, valid_link_freqs); - } - - if (!*valid_link_freqs) { - dev_info(&client->dev, - "no valid link frequencies for %u bpp\n", - f->compressed); - sensor->default_mbus_frame_fmts &= ~BIT(i); - continue; - } - - if (!sensor->csi_format - || f->width > sensor->csi_format->width - || (f->width == sensor->csi_format->width - && f->compressed > sensor->csi_format->compressed)) { - sensor->csi_format = f; - sensor->internal_csi_format = f; - } - } - - if (!sensor->csi_format) { - dev_err(&client->dev, "no supported mbus code found\n"); - return -EINVAL; - } - - ccs_update_mbus_formats(sensor); - - return 0; -} - -static void ccs_update_blanking(struct ccs_sensor *sensor) -{ - struct v4l2_ctrl *vblank = sensor->vblank; - struct v4l2_ctrl *hblank = sensor->hblank; - uint16_t min_fll, max_fll, min_llp, max_llp, min_lbp; - int min, max; - - if (sensor->binning_vertical > 1 || sensor->binning_horizontal > 1) { - min_fll = CCS_LIM(sensor, MIN_FRAME_LENGTH_LINES_BIN); - max_fll = CCS_LIM(sensor, MAX_FRAME_LENGTH_LINES_BIN); - min_llp = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK_BIN); - max_llp = CCS_LIM(sensor, MAX_LINE_LENGTH_PCK_BIN); - min_lbp = CCS_LIM(sensor, MIN_LINE_BLANKING_PCK_BIN); - } else { - min_fll = CCS_LIM(sensor, MIN_FRAME_LENGTH_LINES); - max_fll = CCS_LIM(sensor, MAX_FRAME_LENGTH_LINES); - min_llp = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK); - max_llp = CCS_LIM(sensor, MAX_LINE_LENGTH_PCK); - min_lbp = CCS_LIM(sensor, MIN_LINE_BLANKING_PCK); - } - - min = max_t(int, - CCS_LIM(sensor, MIN_FRAME_BLANKING_LINES), - min_fll - - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height); - max = max_fll - sensor->pixel_array->crop[CCS_PA_PAD_SRC].height; - - __v4l2_ctrl_modify_range(vblank, min, max, vblank->step, min); - - min = max_t(int, - min_llp - - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width, - min_lbp); - max = max_llp - sensor->pixel_array->crop[CCS_PA_PAD_SRC].width; - - __v4l2_ctrl_modify_range(hblank, min, max, hblank->step, min); - - __ccs_update_exposure_limits(sensor); -} - -static int ccs_pll_blanking_update(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - rval = ccs_pll_update(sensor); - if (rval < 0) - return rval; - - /* Output from pixel array, including blanking */ - ccs_update_blanking(sensor); - - dev_dbg(&client->dev, "vblank\t\t%d\n", sensor->vblank->val); - dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val); - - dev_dbg(&client->dev, "real timeperframe\t100/%d\n", - sensor->pll.pixel_rate_pixel_array / - ((sensor->pixel_array->crop[CCS_PA_PAD_SRC].width - + sensor->hblank->val) * - (sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - + sensor->vblank->val) / 100)); - - return 0; -} - -/* - * - * SMIA++ NVM handling - * - */ - -static int ccs_read_nvm_page(struct ccs_sensor *sensor, u32 p, u8 *nvm, - u8 *status) -{ - unsigned int i; - int rval; - u32 s; - - *status = 0; - - rval = ccs_write(sensor, DATA_TRANSFER_IF_1_PAGE_SELECT, p); - if (rval) - return rval; - - rval = ccs_write(sensor, DATA_TRANSFER_IF_1_CTRL, - CCS_DATA_TRANSFER_IF_1_CTRL_ENABLE); - if (rval) - return rval; - - rval = ccs_read(sensor, DATA_TRANSFER_IF_1_STATUS, &s); - if (rval) - return rval; - - if (s & CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE) { - *status = s; - return -ENODATA; - } - - if (CCS_LIM(sensor, DATA_TRANSFER_IF_CAPABILITY) & - CCS_DATA_TRANSFER_IF_CAPABILITY_POLLING) { - for (i = 1000; i > 0; i--) { - if (s & CCS_DATA_TRANSFER_IF_1_STATUS_READ_IF_READY) - break; - - rval = ccs_read(sensor, DATA_TRANSFER_IF_1_STATUS, &s); - if (rval) - return rval; - } - - if (!i) - return -ETIMEDOUT; - } - - for (i = 0; i <= CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P; i++) { - u32 v; - - rval = ccs_read(sensor, DATA_TRANSFER_IF_1_DATA(i), &v); - if (rval) - return rval; - - *nvm++ = v; - } - - return 0; -} - -static int ccs_read_nvm(struct ccs_sensor *sensor, unsigned char *nvm, - size_t nvm_size) -{ - u8 status = 0; - u32 p; - int rval = 0, rval2; - - for (p = 0; p < nvm_size / (CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1) - && !rval; p++) { - rval = ccs_read_nvm_page(sensor, p, nvm, &status); - nvm += CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1; - } - - if (rval == -ENODATA && - status & CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE) - rval = 0; - - rval2 = ccs_write(sensor, DATA_TRANSFER_IF_1_CTRL, 0); - if (rval < 0) - return rval; - else - return rval2 ?: p * (CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P + 1); -} - -/* - * - * SMIA++ CCI address control - * - */ -static int ccs_change_cci_addr(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - u32 val; - - client->addr = sensor->hwcfg->i2c_addr_dfl; - - rval = ccs_write(sensor, CCI_ADDRESS_CTRL, - sensor->hwcfg->i2c_addr_alt << 1); - if (rval) - return rval; - - client->addr = sensor->hwcfg->i2c_addr_alt; - - /* verify addr change went ok */ - rval = ccs_read(sensor, CCI_ADDRESS_CTRL, &val); - if (rval) - return rval; - - if (val != sensor->hwcfg->i2c_addr_alt << 1) - return -ENODEV; - - return 0; -} - -/* - * - * SMIA++ Mode Control - * - */ -static int ccs_setup_flash_strobe(struct ccs_sensor *sensor) -{ - struct ccs_flash_strobe_parms *strobe_setup; - unsigned int ext_freq = sensor->hwcfg->ext_clk; - u32 tmp; - u32 strobe_adjustment; - u32 strobe_width_high_rs; - int rval; - - strobe_setup = sensor->hwcfg->strobe_setup; - - /* - * How to calculate registers related to strobe length. Please - * do not change, or if you do at least know what you're - * doing. :-) - * - * Sakari Ailus 2010-10-25 - * - * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl - * / EXTCLK freq [Hz]) * flash_strobe_adjustment - * - * tFlash_strobe_width_ctrl E N, [1 - 0xffff] - * flash_strobe_adjustment E N, [1 - 0xff] - * - * The formula above is written as below to keep it on one - * line: - * - * l / 10^6 = w / e * a - * - * Let's mark w * a by x: - * - * x = w * a - * - * Thus, we get: - * - * x = l * e / 10^6 - * - * The strobe width must be at least as long as requested, - * thus rounding upwards is needed. - * - * x = (l * e + 10^6 - 1) / 10^6 - * ----------------------------- - * - * Maximum possible accuracy is wanted at all times. Thus keep - * a as small as possible. - * - * Calculate a, assuming maximum w, with rounding upwards: - * - * a = (x + (2^16 - 1) - 1) / (2^16 - 1) - * ------------------------------------- - * - * Thus, we also get w, with that a, with rounding upwards: - * - * w = (x + a - 1) / a - * ------------------- - * - * To get limits: - * - * x E [1, (2^16 - 1) * (2^8 - 1)] - * - * Substituting maximum x to the original formula (with rounding), - * the maximum l is thus - * - * (2^16 - 1) * (2^8 - 1) * 10^6 = l * e + 10^6 - 1 - * - * l = (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / e - * -------------------------------------------------- - * - * flash_strobe_length must be clamped between 1 and - * (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / EXTCLK freq. - * - * Then, - * - * flash_strobe_adjustment = ((flash_strobe_length * - * EXTCLK freq + 10^6 - 1) / 10^6 + (2^16 - 1) - 1) / (2^16 - 1) - * - * tFlash_strobe_width_ctrl = ((flash_strobe_length * - * EXTCLK freq + 10^6 - 1) / 10^6 + - * flash_strobe_adjustment - 1) / flash_strobe_adjustment - */ - tmp = div_u64(1000000ULL * ((1 << 16) - 1) * ((1 << 8) - 1) - - 1000000 + 1, ext_freq); - strobe_setup->strobe_width_high_us = - clamp_t(u32, strobe_setup->strobe_width_high_us, 1, tmp); - - tmp = div_u64(((u64)strobe_setup->strobe_width_high_us * (u64)ext_freq + - 1000000 - 1), 1000000ULL); - strobe_adjustment = (tmp + (1 << 16) - 1 - 1) / ((1 << 16) - 1); - strobe_width_high_rs = (tmp + strobe_adjustment - 1) / - strobe_adjustment; - - rval = ccs_write(sensor, FLASH_MODE_RS, strobe_setup->mode); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, FLASH_STROBE_ADJUSTMENT, strobe_adjustment); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, TFLASH_STROBE_WIDTH_HIGH_RS_CTRL, - strobe_width_high_rs); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, TFLASH_STROBE_DELAY_RS_CTRL, - strobe_setup->strobe_delay); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, FLASH_STROBE_START_POINT, - strobe_setup->stobe_start_point); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, FLASH_TRIGGER_RS, strobe_setup->trigger); - -out: - sensor->hwcfg->strobe_setup->trigger = 0; - - return rval; -} - -/* ----------------------------------------------------------------------------- - * Power management - */ - -static int ccs_power_on(struct device *dev) -{ - struct v4l2_subdev *subdev = dev_get_drvdata(dev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - /* - * The sub-device related to the I2C device is always the - * source one, i.e. ssds[0]. - */ - struct ccs_sensor *sensor = - container_of(ssd, struct ccs_sensor, ssds[0]); - unsigned int sleep; - int rval; - - rval = regulator_enable(sensor->vana); - if (rval) { - dev_err(dev, "failed to enable vana regulator\n"); - return rval; - } - usleep_range(1000, 1000); - - rval = clk_prepare_enable(sensor->ext_clk); - if (rval < 0) { - dev_dbg(dev, "failed to enable xclk\n"); - goto out_xclk_fail; - } - usleep_range(1000, 1000); - - gpiod_set_value(sensor->xshutdown, 1); - - sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk); - usleep_range(sleep, sleep); - - /* - * Failures to respond to the address change command have been noticed. - * Those failures seem to be caused by the sensor requiring a longer - * boot time than advertised. An additional 10ms delay seems to work - * around the issue, but the SMIA++ I2C write retry hack makes the delay - * unnecessary. The failures need to be investigated to find a proper - * fix, and a delay will likely need to be added here if the I2C write - * retry hack is reverted before the root cause of the boot time issue - * is found. - */ - - if (sensor->hwcfg->i2c_addr_alt) { - rval = ccs_change_cci_addr(sensor); - if (rval) { - dev_err(dev, "cci address change error\n"); - goto out_cci_addr_fail; - } - } - - rval = ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON); - if (rval < 0) { - dev_err(dev, "software reset failed\n"); - goto out_cci_addr_fail; - } - - if (sensor->hwcfg->i2c_addr_alt) { - rval = ccs_change_cci_addr(sensor); - if (rval) { - dev_err(dev, "cci address change error\n"); - goto out_cci_addr_fail; - } - } - - rval = ccs_write(sensor, COMPRESSION_MODE, - CCS_COMPRESSION_MODE_DPCM_PCM_SIMPLE); - if (rval) { - dev_err(dev, "compression mode set failed\n"); - goto out_cci_addr_fail; - } - - rval = ccs_write(sensor, EXTCLK_FREQUENCY_MHZ, - sensor->hwcfg->ext_clk / (1000000 / (1 << 8))); - if (rval) { - dev_err(dev, "extclk frequency set failed\n"); - goto out_cci_addr_fail; - } - - rval = ccs_write(sensor, CSI_LANE_MODE, sensor->hwcfg->lanes - 1); - if (rval) { - dev_err(dev, "csi lane mode set failed\n"); - goto out_cci_addr_fail; - } - - rval = ccs_write(sensor, FAST_STANDBY_CTRL, - CCS_FAST_STANDBY_CTRL_FRAME_TRUNCATION); - if (rval) { - dev_err(dev, "fast standby set failed\n"); - goto out_cci_addr_fail; - } - - rval = ccs_write(sensor, CSI_SIGNALING_MODE, - sensor->hwcfg->csi_signalling_mode); - if (rval) { - dev_err(dev, "csi signalling mode set failed\n"); - goto out_cci_addr_fail; - } - - /* DPHY control done by sensor based on requested link rate */ - rval = ccs_write(sensor, PHY_CTRL, CCS_PHY_CTRL_UI); - if (rval < 0) - goto out_cci_addr_fail; - - rval = ccs_call_quirk(sensor, post_poweron); - if (rval) { - dev_err(dev, "post_poweron quirks failed\n"); - goto out_cci_addr_fail; - } - - return 0; - -out_cci_addr_fail: - gpiod_set_value(sensor->xshutdown, 0); - clk_disable_unprepare(sensor->ext_clk); - -out_xclk_fail: - regulator_disable(sensor->vana); - - return rval; -} - -static int ccs_power_off(struct device *dev) -{ - struct v4l2_subdev *subdev = dev_get_drvdata(dev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct ccs_sensor *sensor = - container_of(ssd, struct ccs_sensor, ssds[0]); - - /* - * Currently power/clock to lens are enable/disabled separately - * but they are essentially the same signals. So if the sensor is - * powered off while the lens is powered on the sensor does not - * really see a power off and next time the cci address change - * will fail. So do a soft reset explicitly here. - */ - if (sensor->hwcfg->i2c_addr_alt) - ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON); - - gpiod_set_value(sensor->xshutdown, 0); - clk_disable_unprepare(sensor->ext_clk); - usleep_range(5000, 5000); - regulator_disable(sensor->vana); - sensor->streaming = false; - - return 0; -} - -/* ----------------------------------------------------------------------------- - * Video stream management - */ - -static int ccs_start_streaming(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - unsigned int binning_mode; - int rval; - - mutex_lock(&sensor->mutex); - - rval = ccs_write(sensor, CSI_DATA_FORMAT, - (sensor->csi_format->width << 8) | - sensor->csi_format->compressed); - if (rval) - goto out; - - /* Binning configuration */ - if (sensor->binning_horizontal == 1 && - sensor->binning_vertical == 1) { - binning_mode = 0; - } else { - u8 binning_type = - (sensor->binning_horizontal << 4) - | sensor->binning_vertical; - - rval = ccs_write(sensor, BINNING_TYPE, binning_type); - if (rval < 0) - goto out; - - binning_mode = 1; - } - rval = ccs_write(sensor, BINNING_MODE, binning_mode); - if (rval < 0) - goto out; - - /* Set up PLL */ - rval = ccs_pll_configure(sensor); - if (rval) - goto out; - - /* Analog crop start coordinates */ - rval = ccs_write(sensor, X_ADDR_START, - sensor->pixel_array->crop[CCS_PA_PAD_SRC].left); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, Y_ADDR_START, - sensor->pixel_array->crop[CCS_PA_PAD_SRC].top); - if (rval < 0) - goto out; - - /* Analog crop end coordinates */ - rval = ccs_write( - sensor, X_ADDR_END, - sensor->pixel_array->crop[CCS_PA_PAD_SRC].left - + sensor->pixel_array->crop[CCS_PA_PAD_SRC].width - 1); - if (rval < 0) - goto out; - - rval = ccs_write( - sensor, Y_ADDR_END, - sensor->pixel_array->crop[CCS_PA_PAD_SRC].top - + sensor->pixel_array->crop[CCS_PA_PAD_SRC].height - 1); - if (rval < 0) - goto out; - - /* - * Output from pixel array, including blanking, is set using - * controls below. No need to set here. - */ - - /* Digital crop */ - if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) - == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { - rval = ccs_write( - sensor, DIGITAL_CROP_X_OFFSET, - sensor->scaler->crop[CCS_PAD_SINK].left); - if (rval < 0) - goto out; - - rval = ccs_write( - sensor, DIGITAL_CROP_Y_OFFSET, - sensor->scaler->crop[CCS_PAD_SINK].top); - if (rval < 0) - goto out; - - rval = ccs_write( - sensor, DIGITAL_CROP_IMAGE_WIDTH, - sensor->scaler->crop[CCS_PAD_SINK].width); - if (rval < 0) - goto out; - - rval = ccs_write( - sensor, DIGITAL_CROP_IMAGE_HEIGHT, - sensor->scaler->crop[CCS_PAD_SINK].height); - if (rval < 0) - goto out; - } - - /* Scaling */ - if (CCS_LIM(sensor, SCALING_CAPABILITY) - != CCS_SCALING_CAPABILITY_NONE) { - rval = ccs_write(sensor, SCALING_MODE, sensor->scaling_mode); - if (rval < 0) - goto out; - - rval = ccs_write(sensor, SCALE_M, sensor->scale_m); - if (rval < 0) - goto out; - } - - /* Output size from sensor */ - rval = ccs_write(sensor, X_OUTPUT_SIZE, - sensor->src->crop[CCS_PAD_SRC].width); - if (rval < 0) - goto out; - rval = ccs_write(sensor, Y_OUTPUT_SIZE, - sensor->src->crop[CCS_PAD_SRC].height); - if (rval < 0) - goto out; - - if (CCS_LIM(sensor, FLASH_MODE_CAPABILITY) & - (CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE | - SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE) && - sensor->hwcfg->strobe_setup != NULL && - sensor->hwcfg->strobe_setup->trigger != 0) { - rval = ccs_setup_flash_strobe(sensor); - if (rval) - goto out; - } - - rval = ccs_call_quirk(sensor, pre_streamon); - if (rval) { - dev_err(&client->dev, "pre_streamon quirks failed\n"); - goto out; - } - - rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_STREAMING); - -out: - mutex_unlock(&sensor->mutex); - - return rval; -} - -static int ccs_stop_streaming(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - mutex_lock(&sensor->mutex); - rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_SOFTWARE_STANDBY); - if (rval) - goto out; - - rval = ccs_call_quirk(sensor, post_streamoff); - if (rval) - dev_err(&client->dev, "post_streamoff quirks failed\n"); - -out: - mutex_unlock(&sensor->mutex); - return rval; -} - -/* ----------------------------------------------------------------------------- - * V4L2 subdev video operations - */ - -static int ccs_pm_get_init(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - rval = pm_runtime_get_sync(&client->dev); - if (rval < 0) { - if (rval != -EBUSY && rval != -EAGAIN) - pm_runtime_set_active(&client->dev); - pm_runtime_put_noidle(&client->dev); - - return rval; - } else if (!rval) { - rval = v4l2_ctrl_handler_setup(&sensor->pixel_array-> - ctrl_handler); - if (rval) - return rval; - - return v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); - } - - return 0; -} - -static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - if (sensor->streaming == enable) - return 0; - - if (!enable) { - ccs_stop_streaming(sensor); - sensor->streaming = false; - pm_runtime_mark_last_busy(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - - return 0; - } - - rval = ccs_pm_get_init(sensor); - if (rval) - return rval; - - sensor->streaming = true; - - rval = ccs_start_streaming(sensor); - if (rval < 0) { - sensor->streaming = false; - pm_runtime_mark_last_busy(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - } - - return rval; -} - -static int ccs_enum_mbus_code(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - struct i2c_client *client = v4l2_get_subdevdata(subdev); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - unsigned int i; - int idx = -1; - int rval = -EINVAL; - - mutex_lock(&sensor->mutex); - - dev_err(&client->dev, "subdev %s, pad %d, index %d\n", - subdev->name, code->pad, code->index); - - if (subdev != &sensor->src->sd || code->pad != CCS_PAD_SRC) { - if (code->index) - goto out; - - code->code = sensor->internal_csi_format->code; - rval = 0; - goto out; - } - - for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { - if (sensor->mbus_frame_fmts & (1 << i)) - idx++; - - if (idx == code->index) { - code->code = ccs_csi_data_formats[i].code; - dev_err(&client->dev, "found index %d, i %d, code %x\n", - code->index, i, code->code); - rval = 0; - break; - } - } - -out: - mutex_unlock(&sensor->mutex); - - return rval; -} - -static u32 __ccs_get_mbus_code(struct v4l2_subdev *subdev, unsigned int pad) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - - if (subdev == &sensor->src->sd && pad == CCS_PAD_SRC) - return sensor->csi_format->code; - else - return sensor->internal_csi_format->code; -} - -static int __ccs_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - fmt->format = *v4l2_subdev_get_try_format(subdev, cfg, - fmt->pad); - } else { - struct v4l2_rect *r; - - if (fmt->pad == ssd->source_pad) - r = &ssd->crop[ssd->source_pad]; - else - r = &ssd->sink_fmt; - - fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); - fmt->format.width = r->width; - fmt->format.height = r->height; - fmt->format.field = V4L2_FIELD_NONE; - } - - return 0; -} - -static int ccs_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int rval; - - mutex_lock(&sensor->mutex); - rval = __ccs_get_format(subdev, cfg, fmt); - mutex_unlock(&sensor->mutex); - - return rval; -} - -static void ccs_get_crop_compose(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_rect **crops, - struct v4l2_rect **comps, int which) -{ - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - unsigned int i; - - if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { - if (crops) - for (i = 0; i < subdev->entity.num_pads; i++) - crops[i] = &ssd->crop[i]; - if (comps) - *comps = &ssd->compose; - } else { - if (crops) { - for (i = 0; i < subdev->entity.num_pads; i++) { - crops[i] = v4l2_subdev_get_try_crop(subdev, cfg, i); - BUG_ON(!crops[i]); - } - } - if (comps) { - *comps = v4l2_subdev_get_try_compose(subdev, cfg, - CCS_PAD_SINK); - BUG_ON(!*comps); - } - } -} - -/* Changes require propagation only on sink pad. */ -static void ccs_propagate(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, int which, - int target) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct v4l2_rect *comp, *crops[CCS_PADS]; - - ccs_get_crop_compose(subdev, cfg, crops, &comp, which); - - switch (target) { - case V4L2_SEL_TGT_CROP: - comp->width = crops[CCS_PAD_SINK]->width; - comp->height = crops[CCS_PAD_SINK]->height; - if (which == V4L2_SUBDEV_FORMAT_ACTIVE) { - if (ssd == sensor->scaler) { - sensor->scale_m = - CCS_LIM(sensor, SCALER_N_MIN); - sensor->scaling_mode = - CCS_SCALING_MODE_NO_SCALING; - } else if (ssd == sensor->binner) { - sensor->binning_horizontal = 1; - sensor->binning_vertical = 1; - } - } - fallthrough; - case V4L2_SEL_TGT_COMPOSE: - *crops[CCS_PAD_SRC] = *comp; - break; - default: - BUG(); - } -} - -static const struct ccs_csi_data_format -*ccs_validate_csi_data_format(struct ccs_sensor *sensor, u32 code) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(ccs_csi_data_formats); i++) { - if (sensor->mbus_frame_fmts & (1 << i) && - ccs_csi_data_formats[i].code == code) - return &ccs_csi_data_formats[i]; - } - - return sensor->csi_format; -} - -static int ccs_set_format_source(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - const struct ccs_csi_data_format *csi_format, - *old_csi_format = sensor->csi_format; - unsigned long *valid_link_freqs; - u32 code = fmt->format.code; - unsigned int i; - int rval; - - rval = __ccs_get_format(subdev, cfg, fmt); - if (rval) - return rval; - - /* - * Media bus code is changeable on src subdev's source pad. On - * other source pads we just get format here. - */ - if (subdev != &sensor->src->sd) - return 0; - - csi_format = ccs_validate_csi_data_format(sensor, code); - - fmt->format.code = csi_format->code; - - if (fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return 0; - - sensor->csi_format = csi_format; - - if (csi_format->width != old_csi_format->width) - for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) - __v4l2_ctrl_modify_range( - sensor->test_data[i], 0, - (1 << csi_format->width) - 1, 1, 0); - - if (csi_format->compressed == old_csi_format->compressed) - return 0; - - valid_link_freqs = - &sensor->valid_link_freqs[sensor->csi_format->compressed - - sensor->compressed_min_bpp]; - - __v4l2_ctrl_modify_range( - sensor->link_freq, 0, - __fls(*valid_link_freqs), ~*valid_link_freqs, - __ffs(*valid_link_freqs)); - - return ccs_pll_update(sensor); -} - -static int ccs_set_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct v4l2_rect *crops[CCS_PADS]; - - mutex_lock(&sensor->mutex); - - if (fmt->pad == ssd->source_pad) { - int rval; - - rval = ccs_set_format_source(subdev, cfg, fmt); - - mutex_unlock(&sensor->mutex); - - return rval; - } - - /* Sink pad. Width and height are changeable here. */ - fmt->format.code = __ccs_get_mbus_code(subdev, fmt->pad); - fmt->format.width &= ~1; - fmt->format.height &= ~1; - fmt->format.field = V4L2_FIELD_NONE; - - fmt->format.width = - clamp(fmt->format.width, - CCS_LIM(sensor, MIN_X_OUTPUT_SIZE), - CCS_LIM(sensor, MAX_X_OUTPUT_SIZE)); - fmt->format.height = - clamp(fmt->format.height, - CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), - CCS_LIM(sensor, MAX_Y_OUTPUT_SIZE)); - - ccs_get_crop_compose(subdev, cfg, crops, NULL, fmt->which); - - crops[ssd->sink_pad]->left = 0; - crops[ssd->sink_pad]->top = 0; - crops[ssd->sink_pad]->width = fmt->format.width; - crops[ssd->sink_pad]->height = fmt->format.height; - if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) - ssd->sink_fmt = *crops[ssd->sink_pad]; - ccs_propagate(subdev, cfg, fmt->which, V4L2_SEL_TGT_CROP); - - mutex_unlock(&sensor->mutex); - - return 0; -} - -/* - * Calculate goodness of scaled image size compared to expected image - * size and flags provided. - */ -#define SCALING_GOODNESS 100000 -#define SCALING_GOODNESS_EXTREME 100000000 -static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w, - int h, int ask_h, u32 flags) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct i2c_client *client = v4l2_get_subdevdata(subdev); - int val = 0; - - w &= ~1; - ask_w &= ~1; - h &= ~1; - ask_h &= ~1; - - if (flags & V4L2_SEL_FLAG_GE) { - if (w < ask_w) - val -= SCALING_GOODNESS; - if (h < ask_h) - val -= SCALING_GOODNESS; - } - - if (flags & V4L2_SEL_FLAG_LE) { - if (w > ask_w) - val -= SCALING_GOODNESS; - if (h > ask_h) - val -= SCALING_GOODNESS; - } - - val -= abs(w - ask_w); - val -= abs(h - ask_h); - - if (w < CCS_LIM(sensor, MIN_X_OUTPUT_SIZE)) - val -= SCALING_GOODNESS_EXTREME; - - dev_dbg(&client->dev, "w %d ask_w %d h %d ask_h %d goodness %d\n", - w, ask_w, h, ask_h, val); - - return val; -} - -static void ccs_set_compose_binner(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel, - struct v4l2_rect **crops, - struct v4l2_rect *comp) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - unsigned int i; - unsigned int binh = 1, binv = 1; - int best = scaling_goodness( - subdev, - crops[CCS_PAD_SINK]->width, sel->r.width, - crops[CCS_PAD_SINK]->height, sel->r.height, sel->flags); - - for (i = 0; i < sensor->nbinning_subtypes; i++) { - int this = scaling_goodness( - subdev, - crops[CCS_PAD_SINK]->width - / sensor->binning_subtypes[i].horizontal, - sel->r.width, - crops[CCS_PAD_SINK]->height - / sensor->binning_subtypes[i].vertical, - sel->r.height, sel->flags); - - if (this > best) { - binh = sensor->binning_subtypes[i].horizontal; - binv = sensor->binning_subtypes[i].vertical; - best = this; - } - } - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - sensor->binning_vertical = binv; - sensor->binning_horizontal = binh; - } - - sel->r.width = (crops[CCS_PAD_SINK]->width / binh) & ~1; - sel->r.height = (crops[CCS_PAD_SINK]->height / binv) & ~1; -} - -/* - * Calculate best scaling ratio and mode for given output resolution. - * - * Try all of these: horizontal ratio, vertical ratio and smallest - * size possible (horizontally). - * - * Also try whether horizontal scaler or full scaler gives a better - * result. - */ -static void ccs_set_compose_scaler(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel, - struct v4l2_rect **crops, - struct v4l2_rect *comp) -{ - struct i2c_client *client = v4l2_get_subdevdata(subdev); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - u32 min, max, a, b, max_m; - u32 scale_m = CCS_LIM(sensor, SCALER_N_MIN); - int mode = CCS_SCALING_MODE_HORIZONTAL; - u32 try[4]; - u32 ntry = 0; - unsigned int i; - int best = INT_MIN; - - sel->r.width = min_t(unsigned int, sel->r.width, - crops[CCS_PAD_SINK]->width); - sel->r.height = min_t(unsigned int, sel->r.height, - crops[CCS_PAD_SINK]->height); - - a = crops[CCS_PAD_SINK]->width - * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.width; - b = crops[CCS_PAD_SINK]->height - * CCS_LIM(sensor, SCALER_N_MIN) / sel->r.height; - max_m = crops[CCS_PAD_SINK]->width - * CCS_LIM(sensor, SCALER_N_MIN) - / CCS_LIM(sensor, MIN_X_OUTPUT_SIZE); - - a = clamp(a, CCS_LIM(sensor, SCALER_M_MIN), - CCS_LIM(sensor, SCALER_M_MAX)); - b = clamp(b, CCS_LIM(sensor, SCALER_M_MIN), - CCS_LIM(sensor, SCALER_M_MAX)); - max_m = clamp(max_m, CCS_LIM(sensor, SCALER_M_MIN), - CCS_LIM(sensor, SCALER_M_MAX)); - - dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m); - - min = min(max_m, min(a, b)); - max = min(max_m, max(a, b)); - - try[ntry] = min; - ntry++; - if (min != max) { - try[ntry] = max; - ntry++; - } - if (max != max_m) { - try[ntry] = min + 1; - ntry++; - if (min != max) { - try[ntry] = max + 1; - ntry++; - } - } - - for (i = 0; i < ntry; i++) { - int this = scaling_goodness( - subdev, - crops[CCS_PAD_SINK]->width - / try[i] * CCS_LIM(sensor, SCALER_N_MIN), - sel->r.width, - crops[CCS_PAD_SINK]->height, - sel->r.height, - sel->flags); - - dev_dbg(&client->dev, "trying factor %d (%d)\n", try[i], i); - - if (this > best) { - scale_m = try[i]; - mode = CCS_SCALING_MODE_HORIZONTAL; - best = this; - } - - if (CCS_LIM(sensor, SCALING_CAPABILITY) - == CCS_SCALING_CAPABILITY_HORIZONTAL) - continue; - - this = scaling_goodness( - subdev, crops[CCS_PAD_SINK]->width - / try[i] - * CCS_LIM(sensor, SCALER_N_MIN), - sel->r.width, - crops[CCS_PAD_SINK]->height - / try[i] - * CCS_LIM(sensor, SCALER_N_MIN), - sel->r.height, - sel->flags); - - if (this > best) { - scale_m = try[i]; - mode = SMIAPP_SCALING_MODE_BOTH; - best = this; - } - } - - sel->r.width = - (crops[CCS_PAD_SINK]->width - / scale_m - * CCS_LIM(sensor, SCALER_N_MIN)) & ~1; - if (mode == SMIAPP_SCALING_MODE_BOTH) - sel->r.height = - (crops[CCS_PAD_SINK]->height - / scale_m - * CCS_LIM(sensor, SCALER_N_MIN)) - & ~1; - else - sel->r.height = crops[CCS_PAD_SINK]->height; - - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - sensor->scale_m = scale_m; - sensor->scaling_mode = mode; - } -} -/* We're only called on source pads. This function sets scaling. */ -static int ccs_set_compose(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct v4l2_rect *comp, *crops[CCS_PADS]; - - ccs_get_crop_compose(subdev, cfg, crops, &comp, sel->which); - - sel->r.top = 0; - sel->r.left = 0; - - if (ssd == sensor->binner) - ccs_set_compose_binner(subdev, cfg, sel, crops, comp); - else - ccs_set_compose_scaler(subdev, cfg, sel, crops, comp); - - *comp = sel->r; - ccs_propagate(subdev, cfg, sel->which, V4L2_SEL_TGT_COMPOSE); - - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) - return ccs_pll_blanking_update(sensor); - - return 0; -} - -static int __ccs_sel_supported(struct v4l2_subdev *subdev, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - - /* We only implement crop in three places. */ - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_CROP_BOUNDS: - if (ssd == sensor->pixel_array && sel->pad == CCS_PA_PAD_SRC) - return 0; - if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) - return 0; - if (ssd == sensor->scaler && sel->pad == CCS_PAD_SINK && - CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) - == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) - return 0; - return -EINVAL; - case V4L2_SEL_TGT_NATIVE_SIZE: - if (ssd == sensor->pixel_array && sel->pad == CCS_PA_PAD_SRC) - return 0; - return -EINVAL; - case V4L2_SEL_TGT_COMPOSE: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - if (sel->pad == ssd->source_pad) - return -EINVAL; - if (ssd == sensor->binner) - return 0; - if (ssd == sensor->scaler && CCS_LIM(sensor, SCALING_CAPABILITY) - != CCS_SCALING_CAPABILITY_NONE) - return 0; - fallthrough; - default: - return -EINVAL; - } -} - -static int ccs_set_crop(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct v4l2_rect *src_size, *crops[CCS_PADS]; - struct v4l2_rect _r; - - ccs_get_crop_compose(subdev, cfg, crops, NULL, sel->which); - - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - if (sel->pad == ssd->sink_pad) - src_size = &ssd->sink_fmt; - else - src_size = &ssd->compose; - } else { - if (sel->pad == ssd->sink_pad) { - _r.left = 0; - _r.top = 0; - _r.width = v4l2_subdev_get_try_format(subdev, cfg, sel->pad) - ->width; - _r.height = v4l2_subdev_get_try_format(subdev, cfg, sel->pad) - ->height; - src_size = &_r; - } else { - src_size = v4l2_subdev_get_try_compose( - subdev, cfg, ssd->sink_pad); - } - } - - if (ssd == sensor->src && sel->pad == CCS_PAD_SRC) { - sel->r.left = 0; - sel->r.top = 0; - } - - sel->r.width = min(sel->r.width, src_size->width); - sel->r.height = min(sel->r.height, src_size->height); - - sel->r.left = min_t(int, sel->r.left, src_size->width - sel->r.width); - sel->r.top = min_t(int, sel->r.top, src_size->height - sel->r.height); - - *crops[sel->pad] = sel->r; - - if (ssd != sensor->pixel_array && sel->pad == CCS_PAD_SINK) - ccs_propagate(subdev, cfg, sel->which, V4L2_SEL_TGT_CROP); - - return 0; -} - -static void ccs_get_native_size(struct ccs_subdev *ssd, struct v4l2_rect *r) -{ - r->top = 0; - r->left = 0; - r->width = CCS_LIM(ssd->sensor, X_ADDR_MAX) + 1; - r->height = CCS_LIM(ssd->sensor, Y_ADDR_MAX) + 1; -} - -static int __ccs_get_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_subdev *ssd = to_ccs_subdev(subdev); - struct v4l2_rect *comp, *crops[CCS_PADS]; - struct v4l2_rect sink_fmt; - int ret; - - ret = __ccs_sel_supported(subdev, sel); - if (ret) - return ret; - - ccs_get_crop_compose(subdev, cfg, crops, &comp, sel->which); - - if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { - sink_fmt = ssd->sink_fmt; - } else { - struct v4l2_mbus_framefmt *fmt = - v4l2_subdev_get_try_format(subdev, cfg, ssd->sink_pad); - - sink_fmt.left = 0; - sink_fmt.top = 0; - sink_fmt.width = fmt->width; - sink_fmt.height = fmt->height; - } - - switch (sel->target) { - case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_NATIVE_SIZE: - if (ssd == sensor->pixel_array) - ccs_get_native_size(ssd, &sel->r); - else if (sel->pad == ssd->sink_pad) - sel->r = sink_fmt; - else - sel->r = *comp; - break; - case V4L2_SEL_TGT_CROP: - case V4L2_SEL_TGT_COMPOSE_BOUNDS: - sel->r = *crops[sel->pad]; - break; - case V4L2_SEL_TGT_COMPOSE: - sel->r = *comp; - break; - } - - return 0; -} - -static int ccs_get_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int rval; - - mutex_lock(&sensor->mutex); - rval = __ccs_get_selection(subdev, cfg, sel); - mutex_unlock(&sensor->mutex); - - return rval; -} - -static int ccs_set_selection(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_selection *sel) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int ret; - - ret = __ccs_sel_supported(subdev, sel); - if (ret) - return ret; - - mutex_lock(&sensor->mutex); - - sel->r.left = max(0, sel->r.left & ~1); - sel->r.top = max(0, sel->r.top & ~1); - sel->r.width = CCS_ALIGN_DIM(sel->r.width, sel->flags); - sel->r.height = CCS_ALIGN_DIM(sel->r.height, sel->flags); - - sel->r.width = max_t(unsigned int, - CCS_LIM(sensor, MIN_X_OUTPUT_SIZE), - sel->r.width); - sel->r.height = max_t(unsigned int, - CCS_LIM(sensor, MIN_Y_OUTPUT_SIZE), - sel->r.height); - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - ret = ccs_set_crop(subdev, cfg, sel); - break; - case V4L2_SEL_TGT_COMPOSE: - ret = ccs_set_compose(subdev, cfg, sel); - break; - default: - ret = -EINVAL; - } - - mutex_unlock(&sensor->mutex); - return ret; -} - -static int ccs_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - - *frames = sensor->frame_skip; - return 0; -} - -static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - - *lines = sensor->image_start; - - return 0; -} - -/* ----------------------------------------------------------------------------- - * sysfs attributes - */ - -static ssize_t -ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); - struct i2c_client *client = v4l2_get_subdevdata(subdev); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int rval; - - if (!sensor->dev_init_done) - return -EBUSY; - - rval = ccs_pm_get_init(sensor); - if (rval < 0) - return -ENODEV; - - rval = ccs_read_nvm(sensor, buf, PAGE_SIZE); - if (rval < 0) { - pm_runtime_put(&client->dev); - dev_err(&client->dev, "nvm read failed\n"); - return -ENODEV; - } - - pm_runtime_mark_last_busy(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - - /* - * NVM is still way below a PAGE_SIZE, so we can safely - * assume this for now. - */ - return rval; -} -static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL); - -static ssize_t -ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev)); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - struct ccs_module_info *minfo = &sensor->minfo; - - if (minfo->mipi_manufacturer_id) - return snprintf(buf, PAGE_SIZE, "%4.4x%4.4x%2.2x\n", - minfo->mipi_manufacturer_id, minfo->model_id, - minfo->revision_number_major) + 1; - else - return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n", - minfo->smia_manufacturer_id, minfo->model_id, - minfo->revision_number_major) + 1; -} - -static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL); - -/* ----------------------------------------------------------------------------- - * V4L2 subdev core operations - */ - -static int ccs_identify_module(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct ccs_module_info *minfo = &sensor->minfo; - unsigned int i; - int rval = 0; - - /* Module info */ - rval = ccs_read(sensor, MODULE_MANUFACTURER_ID, - &minfo->mipi_manufacturer_id); - if (!rval && !minfo->mipi_manufacturer_id) - rval = ccs_read_addr_8only(sensor, - SMIAPP_REG_U8_MANUFACTURER_ID, - &minfo->smia_manufacturer_id); - if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_MODEL_ID, - &minfo->model_id); - if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_MODULE_REVISION_NUMBER_MAJOR, - &minfo->revision_number_major); - if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_MODULE_REVISION_NUMBER_MINOR, - &minfo->revision_number_minor); - if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_YEAR, - &minfo->module_year); - if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_MONTH, - &minfo->module_month); - if (!rval) - rval = ccs_read_addr_8only(sensor, CCS_R_MODULE_DATE_DAY, - &minfo->module_day); - - /* Sensor info */ - if (!rval) - rval = ccs_read(sensor, SENSOR_MANUFACTURER_ID, - &minfo->sensor_mipi_manufacturer_id); - if (!rval && !minfo->sensor_mipi_manufacturer_id) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_MANUFACTURER_ID, - &minfo->sensor_smia_manufacturer_id); - if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_MODEL_ID, - &minfo->sensor_model_id); - if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_REVISION_NUMBER, - &minfo->sensor_revision_number); - if (!rval) - rval = ccs_read_addr_8only(sensor, - CCS_R_SENSOR_FIRMWARE_VERSION, - &minfo->sensor_firmware_version); - - /* SMIA */ - if (!rval) - rval = ccs_read(sensor, MIPI_CCS_VERSION, &minfo->ccs_version); - if (!rval && !minfo->ccs_version) - rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIA_VERSION, - &minfo->smia_version); - if (!rval && !minfo->ccs_version) - rval = ccs_read_addr_8only(sensor, SMIAPP_REG_U8_SMIAPP_VERSION, - &minfo->smiapp_version); - - if (rval) { - dev_err(&client->dev, "sensor detection failed\n"); - return -ENODEV; - } - - if (minfo->mipi_manufacturer_id) - dev_dbg(&client->dev, "MIPI CCS module 0x%4.4x-0x%4.4x\n", - minfo->mipi_manufacturer_id, minfo->model_id); - else - dev_dbg(&client->dev, "SMIA module 0x%2.2x-0x%4.4x\n", - minfo->smia_manufacturer_id, minfo->model_id); - - dev_dbg(&client->dev, - "module revision 0x%2.2x-0x%2.2x date %2.2d-%2.2d-%2.2d\n", - minfo->revision_number_major, minfo->revision_number_minor, - minfo->module_year, minfo->module_month, minfo->module_day); - - if (minfo->sensor_mipi_manufacturer_id) - dev_dbg(&client->dev, "MIPI CCS sensor 0x%4.4x-0x%4.4x\n", - minfo->sensor_mipi_manufacturer_id, - minfo->sensor_model_id); - else - dev_dbg(&client->dev, "SMIA sensor 0x%2.2x-0x%4.4x\n", - minfo->sensor_smia_manufacturer_id, - minfo->sensor_model_id); - - dev_dbg(&client->dev, - "sensor revision 0x%2.2x firmware version 0x%2.2x\n", - minfo->sensor_revision_number, minfo->sensor_firmware_version); - - if (minfo->ccs_version) { - dev_dbg(&client->dev, "MIPI CCS version %u.%u", - (minfo->ccs_version & CCS_MIPI_CCS_VERSION_MAJOR_MASK) - >> CCS_MIPI_CCS_VERSION_MAJOR_SHIFT, - (minfo->ccs_version & CCS_MIPI_CCS_VERSION_MINOR_MASK)); - minfo->name = CCS_NAME; - } else { - dev_dbg(&client->dev, - "smia version %2.2d smiapp version %2.2d\n", - minfo->smia_version, minfo->smiapp_version); - minfo->name = SMIAPP_NAME; - } - - /* - * Some modules have bad data in the lvalues below. Hope the - * rvalues have better stuff. The lvalues are module - * parameters whereas the rvalues are sensor parameters. - */ - if (minfo->sensor_smia_manufacturer_id && - !minfo->smia_manufacturer_id && !minfo->model_id) { - minfo->smia_manufacturer_id = - minfo->sensor_smia_manufacturer_id; - minfo->model_id = minfo->sensor_model_id; - minfo->revision_number_major = minfo->sensor_revision_number; - } - - for (i = 0; i < ARRAY_SIZE(ccs_module_idents); i++) { - if (ccs_module_idents[i].mipi_manufacturer_id && - ccs_module_idents[i].mipi_manufacturer_id - != minfo->mipi_manufacturer_id) - continue; - if (ccs_module_idents[i].smia_manufacturer_id && - ccs_module_idents[i].smia_manufacturer_id - != minfo->smia_manufacturer_id) - continue; - if (ccs_module_idents[i].model_id != minfo->model_id) - continue; - if (ccs_module_idents[i].flags - & CCS_MODULE_IDENT_FLAG_REV_LE) { - if (ccs_module_idents[i].revision_number_major - < minfo->revision_number_major) - continue; - } else { - if (ccs_module_idents[i].revision_number_major - != minfo->revision_number_major) - continue; - } - - minfo->name = ccs_module_idents[i].name; - minfo->quirk = ccs_module_idents[i].quirk; - break; - } - - if (i >= ARRAY_SIZE(ccs_module_idents)) - dev_warn(&client->dev, - "no quirks for this module; let's hope it's fully compliant\n"); - - dev_dbg(&client->dev, "the sensor is called %s\n", - minfo->name); - - return 0; -} - -static const struct v4l2_subdev_ops ccs_ops; -static const struct v4l2_subdev_internal_ops ccs_internal_ops; -static const struct media_entity_operations ccs_entity_ops; - -static int ccs_register_subdev(struct ccs_sensor *sensor, - struct ccs_subdev *ssd, - struct ccs_subdev *sink_ssd, - u16 source_pad, u16 sink_pad, u32 link_flags) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - if (!sink_ssd) - return 0; - - rval = media_entity_pads_init(&ssd->sd.entity, - ssd->npads, ssd->pads); - if (rval) { - dev_err(&client->dev, - "media_entity_pads_init failed\n"); - return rval; - } - - rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev, - &ssd->sd); - if (rval) { - dev_err(&client->dev, - "v4l2_device_register_subdev failed\n"); - return rval; - } - - rval = media_create_pad_link(&ssd->sd.entity, source_pad, - &sink_ssd->sd.entity, sink_pad, - link_flags); - if (rval) { - dev_err(&client->dev, - "media_create_pad_link failed\n"); - v4l2_device_unregister_subdev(&ssd->sd); - return rval; - } - - return 0; -} - -static void ccs_unregistered(struct v4l2_subdev *subdev) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - unsigned int i; - - for (i = 1; i < sensor->ssds_used; i++) - v4l2_device_unregister_subdev(&sensor->ssds[i].sd); -} - -static int ccs_registered(struct v4l2_subdev *subdev) -{ - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int rval; - - if (sensor->scaler) { - rval = ccs_register_subdev(sensor, sensor->binner, - sensor->scaler, - CCS_PAD_SRC, CCS_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (rval < 0) - return rval; - } - - rval = ccs_register_subdev(sensor, sensor->pixel_array, sensor->binner, - CCS_PA_PAD_SRC, CCS_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (rval) - goto out_err; - - return 0; - -out_err: - ccs_unregistered(subdev); - - return rval; -} - -static void ccs_cleanup(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - - device_remove_file(&client->dev, &dev_attr_nvm); - device_remove_file(&client->dev, &dev_attr_ident); - - ccs_free_controls(sensor); -} - -static void ccs_create_subdev(struct ccs_sensor *sensor, - struct ccs_subdev *ssd, const char *name, - unsigned short num_pads) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - - if (!ssd) - return; - - if (ssd != sensor->src) - v4l2_subdev_init(&ssd->sd, &ccs_ops); - - ssd->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - ssd->sensor = sensor; - - ssd->npads = num_pads; - ssd->source_pad = num_pads - 1; - - v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name); - - ccs_get_native_size(ssd, &ssd->sink_fmt); - - ssd->compose.width = ssd->sink_fmt.width; - ssd->compose.height = ssd->sink_fmt.height; - ssd->crop[ssd->source_pad] = ssd->compose; - ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE; - if (ssd != sensor->pixel_array) { - ssd->crop[ssd->sink_pad] = ssd->compose; - ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK; - } - - ssd->sd.entity.ops = &ccs_entity_ops; - - if (ssd == sensor->src) - return; - - ssd->sd.internal_ops = &ccs_internal_ops; - ssd->sd.owner = THIS_MODULE; - ssd->sd.dev = &client->dev; - v4l2_set_subdevdata(&ssd->sd, client); -} - -static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -{ - struct ccs_subdev *ssd = to_ccs_subdev(sd); - struct ccs_sensor *sensor = ssd->sensor; - unsigned int i; - - mutex_lock(&sensor->mutex); - - for (i = 0; i < ssd->npads; i++) { - struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_get_try_format(sd, fh->pad, i); - struct v4l2_rect *try_crop = - v4l2_subdev_get_try_crop(sd, fh->pad, i); - struct v4l2_rect *try_comp; - - ccs_get_native_size(ssd, try_crop); - - try_fmt->width = try_crop->width; - try_fmt->height = try_crop->height; - try_fmt->code = sensor->internal_csi_format->code; - try_fmt->field = V4L2_FIELD_NONE; - - if (ssd != sensor->pixel_array) - continue; - - try_comp = v4l2_subdev_get_try_compose(sd, fh->pad, i); - *try_comp = *try_crop; - } - - mutex_unlock(&sensor->mutex); - - return 0; -} - -static const struct v4l2_subdev_video_ops ccs_video_ops = { - .s_stream = ccs_set_stream, -}; - -static const struct v4l2_subdev_pad_ops ccs_pad_ops = { - .enum_mbus_code = ccs_enum_mbus_code, - .get_fmt = ccs_get_format, - .set_fmt = ccs_set_format, - .get_selection = ccs_get_selection, - .set_selection = ccs_set_selection, -}; - -static const struct v4l2_subdev_sensor_ops ccs_sensor_ops = { - .g_skip_frames = ccs_get_skip_frames, - .g_skip_top_lines = ccs_get_skip_top_lines, -}; - -static const struct v4l2_subdev_ops ccs_ops = { - .video = &ccs_video_ops, - .pad = &ccs_pad_ops, - .sensor = &ccs_sensor_ops, -}; - -static const struct media_entity_operations ccs_entity_ops = { - .link_validate = v4l2_subdev_link_validate, -}; - -static const struct v4l2_subdev_internal_ops ccs_internal_src_ops = { - .registered = ccs_registered, - .unregistered = ccs_unregistered, - .open = ccs_open, -}; - -static const struct v4l2_subdev_internal_ops ccs_internal_ops = { - .open = ccs_open, -}; - -/* ----------------------------------------------------------------------------- - * I2C Driver - */ - -static int __maybe_unused ccs_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct v4l2_subdev *subdev = i2c_get_clientdata(client); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - bool streaming = sensor->streaming; - int rval; - - rval = pm_runtime_get_sync(dev); - if (rval < 0) { - if (rval != -EBUSY && rval != -EAGAIN) - pm_runtime_set_active(&client->dev); - pm_runtime_put(dev); - return -EAGAIN; - } - - if (sensor->streaming) - ccs_stop_streaming(sensor); - - /* save state for resume */ - sensor->streaming = streaming; - - return 0; -} - -static int __maybe_unused ccs_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct v4l2_subdev *subdev = i2c_get_clientdata(client); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - int rval = 0; - - pm_runtime_put(dev); - - if (sensor->streaming) - rval = ccs_start_streaming(sensor); - - return rval; -} - -static struct ccs_hwconfig *ccs_get_hwconfig(struct device *dev) -{ - struct ccs_hwconfig *hwcfg; - struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; - struct fwnode_handle *ep; - struct fwnode_handle *fwnode = dev_fwnode(dev); - u32 rotation; - int i; - int rval; - - if (!fwnode) - return dev->platform_data; - - ep = fwnode_graph_get_next_endpoint(fwnode, NULL); - if (!ep) - return NULL; - - bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY; - rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); - if (rval == -ENXIO) { - bus_cfg = (struct v4l2_fwnode_endpoint) - { .bus_type = V4L2_MBUS_CCP2 }; - rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); - } - if (rval) - goto out_err; - - hwcfg = devm_kzalloc(dev, sizeof(*hwcfg), GFP_KERNEL); - if (!hwcfg) - goto out_err; - - switch (bus_cfg.bus_type) { - case V4L2_MBUS_CSI2_DPHY: - hwcfg->csi_signalling_mode = CCS_CSI_SIGNALING_MODE_CSI_2_DPHY; - hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; - break; - case V4L2_MBUS_CCP2: - hwcfg->csi_signalling_mode = (bus_cfg.bus.mipi_csi1.strobe) ? - SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE : - SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK; - hwcfg->lanes = 1; - break; - default: - dev_err(dev, "unsupported bus %u\n", bus_cfg.bus_type); - goto out_err; - } - - dev_dbg(dev, "lanes %u\n", hwcfg->lanes); - - rval = fwnode_property_read_u32(fwnode, "rotation", &rotation); - if (!rval) { - switch (rotation) { - case 180: - hwcfg->module_board_orient = - CCS_MODULE_BOARD_ORIENT_180; - fallthrough; - case 0: - break; - default: - dev_err(dev, "invalid rotation %u\n", rotation); - goto out_err; - } - } - - rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", - &hwcfg->ext_clk); - if (rval) - dev_info(dev, "can't get clock-frequency\n"); - - dev_dbg(dev, "clk %d, mode %d\n", hwcfg->ext_clk, - hwcfg->csi_signalling_mode); - - if (!bus_cfg.nr_of_link_frequencies) { - dev_warn(dev, "no link frequencies defined\n"); - goto out_err; - } - - hwcfg->op_sys_clock = devm_kcalloc( - dev, bus_cfg.nr_of_link_frequencies + 1 /* guardian */, - sizeof(*hwcfg->op_sys_clock), GFP_KERNEL); - if (!hwcfg->op_sys_clock) - goto out_err; - - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { - hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i]; - dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]); - } - - v4l2_fwnode_endpoint_free(&bus_cfg); - fwnode_handle_put(ep); - return hwcfg; - -out_err: - v4l2_fwnode_endpoint_free(&bus_cfg); - fwnode_handle_put(ep); - return NULL; -} - -static int ccs_probe(struct i2c_client *client) -{ - struct ccs_sensor *sensor; - struct ccs_hwconfig *hwcfg = ccs_get_hwconfig(&client->dev); - unsigned int i; - int rval; - - if (hwcfg == NULL) - return -ENODEV; - - sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); - if (sensor == NULL) - return -ENOMEM; - - sensor->hwcfg = hwcfg; - sensor->src = &sensor->ssds[sensor->ssds_used]; - - v4l2_i2c_subdev_init(&sensor->src->sd, client, &ccs_ops); - sensor->src->sd.internal_ops = &ccs_internal_src_ops; - - sensor->vana = devm_regulator_get(&client->dev, "vana"); - if (IS_ERR(sensor->vana)) { - dev_err(&client->dev, "could not get regulator for vana\n"); - return PTR_ERR(sensor->vana); - } - - sensor->ext_clk = devm_clk_get(&client->dev, NULL); - if (PTR_ERR(sensor->ext_clk) == -ENOENT) { - dev_info(&client->dev, "no clock defined, continuing...\n"); - sensor->ext_clk = NULL; - } else if (IS_ERR(sensor->ext_clk)) { - dev_err(&client->dev, "could not get clock (%ld)\n", - PTR_ERR(sensor->ext_clk)); - return -EPROBE_DEFER; - } - - if (sensor->ext_clk) { - if (sensor->hwcfg->ext_clk) { - unsigned long rate; - - rval = clk_set_rate(sensor->ext_clk, - sensor->hwcfg->ext_clk); - if (rval < 0) { - dev_err(&client->dev, - "unable to set clock freq to %u\n", - sensor->hwcfg->ext_clk); - return rval; - } - - rate = clk_get_rate(sensor->ext_clk); - if (rate != sensor->hwcfg->ext_clk) { - dev_err(&client->dev, - "can't set clock freq, asked for %u but got %lu\n", - sensor->hwcfg->ext_clk, rate); - return rval; - } - } else { - sensor->hwcfg->ext_clk = clk_get_rate(sensor->ext_clk); - dev_dbg(&client->dev, "obtained clock freq %u\n", - sensor->hwcfg->ext_clk); - } - } else if (sensor->hwcfg->ext_clk) { - dev_dbg(&client->dev, "assuming clock freq %u\n", - sensor->hwcfg->ext_clk); - } else { - dev_err(&client->dev, "unable to obtain clock freq\n"); - return -EINVAL; - } - - sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown", - GPIOD_OUT_LOW); - if (IS_ERR(sensor->xshutdown)) - return PTR_ERR(sensor->xshutdown); - - rval = ccs_power_on(&client->dev); - if (rval < 0) - return rval; - - mutex_init(&sensor->mutex); - - rval = ccs_identify_module(sensor); - if (rval) { - rval = -ENODEV; - goto out_power_off; - } - - rval = ccs_read_all_limits(sensor); - if (rval) - goto out_power_off; - - rval = ccs_read_frame_fmt(sensor); - if (rval) { - rval = -ENODEV; - goto out_free_ccs_limits; - } - - /* - * Handle Sensor Module orientation on the board. - * - * The application of H-FLIP and V-FLIP on the sensor is modified by - * the sensor orientation on the board. - * - * For CCS_BOARD_SENSOR_ORIENT_180 the default behaviour is to set - * both H-FLIP and V-FLIP for normal operation which also implies - * that a set/unset operation for user space HFLIP and VFLIP v4l2 - * controls will need to be internally inverted. - * - * Rotation also changes the bayer pattern. - */ - if (sensor->hwcfg->module_board_orient == - CCS_MODULE_BOARD_ORIENT_180) - sensor->hvflip_inv_mask = - CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR | - CCS_IMAGE_ORIENTATION_VERTICAL_FLIP; - - rval = ccs_call_quirk(sensor, limits); - if (rval) { - dev_err(&client->dev, "limits quirks failed\n"); - goto out_free_ccs_limits; - } - - if (CCS_LIM(sensor, BINNING_CAPABILITY)) { - sensor->nbinning_subtypes = - min_t(u8, CCS_LIM(sensor, BINNING_SUB_TYPES), - CCS_LIM_BINNING_SUB_TYPE_MAX_N); - - for (i = 0; i < sensor->nbinning_subtypes; i++) { - sensor->binning_subtypes[i].horizontal = - CCS_LIM_AT(sensor, BINNING_SUB_TYPE, i) >> - CCS_BINNING_SUB_TYPE_COLUMN_SHIFT; - sensor->binning_subtypes[i].vertical = - CCS_LIM_AT(sensor, BINNING_SUB_TYPE, i) & - CCS_BINNING_SUB_TYPE_ROW_MASK; - - dev_dbg(&client->dev, "binning %xx%x\n", - sensor->binning_subtypes[i].horizontal, - sensor->binning_subtypes[i].vertical); - } - } - sensor->binning_horizontal = 1; - sensor->binning_vertical = 1; - - if (device_create_file(&client->dev, &dev_attr_ident) != 0) { - dev_err(&client->dev, "sysfs ident entry creation failed\n"); - rval = -ENOENT; - goto out_free_ccs_limits; - } - - if (sensor->minfo.smiapp_version && - CCS_LIM(sensor, DATA_TRANSFER_IF_CAPABILITY) & - CCS_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED) { - if (device_create_file(&client->dev, &dev_attr_nvm) != 0) { - dev_err(&client->dev, "sysfs nvm entry failed\n"); - rval = -EBUSY; - goto out_cleanup; - } - } - - /* We consider this as profile 0 sensor if any of these are zero. */ - if (!CCS_LIM(sensor, MIN_OP_SYS_CLK_DIV) || - !CCS_LIM(sensor, MAX_OP_SYS_CLK_DIV) || - !CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV) || - !CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV)) { - sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0; - } else if (CCS_LIM(sensor, SCALING_CAPABILITY) - != CCS_SCALING_CAPABILITY_NONE) { - if (CCS_LIM(sensor, SCALING_CAPABILITY) - == CCS_SCALING_CAPABILITY_HORIZONTAL) - sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1; - else - sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2; - sensor->scaler = &sensor->ssds[sensor->ssds_used]; - sensor->ssds_used++; - } else if (CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) - == CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP) { - sensor->scaler = &sensor->ssds[sensor->ssds_used]; - sensor->ssds_used++; - } - sensor->binner = &sensor->ssds[sensor->ssds_used]; - sensor->ssds_used++; - sensor->pixel_array = &sensor->ssds[sensor->ssds_used]; - sensor->ssds_used++; - - sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); - - /* prepare PLL configuration input values */ - sensor->pll.bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; - sensor->pll.csi2.lanes = sensor->hwcfg->lanes; - sensor->pll.ext_clk_freq_hz = sensor->hwcfg->ext_clk; - sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); - /* Profile 0 sensors have no separate OP clock branch. */ - if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) - sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; - - ccs_create_subdev(sensor, sensor->scaler, " scaler", 2); - ccs_create_subdev(sensor, sensor->binner, " binner", 2); - ccs_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1); - - dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); - - sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; - - rval = ccs_init_controls(sensor); - if (rval < 0) - goto out_cleanup; - - rval = ccs_call_quirk(sensor, init); - if (rval) - goto out_cleanup; - - rval = ccs_get_mbus_formats(sensor); - if (rval) { - rval = -ENODEV; - goto out_cleanup; - } - - rval = ccs_init_late_controls(sensor); - if (rval) { - rval = -ENODEV; - goto out_cleanup; - } - - mutex_lock(&sensor->mutex); - rval = ccs_pll_blanking_update(sensor); - mutex_unlock(&sensor->mutex); - if (rval) { - dev_err(&client->dev, "update mode failed\n"); - goto out_cleanup; - } - - sensor->streaming = false; - sensor->dev_init_done = true; - - rval = media_entity_pads_init(&sensor->src->sd.entity, 2, - sensor->src->pads); - if (rval < 0) - goto out_media_entity_cleanup; - - pm_runtime_set_active(&client->dev); - pm_runtime_get_noresume(&client->dev); - pm_runtime_enable(&client->dev); - - rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd); - if (rval < 0) - goto out_disable_runtime_pm; - - pm_runtime_set_autosuspend_delay(&client->dev, 1000); - pm_runtime_use_autosuspend(&client->dev); - pm_runtime_put_autosuspend(&client->dev); - - return 0; - -out_disable_runtime_pm: - pm_runtime_put_noidle(&client->dev); - pm_runtime_disable(&client->dev); - -out_media_entity_cleanup: - media_entity_cleanup(&sensor->src->sd.entity); - -out_cleanup: - ccs_cleanup(sensor); - -out_free_ccs_limits: - kfree(sensor->ccs_limits); - -out_power_off: - ccs_power_off(&client->dev); - mutex_destroy(&sensor->mutex); - - return rval; -} - -static int ccs_remove(struct i2c_client *client) -{ - struct v4l2_subdev *subdev = i2c_get_clientdata(client); - struct ccs_sensor *sensor = to_ccs_sensor(subdev); - unsigned int i; - - v4l2_async_unregister_subdev(subdev); - - pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) - ccs_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); - - for (i = 0; i < sensor->ssds_used; i++) { - v4l2_device_unregister_subdev(&sensor->ssds[i].sd); - media_entity_cleanup(&sensor->ssds[i].sd.entity); - } - ccs_cleanup(sensor); - mutex_destroy(&sensor->mutex); - kfree(sensor->ccs_limits); - - return 0; -} - -static const struct of_device_id ccs_of_table[] = { - { .compatible = "nokia,smia" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ccs_of_table); - -static const struct i2c_device_id ccs_id_table[] = { - { SMIAPP_NAME, 0 }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, ccs_id_table); - -static const struct dev_pm_ops ccs_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ccs_suspend, ccs_resume) - SET_RUNTIME_PM_OPS(ccs_power_off, ccs_power_on, NULL) -}; - -static struct i2c_driver ccs_i2c_driver = { - .driver = { - .of_match_table = ccs_of_table, - .name = CCS_NAME, - .pm = &ccs_pm_ops, - }, - .probe_new = ccs_probe, - .remove = ccs_remove, - .id_table = ccs_id_table, -}; - -static int ccs_module_init(void) -{ - unsigned int i, l; - - for (i = 0, l = 0; ccs_limits[i].size && l < CCS_L_LAST; i++) { - if (!(ccs_limits[i].flags & CCS_L_FL_SAME_REG)) { - ccs_limit_offsets[l + 1].lim = - ALIGN(ccs_limit_offsets[l].lim + - ccs_limits[i].size, - ccs_reg_width(ccs_limits[i + 1].reg)); - ccs_limit_offsets[l].info = i; - l++; - } else { - ccs_limit_offsets[l].lim += ccs_limits[i].size; - } - } - - if (WARN_ON(ccs_limits[i].size)) - return -EINVAL; - - if (WARN_ON(l != CCS_L_LAST)) - return -EINVAL; - - return i2c_register_driver(THIS_MODULE, &ccs_i2c_driver); -} - -static void ccs_module_cleanup(void) -{ - i2c_del_driver(&ccs_i2c_driver); -} - -module_init(ccs_module_init); -module_exit(ccs_module_cleanup); - -MODULE_AUTHOR("Sakari Ailus "); -MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ camera sensor driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/smiapp/ccs-limits.c b/drivers/media/i2c/smiapp/ccs-limits.c deleted file mode 100644 index f5511789ac83..000000000000 --- a/drivers/media/i2c/smiapp/ccs-limits.c +++ /dev/null @@ -1,239 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause -/* Copyright (C) 2019--2020 Intel Corporation */ - -#include "ccs-limits.h" -#include "ccs-regs.h" - -const struct ccs_limit ccs_limits[] = { - { CCS_R_FRAME_FORMAT_MODEL_TYPE, 1, 0, "frame_format_model_type" }, - { CCS_R_FRAME_FORMAT_MODEL_SUBTYPE, 1, 0, "frame_format_model_subtype" }, - { CCS_R_FRAME_FORMAT_DESCRIPTOR(0), 30, 0, "frame_format_descriptor" }, - { CCS_R_FRAME_FORMAT_DESCRIPTOR_4(0), 32, 0, "frame_format_descriptor_4" }, - { CCS_R_ANALOG_GAIN_CAPABILITY, 2, 0, "analog_gain_capability" }, - { CCS_R_ANALOG_GAIN_CODE_MIN, 2, 0, "analog_gain_code_min" }, - { CCS_R_ANALOG_GAIN_CODE_MAX, 2, 0, "analog_gain_code_max" }, - { CCS_R_ANALOG_GAIN_CODE_STEP, 2, 0, "analog_gain_code_step" }, - { CCS_R_ANALOG_GAIN_TYPE, 2, 0, "analog_gain_type" }, - { CCS_R_ANALOG_GAIN_M0, 2, 0, "analog_gain_m0" }, - { CCS_R_ANALOG_GAIN_C0, 2, 0, "analog_gain_c0" }, - { CCS_R_ANALOG_GAIN_M1, 2, 0, "analog_gain_m1" }, - { CCS_R_ANALOG_GAIN_C1, 2, 0, "analog_gain_c1" }, - { CCS_R_ANALOG_LINEAR_GAIN_MIN, 2, 0, "analog_linear_gain_min" }, - { CCS_R_ANALOG_LINEAR_GAIN_MAX, 2, 0, "analog_linear_gain_max" }, - { CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE, 2, 0, "analog_linear_gain_step_size" }, - { CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN, 2, 0, "analog_exponential_gain_min" }, - { CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX, 2, 0, "analog_exponential_gain_max" }, - { CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE, 2, 0, "analog_exponential_gain_step_size" }, - { CCS_R_DATA_FORMAT_MODEL_TYPE, 1, 0, "data_format_model_type" }, - { CCS_R_DATA_FORMAT_MODEL_SUBTYPE, 1, 0, "data_format_model_subtype" }, - { CCS_R_DATA_FORMAT_DESCRIPTOR(0), 32, 0, "data_format_descriptor" }, - { CCS_R_INTEGRATION_TIME_CAPABILITY, 2, 0, "integration_time_capability" }, - { CCS_R_COARSE_INTEGRATION_TIME_MIN, 2, 0, "coarse_integration_time_min" }, - { CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN, 2, 0, "coarse_integration_time_max_margin" }, - { CCS_R_FINE_INTEGRATION_TIME_MIN, 2, 0, "fine_integration_time_min" }, - { CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN, 2, 0, "fine_integration_time_max_margin" }, - { CCS_R_DIGITAL_GAIN_CAPABILITY, 1, 0, "digital_gain_capability" }, - { CCS_R_DIGITAL_GAIN_MIN, 2, 0, "digital_gain_min" }, - { CCS_R_DIGITAL_GAIN_MAX, 2, 0, "digital_gain_max" }, - { CCS_R_DIGITAL_GAIN_STEP_SIZE, 2, 0, "digital_gain_step_size" }, - { CCS_R_PEDESTAL_CAPABILITY, 1, 0, "Pedestal_capability" }, - { CCS_R_ADC_CAPABILITY, 1, 0, "ADC_capability" }, - { CCS_R_ADC_BIT_DEPTH_CAPABILITY, 4, 0, "ADC_bit_depth_capability" }, - { CCS_R_MIN_EXT_CLK_FREQ_MHZ, 4, 0, "min_ext_clk_freq_mhz" }, - { CCS_R_MAX_EXT_CLK_FREQ_MHZ, 4, 0, "max_ext_clk_freq_mhz" }, - { CCS_R_MIN_PRE_PLL_CLK_DIV, 2, 0, "min_pre_pll_clk_div" }, - { CCS_R_MAX_PRE_PLL_CLK_DIV, 2, 0, "max_pre_pll_clk_div" }, - { CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ, 4, 0, "min_pll_ip_clk_freq_mhz" }, - { CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ, 4, 0, "max_pll_ip_clk_freq_mhz" }, - { CCS_R_MIN_PLL_MULTIPLIER, 2, 0, "min_pll_multiplier" }, - { CCS_R_MAX_PLL_MULTIPLIER, 2, 0, "max_pll_multiplier" }, - { CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ, 4, 0, "min_pll_op_clk_freq_mhz" }, - { CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ, 4, 0, "max_pll_op_clk_freq_mhz" }, - { CCS_R_MIN_VT_SYS_CLK_DIV, 2, 0, "min_vt_sys_clk_div" }, - { CCS_R_MAX_VT_SYS_CLK_DIV, 2, 0, "max_vt_sys_clk_div" }, - { CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ, 4, 0, "min_vt_sys_clk_freq_mhz" }, - { CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ, 4, 0, "max_vt_sys_clk_freq_mhz" }, - { CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ, 4, 0, "min_vt_pix_clk_freq_mhz" }, - { CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ, 4, 0, "max_vt_pix_clk_freq_mhz" }, - { CCS_R_MIN_VT_PIX_CLK_DIV, 2, 0, "min_vt_pix_clk_div" }, - { CCS_R_MAX_VT_PIX_CLK_DIV, 2, 0, "max_vt_pix_clk_div" }, - { CCS_R_CLOCK_CALCULATION, 1, 0, "clock_calculation" }, - { CCS_R_NUM_OF_VT_LANES, 1, 0, "num_of_vt_lanes" }, - { CCS_R_NUM_OF_OP_LANES, 1, 0, "num_of_op_lanes" }, - { CCS_R_OP_BITS_PER_LANE, 1, 0, "op_bits_per_lane" }, - { CCS_R_MIN_FRAME_LENGTH_LINES, 2, 0, "min_frame_length_lines" }, - { CCS_R_MAX_FRAME_LENGTH_LINES, 2, 0, "max_frame_length_lines" }, - { CCS_R_MIN_LINE_LENGTH_PCK, 2, 0, "min_line_length_pck" }, - { CCS_R_MAX_LINE_LENGTH_PCK, 2, 0, "max_line_length_pck" }, - { CCS_R_MIN_LINE_BLANKING_PCK, 2, 0, "min_line_blanking_pck" }, - { CCS_R_MIN_FRAME_BLANKING_LINES, 2, 0, "min_frame_blanking_lines" }, - { CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE, 1, 0, "min_line_length_pck_step_size" }, - { CCS_R_TIMING_MODE_CAPABILITY, 1, 0, "timing_mode_capability" }, - { CCS_R_FRAME_MARGIN_MAX_VALUE, 2, 0, "frame_margin_max_value" }, - { CCS_R_FRAME_MARGIN_MIN_VALUE, 1, 0, "frame_margin_min_value" }, - { CCS_R_GAIN_DELAY_TYPE, 1, 0, "gain_delay_type" }, - { CCS_R_MIN_OP_SYS_CLK_DIV, 2, 0, "min_op_sys_clk_div" }, - { CCS_R_MAX_OP_SYS_CLK_DIV, 2, 0, "max_op_sys_clk_div" }, - { CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ, 4, 0, "min_op_sys_clk_freq_mhz" }, - { CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ, 4, 0, "max_op_sys_clk_freq_mhz" }, - { CCS_R_MIN_OP_PIX_CLK_DIV, 2, 0, "min_op_pix_clk_div" }, - { CCS_R_MAX_OP_PIX_CLK_DIV, 2, 0, "max_op_pix_clk_div" }, - { CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ, 4, 0, "min_op_pix_clk_freq_mhz" }, - { CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ, 4, 0, "max_op_pix_clk_freq_mhz" }, - { CCS_R_X_ADDR_MIN, 2, 0, "x_addr_min" }, - { CCS_R_Y_ADDR_MIN, 2, 0, "y_addr_min" }, - { CCS_R_X_ADDR_MAX, 2, 0, "x_addr_max" }, - { CCS_R_Y_ADDR_MAX, 2, 0, "y_addr_max" }, - { CCS_R_MIN_X_OUTPUT_SIZE, 2, 0, "min_x_output_size" }, - { CCS_R_MIN_Y_OUTPUT_SIZE, 2, 0, "min_y_output_size" }, - { CCS_R_MAX_X_OUTPUT_SIZE, 2, 0, "max_x_output_size" }, - { CCS_R_MAX_Y_OUTPUT_SIZE, 2, 0, "max_y_output_size" }, - { CCS_R_X_ADDR_START_DIV_CONSTANT, 1, 0, "x_addr_start_div_constant" }, - { CCS_R_Y_ADDR_START_DIV_CONSTANT, 1, 0, "y_addr_start_div_constant" }, - { CCS_R_X_ADDR_END_DIV_CONSTANT, 1, 0, "x_addr_end_div_constant" }, - { CCS_R_Y_ADDR_END_DIV_CONSTANT, 1, 0, "y_addr_end_div_constant" }, - { CCS_R_X_SIZE_DIV, 1, 0, "x_size_div" }, - { CCS_R_Y_SIZE_DIV, 1, 0, "y_size_div" }, - { CCS_R_X_OUTPUT_DIV, 1, 0, "x_output_div" }, - { CCS_R_Y_OUTPUT_DIV, 1, 0, "y_output_div" }, - { CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT, 1, 0, "non_flexible_resolution_support" }, - { CCS_R_MIN_OP_PRE_PLL_CLK_DIV, 2, 0, "min_op_pre_pll_clk_div" }, - { CCS_R_MAX_OP_PRE_PLL_CLK_DIV, 2, 0, "max_op_pre_pll_clk_div" }, - { CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ, 4, 0, "min_op_pll_ip_clk_freq_mhz" }, - { CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ, 4, 0, "max_op_pll_ip_clk_freq_mhz" }, - { CCS_R_MIN_OP_PLL_MULTIPLIER, 2, 0, "min_op_pll_multiplier" }, - { CCS_R_MAX_OP_PLL_MULTIPLIER, 2, 0, "max_op_pll_multiplier" }, - { CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ, 4, 0, "min_op_pll_op_clk_freq_mhz" }, - { CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ, 4, 0, "max_op_pll_op_clk_freq_mhz" }, - { CCS_R_CLOCK_TREE_PLL_CAPABILITY, 1, 0, "clock_tree_pll_capability" }, - { CCS_R_CLOCK_CAPA_TYPE_CAPABILITY, 1, 0, "clock_capa_type_capability" }, - { CCS_R_MIN_EVEN_INC, 2, 0, "min_even_inc" }, - { CCS_R_MIN_ODD_INC, 2, 0, "min_odd_inc" }, - { CCS_R_MAX_EVEN_INC, 2, 0, "max_even_inc" }, - { CCS_R_MAX_ODD_INC, 2, 0, "max_odd_inc" }, - { CCS_R_AUX_SUBSAMP_CAPABILITY, 1, 0, "aux_subsamp_capability" }, - { CCS_R_AUX_SUBSAMP_MONO_CAPABILITY, 1, 0, "aux_subsamp_mono_capability" }, - { CCS_R_MONOCHROME_CAPABILITY, 1, 0, "monochrome_capability" }, - { CCS_R_PIXEL_READOUT_CAPABILITY, 1, 0, "pixel_readout_capability" }, - { CCS_R_MIN_EVEN_INC_MONO, 2, 0, "min_even_inc_mono" }, - { CCS_R_MAX_EVEN_INC_MONO, 2, 0, "max_even_inc_mono" }, - { CCS_R_MIN_ODD_INC_MONO, 2, 0, "min_odd_inc_mono" }, - { CCS_R_MAX_ODD_INC_MONO, 2, 0, "max_odd_inc_mono" }, - { CCS_R_MIN_EVEN_INC_BC2, 2, 0, "min_even_inc_bc2" }, - { CCS_R_MAX_EVEN_INC_BC2, 2, 0, "max_even_inc_bc2" }, - { CCS_R_MIN_ODD_INC_BC2, 2, 0, "min_odd_inc_bc2" }, - { CCS_R_MAX_ODD_INC_BC2, 2, 0, "max_odd_inc_bc2" }, - { CCS_R_MIN_EVEN_INC_MONO_BC2, 2, 0, "min_even_inc_mono_bc2" }, - { CCS_R_MAX_EVEN_INC_MONO_BC2, 2, 0, "max_even_inc_mono_bc2" }, - { CCS_R_MIN_ODD_INC_MONO_BC2, 2, 0, "min_odd_inc_mono_bc2" }, - { CCS_R_MAX_ODD_INC_MONO_BC2, 2, 0, "max_odd_inc_mono_bc2" }, - { CCS_R_SCALING_CAPABILITY, 2, 0, "scaling_capability" }, - { CCS_R_SCALER_M_MIN, 2, 0, "scaler_m_min" }, - { CCS_R_SCALER_M_MAX, 2, 0, "scaler_m_max" }, - { CCS_R_SCALER_N_MIN, 2, 0, "scaler_n_min" }, - { CCS_R_SCALER_N_MAX, 2, 0, "scaler_n_max" }, - { CCS_R_DIGITAL_CROP_CAPABILITY, 1, 0, "digital_crop_capability" }, - { CCS_R_HDR_CAPABILITY_1, 1, 0, "hdr_capability_1" }, - { CCS_R_MIN_HDR_BIT_DEPTH, 1, 0, "min_hdr_bit_depth" }, - { CCS_R_HDR_RESOLUTION_SUB_TYPES, 1, 0, "hdr_resolution_sub_types" }, - { CCS_R_HDR_RESOLUTION_SUB_TYPE(0), 2, 0, "hdr_resolution_sub_type" }, - { CCS_R_HDR_CAPABILITY_2, 1, 0, "hdr_capability_2" }, - { CCS_R_MAX_HDR_BIT_DEPTH, 1, 0, "max_hdr_bit_depth" }, - { CCS_R_USL_SUPPORT_CAPABILITY, 1, 0, "usl_support_capability" }, - { CCS_R_USL_CLOCK_MODE_D_CAPABILITY, 1, 0, "usl_clock_mode_d_capability" }, - { CCS_R_MIN_OP_SYS_CLK_DIV_REV, 1, 0, "min_op_sys_clk_div_rev" }, - { CCS_R_MAX_OP_SYS_CLK_DIV_REV, 1, 0, "max_op_sys_clk_div_rev" }, - { CCS_R_MIN_OP_PIX_CLK_DIV_REV, 1, 0, "min_op_pix_clk_div_rev" }, - { CCS_R_MAX_OP_PIX_CLK_DIV_REV, 1, 0, "max_op_pix_clk_div_rev" }, - { CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ, 4, 0, "min_op_sys_clk_freq_rev_mhz" }, - { CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ, 4, 0, "max_op_sys_clk_freq_rev_mhz" }, - { CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ, 4, 0, "min_op_pix_clk_freq_rev_mhz" }, - { CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ, 4, 0, "max_op_pix_clk_freq_rev_mhz" }, - { CCS_R_MAX_BITRATE_REV_D_MODE_MBPS, 4, 0, "max_bitrate_rev_d_mode_mbps" }, - { CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS, 4, 0, "max_symrate_rev_c_mode_msps" }, - { CCS_R_COMPRESSION_CAPABILITY, 1, 0, "compression_capability" }, - { CCS_R_TEST_MODE_CAPABILITY, 2, 0, "test_mode_capability" }, - { CCS_R_PN9_DATA_FORMAT1, 1, 0, "pn9_data_format1" }, - { CCS_R_PN9_DATA_FORMAT2, 1, 0, "pn9_data_format2" }, - { CCS_R_PN9_DATA_FORMAT3, 1, 0, "pn9_data_format3" }, - { CCS_R_PN9_DATA_FORMAT4, 1, 0, "pn9_data_format4" }, - { CCS_R_PN9_MISC_CAPABILITY, 1, 0, "pn9_misc_capability" }, - { CCS_R_TEST_PATTERN_CAPABILITY, 1, 0, "test_pattern_capability" }, - { CCS_R_PATTERN_SIZE_DIV_M1, 1, 0, "pattern_size_div_m1" }, - { CCS_R_FIFO_SUPPORT_CAPABILITY, 1, 0, "fifo_support_capability" }, - { CCS_R_PHY_CTRL_CAPABILITY, 1, 0, "phy_ctrl_capability" }, - { CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY, 1, 0, "csi_dphy_lane_mode_capability" }, - { CCS_R_CSI_SIGNALING_MODE_CAPABILITY, 1, 0, "csi_signaling_mode_capability" }, - { CCS_R_FAST_STANDBY_CAPABILITY, 1, 0, "fast_standby_capability" }, - { CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY, 1, 0, "csi_address_control_capability" }, - { CCS_R_DATA_TYPE_CAPABILITY, 1, 0, "data_type_capability" }, - { CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY, 1, 0, "csi_cphy_lane_mode_capability" }, - { CCS_R_EMB_DATA_CAPABILITY, 1, 0, "emb_data_capability" }, - { CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(0), 16, 0, "max_per_lane_bitrate_lane_d_mode_mbps 0" }, - { CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(4), 16, CCS_L_FL_SAME_REG, "max_per_lane_bitrate_lane_d_mode_mbps 4" }, - { CCS_R_TEMP_SENSOR_CAPABILITY, 1, 0, "temp_sensor_capability" }, - { CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(0), 16, 0, "max_per_lane_bitrate_lane_c_mode_mbps 0" }, - { CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(4), 16, CCS_L_FL_SAME_REG, "max_per_lane_bitrate_lane_c_mode_mbps 4" }, - { CCS_R_DPHY_EQUALIZATION_CAPABILITY, 1, 0, "dphy_equalization_capability" }, - { CCS_R_CPHY_EQUALIZATION_CAPABILITY, 1, 0, "cphy_equalization_capability" }, - { CCS_R_DPHY_PREAMBLE_CAPABILITY, 1, 0, "dphy_preamble_capability" }, - { CCS_R_DPHY_SSC_CAPABILITY, 1, 0, "dphy_ssc_capability" }, - { CCS_R_CPHY_CALIBRATION_CAPABILITY, 1, 0, "cphy_calibration_capability" }, - { CCS_R_DPHY_CALIBRATION_CAPABILITY, 1, 0, "dphy_calibration_capability" }, - { CCS_R_PHY_CTRL_CAPABILITY_2, 1, 0, "phy_ctrl_capability_2" }, - { CCS_R_LRTE_CPHY_CAPABILITY, 1, 0, "lrte_cphy_capability" }, - { CCS_R_LRTE_DPHY_CAPABILITY, 1, 0, "lrte_dphy_capability" }, - { CCS_R_ALPS_CAPABILITY_DPHY, 1, 0, "alps_capability_dphy" }, - { CCS_R_ALPS_CAPABILITY_CPHY, 1, 0, "alps_capability_cphy" }, - { CCS_R_SCRAMBLING_CAPABILITY, 1, 0, "scrambling_capability" }, - { CCS_R_DPHY_MANUAL_CONSTANT, 1, 0, "dphy_manual_constant" }, - { CCS_R_CPHY_MANUAL_CONSTANT, 1, 0, "cphy_manual_constant" }, - { CCS_R_CSI2_INTERFACE_CAPABILITY_MISC, 1, 0, "CSI2_interface_capability_misc" }, - { CCS_R_PHY_CTRL_CAPABILITY_3, 1, 0, "PHY_ctrl_capability_3" }, - { CCS_R_DPHY_SF, 1, 0, "dphy_sf" }, - { CCS_R_CPHY_SF, 1, 0, "cphy_sf" }, - { CCS_R_DPHY_LIMITS_1, 1, 0, "dphy_limits_1" }, - { CCS_R_DPHY_LIMITS_2, 1, 0, "dphy_limits_2" }, - { CCS_R_DPHY_LIMITS_3, 1, 0, "dphy_limits_3" }, - { CCS_R_DPHY_LIMITS_4, 1, 0, "dphy_limits_4" }, - { CCS_R_DPHY_LIMITS_5, 1, 0, "dphy_limits_5" }, - { CCS_R_DPHY_LIMITS_6, 1, 0, "dphy_limits_6" }, - { CCS_R_CPHY_LIMITS_1, 1, 0, "cphy_limits_1" }, - { CCS_R_CPHY_LIMITS_2, 1, 0, "cphy_limits_2" }, - { CCS_R_CPHY_LIMITS_3, 1, 0, "cphy_limits_3" }, - { CCS_R_MIN_FRAME_LENGTH_LINES_BIN, 2, 0, "min_frame_length_lines_bin" }, - { CCS_R_MAX_FRAME_LENGTH_LINES_BIN, 2, 0, "max_frame_length_lines_bin" }, - { CCS_R_MIN_LINE_LENGTH_PCK_BIN, 2, 0, "min_line_length_pck_bin" }, - { CCS_R_MAX_LINE_LENGTH_PCK_BIN, 2, 0, "max_line_length_pck_bin" }, - { CCS_R_MIN_LINE_BLANKING_PCK_BIN, 2, 0, "min_line_blanking_pck_bin" }, - { CCS_R_FINE_INTEGRATION_TIME_MIN_BIN, 2, 0, "fine_integration_time_min_bin" }, - { CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN, 2, 0, "fine_integration_time_max_margin_bin" }, - { CCS_R_BINNING_CAPABILITY, 1, 0, "binning_capability" }, - { CCS_R_BINNING_WEIGHTING_CAPABILITY, 1, 0, "binning_weighting_capability" }, - { CCS_R_BINNING_SUB_TYPES, 1, 0, "binning_sub_types" }, - { CCS_R_BINNING_SUB_TYPE(0), 64, 0, "binning_sub_type" }, - { CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY, 1, 0, "binning_weighting_mono_capability" }, - { CCS_R_BINNING_SUB_TYPES_MONO, 1, 0, "binning_sub_types_mono" }, - { CCS_R_BINNING_SUB_TYPE_MONO(0), 64, 0, "binning_sub_type_mono" }, - { CCS_R_DATA_TRANSFER_IF_CAPABILITY, 1, 0, "data_transfer_if_capability" }, - { CCS_R_SHADING_CORRECTION_CAPABILITY, 1, 0, "shading_correction_capability" }, - { CCS_R_GREEN_IMBALANCE_CAPABILITY, 1, 0, "green_imbalance_capability" }, - { CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY, 1, 0, "module_specific_correction_capability" }, - { CCS_R_DEFECT_CORRECTION_CAPABILITY, 2, 0, "defect_correction_capability" }, - { CCS_R_DEFECT_CORRECTION_CAPABILITY_2, 2, 0, "defect_correction_capability_2" }, - { CCS_R_NF_CAPABILITY, 1, 0, "nf_capability" }, - { CCS_R_OB_READOUT_CAPABILITY, 1, 0, "ob_readout_capability" }, - { CCS_R_COLOR_FEEDBACK_CAPABILITY, 1, 0, "color_feedback_capability" }, - { CCS_R_CFA_PATTERN_CAPABILITY, 1, 0, "CFA_pattern_capability" }, - { CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY, 1, 0, "CFA_pattern_conversion_capability" }, - { CCS_R_FLASH_MODE_CAPABILITY, 1, 0, "flash_mode_capability" }, - { CCS_R_SA_STROBE_MODE_CAPABILITY, 1, 0, "sa_strobe_mode_capability" }, - { CCS_R_RESET_MAX_DELAY, 1, 0, "reset_max_delay" }, - { CCS_R_RESET_MIN_TIME, 1, 0, "reset_min_time" }, - { CCS_R_PDAF_CAPABILITY_1, 1, 0, "pdaf_capability_1" }, - { CCS_R_PDAF_CAPABILITY_2, 1, 0, "pdaf_capability_2" }, - { CCS_R_BRACKETING_LUT_CAPABILITY_1, 1, 0, "bracketing_lut_capability_1" }, - { CCS_R_BRACKETING_LUT_CAPABILITY_2, 1, 0, "bracketing_lut_capability_2" }, - { CCS_R_BRACKETING_LUT_SIZE, 1, 0, "bracketing_lut_size" }, - { 0 } /* Guardian */ -}; diff --git a/drivers/media/i2c/smiapp/ccs-limits.h b/drivers/media/i2c/smiapp/ccs-limits.h deleted file mode 100644 index 1efa43c23a2e..000000000000 --- a/drivers/media/i2c/smiapp/ccs-limits.h +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ -/* Copyright (C) 2019--2020 Intel Corporation */ - -#ifndef __CCS_LIMITS_H__ -#define __CCS_LIMITS_H__ - -#include -#include - -struct ccs_limit { - u32 reg; - u16 size; - u16 flags; - const char *name; -}; - -#define CCS_L_FL_SAME_REG BIT(0) - -extern const struct ccs_limit ccs_limits[]; - -#define CCS_L_FRAME_FORMAT_MODEL_TYPE 0 -#define CCS_L_FRAME_FORMAT_MODEL_SUBTYPE 1 -#define CCS_L_FRAME_FORMAT_DESCRIPTOR 2 -#define CCS_L_FRAME_FORMAT_DESCRIPTOR_OFFSET(n) ((n) * 2) -#define CCS_L_FRAME_FORMAT_DESCRIPTOR_4 3 -#define CCS_L_FRAME_FORMAT_DESCRIPTOR_4_OFFSET(n) ((n) * 4) -#define CCS_L_ANALOG_GAIN_CAPABILITY 4 -#define CCS_L_ANALOG_GAIN_CODE_MIN 5 -#define CCS_L_ANALOG_GAIN_CODE_MAX 6 -#define CCS_L_ANALOG_GAIN_CODE_STEP 7 -#define CCS_L_ANALOG_GAIN_TYPE 8 -#define CCS_L_ANALOG_GAIN_M0 9 -#define CCS_L_ANALOG_GAIN_C0 10 -#define CCS_L_ANALOG_GAIN_M1 11 -#define CCS_L_ANALOG_GAIN_C1 12 -#define CCS_L_ANALOG_LINEAR_GAIN_MIN 13 -#define CCS_L_ANALOG_LINEAR_GAIN_MAX 14 -#define CCS_L_ANALOG_LINEAR_GAIN_STEP_SIZE 15 -#define CCS_L_ANALOG_EXPONENTIAL_GAIN_MIN 16 -#define CCS_L_ANALOG_EXPONENTIAL_GAIN_MAX 17 -#define CCS_L_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE 18 -#define CCS_L_DATA_FORMAT_MODEL_TYPE 19 -#define CCS_L_DATA_FORMAT_MODEL_SUBTYPE 20 -#define CCS_L_DATA_FORMAT_DESCRIPTOR 21 -#define CCS_L_DATA_FORMAT_DESCRIPTOR_OFFSET(n) ((n) * 2) -#define CCS_L_INTEGRATION_TIME_CAPABILITY 22 -#define CCS_L_COARSE_INTEGRATION_TIME_MIN 23 -#define CCS_L_COARSE_INTEGRATION_TIME_MAX_MARGIN 24 -#define CCS_L_FINE_INTEGRATION_TIME_MIN 25 -#define CCS_L_FINE_INTEGRATION_TIME_MAX_MARGIN 26 -#define CCS_L_DIGITAL_GAIN_CAPABILITY 27 -#define CCS_L_DIGITAL_GAIN_MIN 28 -#define CCS_L_DIGITAL_GAIN_MAX 29 -#define CCS_L_DIGITAL_GAIN_STEP_SIZE 30 -#define CCS_L_PEDESTAL_CAPABILITY 31 -#define CCS_L_ADC_CAPABILITY 32 -#define CCS_L_ADC_BIT_DEPTH_CAPABILITY 33 -#define CCS_L_MIN_EXT_CLK_FREQ_MHZ 34 -#define CCS_L_MAX_EXT_CLK_FREQ_MHZ 35 -#define CCS_L_MIN_PRE_PLL_CLK_DIV 36 -#define CCS_L_MAX_PRE_PLL_CLK_DIV 37 -#define CCS_L_MIN_PLL_IP_CLK_FREQ_MHZ 38 -#define CCS_L_MAX_PLL_IP_CLK_FREQ_MHZ 39 -#define CCS_L_MIN_PLL_MULTIPLIER 40 -#define CCS_L_MAX_PLL_MULTIPLIER 41 -#define CCS_L_MIN_PLL_OP_CLK_FREQ_MHZ 42 -#define CCS_L_MAX_PLL_OP_CLK_FREQ_MHZ 43 -#define CCS_L_MIN_VT_SYS_CLK_DIV 44 -#define CCS_L_MAX_VT_SYS_CLK_DIV 45 -#define CCS_L_MIN_VT_SYS_CLK_FREQ_MHZ 46 -#define CCS_L_MAX_VT_SYS_CLK_FREQ_MHZ 47 -#define CCS_L_MIN_VT_PIX_CLK_FREQ_MHZ 48 -#define CCS_L_MAX_VT_PIX_CLK_FREQ_MHZ 49 -#define CCS_L_MIN_VT_PIX_CLK_DIV 50 -#define CCS_L_MAX_VT_PIX_CLK_DIV 51 -#define CCS_L_CLOCK_CALCULATION 52 -#define CCS_L_NUM_OF_VT_LANES 53 -#define CCS_L_NUM_OF_OP_LANES 54 -#define CCS_L_OP_BITS_PER_LANE 55 -#define CCS_L_MIN_FRAME_LENGTH_LINES 56 -#define CCS_L_MAX_FRAME_LENGTH_LINES 57 -#define CCS_L_MIN_LINE_LENGTH_PCK 58 -#define CCS_L_MAX_LINE_LENGTH_PCK 59 -#define CCS_L_MIN_LINE_BLANKING_PCK 60 -#define CCS_L_MIN_FRAME_BLANKING_LINES 61 -#define CCS_L_MIN_LINE_LENGTH_PCK_STEP_SIZE 62 -#define CCS_L_TIMING_MODE_CAPABILITY 63 -#define CCS_L_FRAME_MARGIN_MAX_VALUE 64 -#define CCS_L_FRAME_MARGIN_MIN_VALUE 65 -#define CCS_L_GAIN_DELAY_TYPE 66 -#define CCS_L_MIN_OP_SYS_CLK_DIV 67 -#define CCS_L_MAX_OP_SYS_CLK_DIV 68 -#define CCS_L_MIN_OP_SYS_CLK_FREQ_MHZ 69 -#define CCS_L_MAX_OP_SYS_CLK_FREQ_MHZ 70 -#define CCS_L_MIN_OP_PIX_CLK_DIV 71 -#define CCS_L_MAX_OP_PIX_CLK_DIV 72 -#define CCS_L_MIN_OP_PIX_CLK_FREQ_MHZ 73 -#define CCS_L_MAX_OP_PIX_CLK_FREQ_MHZ 74 -#define CCS_L_X_ADDR_MIN 75 -#define CCS_L_Y_ADDR_MIN 76 -#define CCS_L_X_ADDR_MAX 77 -#define CCS_L_Y_ADDR_MAX 78 -#define CCS_L_MIN_X_OUTPUT_SIZE 79 -#define CCS_L_MIN_Y_OUTPUT_SIZE 80 -#define CCS_L_MAX_X_OUTPUT_SIZE 81 -#define CCS_L_MAX_Y_OUTPUT_SIZE 82 -#define CCS_L_X_ADDR_START_DIV_CONSTANT 83 -#define CCS_L_Y_ADDR_START_DIV_CONSTANT 84 -#define CCS_L_X_ADDR_END_DIV_CONSTANT 85 -#define CCS_L_Y_ADDR_END_DIV_CONSTANT 86 -#define CCS_L_X_SIZE_DIV 87 -#define CCS_L_Y_SIZE_DIV 88 -#define CCS_L_X_OUTPUT_DIV 89 -#define CCS_L_Y_OUTPUT_DIV 90 -#define CCS_L_NON_FLEXIBLE_RESOLUTION_SUPPORT 91 -#define CCS_L_MIN_OP_PRE_PLL_CLK_DIV 92 -#define CCS_L_MAX_OP_PRE_PLL_CLK_DIV 93 -#define CCS_L_MIN_OP_PLL_IP_CLK_FREQ_MHZ 94 -#define CCS_L_MAX_OP_PLL_IP_CLK_FREQ_MHZ 95 -#define CCS_L_MIN_OP_PLL_MULTIPLIER 96 -#define CCS_L_MAX_OP_PLL_MULTIPLIER 97 -#define CCS_L_MIN_OP_PLL_OP_CLK_FREQ_MHZ 98 -#define CCS_L_MAX_OP_PLL_OP_CLK_FREQ_MHZ 99 -#define CCS_L_CLOCK_TREE_PLL_CAPABILITY 100 -#define CCS_L_CLOCK_CAPA_TYPE_CAPABILITY 101 -#define CCS_L_MIN_EVEN_INC 102 -#define CCS_L_MIN_ODD_INC 103 -#define CCS_L_MAX_EVEN_INC 104 -#define CCS_L_MAX_ODD_INC 105 -#define CCS_L_AUX_SUBSAMP_CAPABILITY 106 -#define CCS_L_AUX_SUBSAMP_MONO_CAPABILITY 107 -#define CCS_L_MONOCHROME_CAPABILITY 108 -#define CCS_L_PIXEL_READOUT_CAPABILITY 109 -#define CCS_L_MIN_EVEN_INC_MONO 110 -#define CCS_L_MAX_EVEN_INC_MONO 111 -#define CCS_L_MIN_ODD_INC_MONO 112 -#define CCS_L_MAX_ODD_INC_MONO 113 -#define CCS_L_MIN_EVEN_INC_BC2 114 -#define CCS_L_MAX_EVEN_INC_BC2 115 -#define CCS_L_MIN_ODD_INC_BC2 116 -#define CCS_L_MAX_ODD_INC_BC2 117 -#define CCS_L_MIN_EVEN_INC_MONO_BC2 118 -#define CCS_L_MAX_EVEN_INC_MONO_BC2 119 -#define CCS_L_MIN_ODD_INC_MONO_BC2 120 -#define CCS_L_MAX_ODD_INC_MONO_BC2 121 -#define CCS_L_SCALING_CAPABILITY 122 -#define CCS_L_SCALER_M_MIN 123 -#define CCS_L_SCALER_M_MAX 124 -#define CCS_L_SCALER_N_MIN 125 -#define CCS_L_SCALER_N_MAX 126 -#define CCS_L_DIGITAL_CROP_CAPABILITY 127 -#define CCS_L_HDR_CAPABILITY_1 128 -#define CCS_L_MIN_HDR_BIT_DEPTH 129 -#define CCS_L_HDR_RESOLUTION_SUB_TYPES 130 -#define CCS_L_HDR_RESOLUTION_SUB_TYPE 131 -#define CCS_L_HDR_RESOLUTION_SUB_TYPE_OFFSET(n) (n) -#define CCS_L_HDR_CAPABILITY_2 132 -#define CCS_L_MAX_HDR_BIT_DEPTH 133 -#define CCS_L_USL_SUPPORT_CAPABILITY 134 -#define CCS_L_USL_CLOCK_MODE_D_CAPABILITY 135 -#define CCS_L_MIN_OP_SYS_CLK_DIV_REV 136 -#define CCS_L_MAX_OP_SYS_CLK_DIV_REV 137 -#define CCS_L_MIN_OP_PIX_CLK_DIV_REV 138 -#define CCS_L_MAX_OP_PIX_CLK_DIV_REV 139 -#define CCS_L_MIN_OP_SYS_CLK_FREQ_REV_MHZ 140 -#define CCS_L_MAX_OP_SYS_CLK_FREQ_REV_MHZ 141 -#define CCS_L_MIN_OP_PIX_CLK_FREQ_REV_MHZ 142 -#define CCS_L_MAX_OP_PIX_CLK_FREQ_REV_MHZ 143 -#define CCS_L_MAX_BITRATE_REV_D_MODE_MBPS 144 -#define CCS_L_MAX_SYMRATE_REV_C_MODE_MSPS 145 -#define CCS_L_COMPRESSION_CAPABILITY 146 -#define CCS_L_TEST_MODE_CAPABILITY 147 -#define CCS_L_PN9_DATA_FORMAT1 148 -#define CCS_L_PN9_DATA_FORMAT2 149 -#define CCS_L_PN9_DATA_FORMAT3 150 -#define CCS_L_PN9_DATA_FORMAT4 151 -#define CCS_L_PN9_MISC_CAPABILITY 152 -#define CCS_L_TEST_PATTERN_CAPABILITY 153 -#define CCS_L_PATTERN_SIZE_DIV_M1 154 -#define CCS_L_FIFO_SUPPORT_CAPABILITY 155 -#define CCS_L_PHY_CTRL_CAPABILITY 156 -#define CCS_L_CSI_DPHY_LANE_MODE_CAPABILITY 157 -#define CCS_L_CSI_SIGNALING_MODE_CAPABILITY 158 -#define CCS_L_FAST_STANDBY_CAPABILITY 159 -#define CCS_L_CSI_ADDRESS_CONTROL_CAPABILITY 160 -#define CCS_L_DATA_TYPE_CAPABILITY 161 -#define CCS_L_CSI_CPHY_LANE_MODE_CAPABILITY 162 -#define CCS_L_EMB_DATA_CAPABILITY 163 -#define CCS_L_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS 164 -#define CCS_L_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_OFFSET(n) ((n) * 4) -#define CCS_L_TEMP_SENSOR_CAPABILITY 165 -#define CCS_L_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS 166 -#define CCS_L_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_OFFSET(n) ((n) * 4) -#define CCS_L_DPHY_EQUALIZATION_CAPABILITY 167 -#define CCS_L_CPHY_EQUALIZATION_CAPABILITY 168 -#define CCS_L_DPHY_PREAMBLE_CAPABILITY 169 -#define CCS_L_DPHY_SSC_CAPABILITY 170 -#define CCS_L_CPHY_CALIBRATION_CAPABILITY 171 -#define CCS_L_DPHY_CALIBRATION_CAPABILITY 172 -#define CCS_L_PHY_CTRL_CAPABILITY_2 173 -#define CCS_L_LRTE_CPHY_CAPABILITY 174 -#define CCS_L_LRTE_DPHY_CAPABILITY 175 -#define CCS_L_ALPS_CAPABILITY_DPHY 176 -#define CCS_L_ALPS_CAPABILITY_CPHY 177 -#define CCS_L_SCRAMBLING_CAPABILITY 178 -#define CCS_L_DPHY_MANUAL_CONSTANT 179 -#define CCS_L_CPHY_MANUAL_CONSTANT 180 -#define CCS_L_CSI2_INTERFACE_CAPABILITY_MISC 181 -#define CCS_L_PHY_CTRL_CAPABILITY_3 182 -#define CCS_L_DPHY_SF 183 -#define CCS_L_CPHY_SF 184 -#define CCS_L_DPHY_LIMITS_1 185 -#define CCS_L_DPHY_LIMITS_2 186 -#define CCS_L_DPHY_LIMITS_3 187 -#define CCS_L_DPHY_LIMITS_4 188 -#define CCS_L_DPHY_LIMITS_5 189 -#define CCS_L_DPHY_LIMITS_6 190 -#define CCS_L_CPHY_LIMITS_1 191 -#define CCS_L_CPHY_LIMITS_2 192 -#define CCS_L_CPHY_LIMITS_3 193 -#define CCS_L_MIN_FRAME_LENGTH_LINES_BIN 194 -#define CCS_L_MAX_FRAME_LENGTH_LINES_BIN 195 -#define CCS_L_MIN_LINE_LENGTH_PCK_BIN 196 -#define CCS_L_MAX_LINE_LENGTH_PCK_BIN 197 -#define CCS_L_MIN_LINE_BLANKING_PCK_BIN 198 -#define CCS_L_FINE_INTEGRATION_TIME_MIN_BIN 199 -#define CCS_L_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN 200 -#define CCS_L_BINNING_CAPABILITY 201 -#define CCS_L_BINNING_WEIGHTING_CAPABILITY 202 -#define CCS_L_BINNING_SUB_TYPES 203 -#define CCS_L_BINNING_SUB_TYPE 204 -#define CCS_L_BINNING_SUB_TYPE_OFFSET(n) (n) -#define CCS_L_BINNING_WEIGHTING_MONO_CAPABILITY 205 -#define CCS_L_BINNING_SUB_TYPES_MONO 206 -#define CCS_L_BINNING_SUB_TYPE_MONO 207 -#define CCS_L_BINNING_SUB_TYPE_MONO_OFFSET(n) (n) -#define CCS_L_DATA_TRANSFER_IF_CAPABILITY 208 -#define CCS_L_SHADING_CORRECTION_CAPABILITY 209 -#define CCS_L_GREEN_IMBALANCE_CAPABILITY 210 -#define CCS_L_MODULE_SPECIFIC_CORRECTION_CAPABILITY 211 -#define CCS_L_DEFECT_CORRECTION_CAPABILITY 212 -#define CCS_L_DEFECT_CORRECTION_CAPABILITY_2 213 -#define CCS_L_NF_CAPABILITY 214 -#define CCS_L_OB_READOUT_CAPABILITY 215 -#define CCS_L_COLOR_FEEDBACK_CAPABILITY 216 -#define CCS_L_CFA_PATTERN_CAPABILITY 217 -#define CCS_L_CFA_PATTERN_CONVERSION_CAPABILITY 218 -#define CCS_L_FLASH_MODE_CAPABILITY 219 -#define CCS_L_SA_STROBE_MODE_CAPABILITY 220 -#define CCS_L_RESET_MAX_DELAY 221 -#define CCS_L_RESET_MIN_TIME 222 -#define CCS_L_PDAF_CAPABILITY_1 223 -#define CCS_L_PDAF_CAPABILITY_2 224 -#define CCS_L_BRACKETING_LUT_CAPABILITY_1 225 -#define CCS_L_BRACKETING_LUT_CAPABILITY_2 226 -#define CCS_L_BRACKETING_LUT_SIZE 227 -#define CCS_L_LAST 228 - -#endif /* __CCS_LIMITS_H__ */ diff --git a/drivers/media/i2c/smiapp/ccs-quirk.c b/drivers/media/i2c/smiapp/ccs-quirk.c deleted file mode 100644 index 6c48d0901952..000000000000 --- a/drivers/media/i2c/smiapp/ccs-quirk.c +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/media/i2c/smiapp/ccs-quirk.c - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#include - -#include "ccs.h" -#include "ccs-limits.h" - -static int ccs_write_addr_8s(struct ccs_sensor *sensor, - const struct ccs_reg_8 *regs, int len) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - - for (; len > 0; len--, regs++) { - rval = ccs_write_addr(sensor, regs->reg, regs->val); - if (rval < 0) { - dev_err(&client->dev, - "error %d writing reg 0x%4.4x, val 0x%2.2x", - rval, regs->reg, regs->val); - return rval; - } - } - - return 0; -} - -static int jt8ew9_limits(struct ccs_sensor *sensor) -{ - if (sensor->minfo.revision_number_major < 0x03) - sensor->frame_skip = 1; - - /* Below 24 gain doesn't have effect at all, */ - /* but ~59 is needed for full dynamic range */ - ccs_replace_limit(sensor, CCS_L_ANALOG_GAIN_CODE_MIN, 0, 59); - ccs_replace_limit(sensor, CCS_L_ANALOG_GAIN_CODE_MAX, 0, 6000); - - return 0; -} - -static int jt8ew9_post_poweron(struct ccs_sensor *sensor) -{ - static const struct ccs_reg_8 regs[] = { - { 0x30a3, 0xd8 }, /* Output port control : LVDS ports only */ - { 0x30ae, 0x00 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */ - { 0x30af, 0xd0 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */ - { 0x322d, 0x04 }, /* Adjusting Processing Image Size to Scaler Toshiba Recommendation Setting */ - { 0x3255, 0x0f }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ - { 0x3256, 0x15 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ - { 0x3258, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */ - { 0x3259, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */ - { 0x325f, 0x7c }, /* Analog Gain Control Toshiba Recommendation Setting */ - { 0x3302, 0x06 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ - { 0x3304, 0x00 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ - { 0x3307, 0x22 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ - { 0x3308, 0x8d }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */ - { 0x331e, 0x0f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x3320, 0x30 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x3321, 0x11 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x3322, 0x98 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x3323, 0x64 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x3325, 0x83 }, /* Read Out Timing Control Toshiba Recommendation Setting */ - { 0x3330, 0x18 }, /* Read Out Timing Control Toshiba Recommendation Setting */ - { 0x333c, 0x01 }, /* Read Out Timing Control Toshiba Recommendation Setting */ - { 0x3345, 0x2f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */ - { 0x33de, 0x38 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */ - /* Taken from v03. No idea what the rest are. */ - { 0x32e0, 0x05 }, - { 0x32e1, 0x05 }, - { 0x32e2, 0x04 }, - { 0x32e5, 0x04 }, - { 0x32e6, 0x04 }, - - }; - - return ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); -} - -const struct ccs_quirk smiapp_jt8ew9_quirk = { - .limits = jt8ew9_limits, - .post_poweron = jt8ew9_post_poweron, -}; - -static int imx125es_post_poweron(struct ccs_sensor *sensor) -{ - /* Taken from v02. No idea what the other two are. */ - static const struct ccs_reg_8 regs[] = { - /* - * 0x3302: clk during frame blanking: - * 0x00 - HS mode, 0x01 - LP11 - */ - { 0x3302, 0x01 }, - { 0x302d, 0x00 }, - { 0x3b08, 0x8c }, - }; - - return ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); -} - -const struct ccs_quirk smiapp_imx125es_quirk = { - .post_poweron = imx125es_post_poweron, -}; - -static int jt8ev1_limits(struct ccs_sensor *sensor) -{ - ccs_replace_limit(sensor, CCS_L_X_ADDR_MAX, 0, 4271); - ccs_replace_limit(sensor, CCS_L_MIN_LINE_BLANKING_PCK_BIN, 0, 184); - - return 0; -} - -static int jt8ev1_post_poweron(struct ccs_sensor *sensor) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - int rval; - static const struct ccs_reg_8 regs[] = { - { 0x3031, 0xcd }, /* For digital binning (EQ_MONI) */ - { 0x30a3, 0xd0 }, /* FLASH STROBE enable */ - { 0x3237, 0x00 }, /* For control of pulse timing for ADC */ - { 0x3238, 0x43 }, - { 0x3301, 0x06 }, /* For analog bias for sensor */ - { 0x3302, 0x06 }, - { 0x3304, 0x00 }, - { 0x3305, 0x88 }, - { 0x332a, 0x14 }, - { 0x332c, 0x6b }, - { 0x3336, 0x01 }, - { 0x333f, 0x1f }, - { 0x3355, 0x00 }, - { 0x3356, 0x20 }, - { 0x33bf, 0x20 }, /* Adjust the FBC speed */ - { 0x33c9, 0x20 }, - { 0x33ce, 0x30 }, /* Adjust the parameter for logic function */ - { 0x33cf, 0xec }, /* For Black sun */ - { 0x3328, 0x80 }, /* Ugh. No idea what's this. */ - }; - static const struct ccs_reg_8 regs_96[] = { - { 0x30ae, 0x00 }, /* For control of ADC clock */ - { 0x30af, 0xd0 }, - { 0x30b0, 0x01 }, - }; - - rval = ccs_write_addr_8s(sensor, regs, ARRAY_SIZE(regs)); - if (rval < 0) - return rval; - - switch (sensor->hwcfg->ext_clk) { - case 9600000: - return ccs_write_addr_8s(sensor, regs_96, - ARRAY_SIZE(regs_96)); - default: - dev_warn(&client->dev, "no MSRs for %d Hz ext_clk\n", - sensor->hwcfg->ext_clk); - return 0; - } -} - -static int jt8ev1_pre_streamon(struct ccs_sensor *sensor) -{ - return ccs_write_addr(sensor, 0x3328, 0x00); -} - -static int jt8ev1_post_streamoff(struct ccs_sensor *sensor) -{ - int rval; - - /* Workaround: allows fast standby to work properly */ - rval = ccs_write_addr(sensor, 0x3205, 0x04); - if (rval < 0) - return rval; - - /* Wait for 1 ms + one line => 2 ms is likely enough */ - usleep_range(2000, 2050); - - /* Restore it */ - rval = ccs_write_addr(sensor, 0x3205, 0x00); - if (rval < 0) - return rval; - - return ccs_write_addr(sensor, 0x3328, 0x80); -} - -static int jt8ev1_init(struct ccs_sensor *sensor) -{ - sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; - - return 0; -} - -const struct ccs_quirk smiapp_jt8ev1_quirk = { - .limits = jt8ev1_limits, - .post_poweron = jt8ev1_post_poweron, - .pre_streamon = jt8ev1_pre_streamon, - .post_streamoff = jt8ev1_post_streamoff, - .init = jt8ev1_init, -}; - -static int tcm8500md_limits(struct ccs_sensor *sensor) -{ - ccs_replace_limit(sensor, CCS_L_MIN_PLL_IP_CLK_FREQ_MHZ, 0, 2700000); - - return 0; -} - -const struct ccs_quirk smiapp_tcm8500md_quirk = { - .limits = tcm8500md_limits, -}; diff --git a/drivers/media/i2c/smiapp/ccs-quirk.h b/drivers/media/i2c/smiapp/ccs-quirk.h deleted file mode 100644 index d208379158f2..000000000000 --- a/drivers/media/i2c/smiapp/ccs-quirk.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * drivers/media/i2c/smiapp/ccs-quirk.h - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#ifndef __CCS_QUIRK__ -#define __CCS_QUIRK__ - -struct ccs_sensor; - -/** - * struct ccs_quirk - quirks for sensors that deviate from SMIA++ standard - * - * @limits: Replace sensor->limits with values which can't be read from - * sensor registers. Called the first time the sensor is powered up. - * @post_poweron: Called always after the sensor has been fully powered on. - * @pre_streamon: Called just before streaming is enabled. - * @post_streamon: Called right after stopping streaming. - * @pll_flags: Return flags for the PLL calculator. - * @init: Quirk initialisation, called the last in probe(). This is - * also appropriate for adding sensor specific controls, for instance. - * @reg_access: Register access quirk. The quirk may divert the access - * to another register, or no register at all. - * - * @write: Is this read (false) or write (true) access? - * @reg: Pointer to the register to access - * @value: Register value, set by the caller on write, or - * by the quirk on read - * - * @return: 0 on success, -ENOIOCTLCMD if no register - * access may be done by the caller (default read - * value is zero), else negative error code on error - */ -struct ccs_quirk { - int (*limits)(struct ccs_sensor *sensor); - int (*post_poweron)(struct ccs_sensor *sensor); - int (*pre_streamon)(struct ccs_sensor *sensor); - int (*post_streamoff)(struct ccs_sensor *sensor); - unsigned long (*pll_flags)(struct ccs_sensor *sensor); - int (*init)(struct ccs_sensor *sensor); - int (*reg_access)(struct ccs_sensor *sensor, bool write, u32 *reg, - u32 *val); - unsigned long flags; -}; - -#define CCS_QUIRK_FLAG_8BIT_READ_ONLY (1 << 0) - -struct ccs_reg_8 { - u16 reg; - u8 val; -}; - -#define CCS_MK_QUIRK_REG_8(_reg, _val) \ - { \ - .reg = (u16)_reg, \ - .val = _val, \ - } - -#define ccs_call_quirk(sensor, _quirk, ...) \ - ((sensor)->minfo.quirk && \ - (sensor)->minfo.quirk->_quirk ? \ - (sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0) - -#define ccs_needs_quirk(sensor, _quirk) \ - ((sensor)->minfo.quirk ? \ - (sensor)->minfo.quirk->flags & _quirk : 0) - -extern const struct ccs_quirk smiapp_jt8ev1_quirk; -extern const struct ccs_quirk smiapp_imx125es_quirk; -extern const struct ccs_quirk smiapp_jt8ew9_quirk; -extern const struct ccs_quirk smiapp_tcm8500md_quirk; - -#endif /* __CCS_QUIRK__ */ diff --git a/drivers/media/i2c/smiapp/ccs-reg-access.c b/drivers/media/i2c/smiapp/ccs-reg-access.c deleted file mode 100644 index 4e6d212473fc..000000000000 --- a/drivers/media/i2c/smiapp/ccs-reg-access.c +++ /dev/null @@ -1,265 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/media/i2c/smiapp/ccs-regs.c - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#include - -#include -#include - -#include "ccs.h" - -static uint32_t float_to_u32_mul_1000000(struct i2c_client *client, - uint32_t phloat) -{ - int32_t exp; - uint64_t man; - - if (phloat >= 0x80000000) { - dev_err(&client->dev, "this is a negative number\n"); - return 0; - } - - if (phloat == 0x7f800000) - return ~0; /* Inf. */ - - if ((phloat & 0x7f800000) == 0x7f800000) { - dev_err(&client->dev, "NaN or other special number\n"); - return 0; - } - - /* Valid cases begin here */ - if (phloat == 0) - return 0; /* Valid zero */ - - if (phloat > 0x4f800000) - return ~0; /* larger than 4294967295 */ - - /* - * Unbias exponent (note how phloat is now guaranteed to - * have 0 in the high bit) - */ - exp = ((int32_t)phloat >> 23) - 127; - - /* Extract mantissa, add missing '1' bit and it's in MHz */ - man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL; - - if (exp < 0) - man >>= -exp; - else - man <<= exp; - - man >>= 23; /* Remove mantissa bias */ - - return man & 0xffffffff; -} - - -/* - * Read a 8/16/32-bit i2c register. The value is returned in 'val'. - * Returns zero if successful, or non-zero otherwise. - */ -static int ____ccs_read_addr(struct ccs_sensor *sensor, u16 reg, u16 len, - u32 *val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct i2c_msg msg; - unsigned char data_buf[sizeof(u32)] = { 0 }; - unsigned char offset_buf[sizeof(u16)]; - int r; - - if (len > sizeof(data_buf)) - return -EINVAL; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = sizeof(offset_buf); - msg.buf = offset_buf; - put_unaligned_be16(reg, offset_buf); - - r = i2c_transfer(client->adapter, &msg, 1); - if (r != 1) { - if (r >= 0) - r = -EBUSY; - goto err; - } - - msg.len = len; - msg.flags = I2C_M_RD; - msg.buf = &data_buf[sizeof(data_buf) - len]; - - r = i2c_transfer(client->adapter, &msg, 1); - if (r != 1) { - if (r >= 0) - r = -EBUSY; - goto err; - } - - *val = get_unaligned_be32(data_buf); - - return 0; - -err: - dev_err(&client->dev, "read from offset 0x%x error %d\n", reg, r); - - return r; -} - -/* Read a register using 8-bit access only. */ -static int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg, - u16 len, u32 *val) -{ - unsigned int i; - int rval; - - *val = 0; - - for (i = 0; i < len; i++) { - u32 val8; - - rval = ____ccs_read_addr(sensor, reg + i, 1, &val8); - if (rval < 0) - return rval; - *val |= val8 << ((len - i - 1) << 3); - } - - return 0; -} - -unsigned int ccs_reg_width(u32 reg) -{ - if (reg & CCS_FL_16BIT) - return sizeof(uint16_t); - if (reg & CCS_FL_32BIT) - return sizeof(uint32_t); - - return sizeof(uint8_t); -} - -/* - * Read a 8/16/32-bit i2c register. The value is returned in 'val'. - * Returns zero if successful, or non-zero otherwise. - */ -static int __ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val, - bool only8) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - unsigned int len = ccs_reg_width(reg); - int rval; - - if (!only8) - rval = ____ccs_read_addr(sensor, CCS_REG_ADDR(reg), len, val); - else - rval = ____ccs_read_addr_8only(sensor, CCS_REG_ADDR(reg), len, - val); - if (rval < 0) - return rval; - - if (reg & CCS_FL_FLOAT_IREAL) - *val = float_to_u32_mul_1000000(client, *val); - - return 0; -} - -int ccs_read_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val) -{ - return __ccs_read_addr( - sensor, reg, val, - ccs_needs_quirk(sensor, CCS_QUIRK_FLAG_8BIT_READ_ONLY)); -} - -static int ccs_read_addr_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val, - bool force8) -{ - int rval; - - *val = 0; - rval = ccs_call_quirk(sensor, reg_access, false, ®, val); - if (rval == -ENOIOCTLCMD) - return 0; - if (rval < 0) - return rval; - - if (force8) - return __ccs_read_addr(sensor, reg, val, true); - - return ccs_read_addr_no_quirk(sensor, reg, val); -} - -int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val) -{ - return ccs_read_addr_quirk(sensor, reg, val, false); -} - -int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val) -{ - return ccs_read_addr_quirk(sensor, reg, val, true); -} - -int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val) -{ - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct i2c_msg msg; - unsigned char data[6]; - unsigned int retries; - unsigned int len = ccs_reg_width(reg); - int r; - - if (len > sizeof(data) - 2) - return -EINVAL; - - msg.addr = client->addr; - msg.flags = 0; /* Write */ - msg.len = 2 + len; - msg.buf = data; - - put_unaligned_be16(CCS_REG_ADDR(reg), data); - put_unaligned_be32(val << (8 * (sizeof(val) - len)), data + 2); - - for (retries = 0; retries < 5; retries++) { - /* - * Due to unknown reason sensor stops responding. This - * loop is a temporaty solution until the root cause - * is found. - */ - r = i2c_transfer(client->adapter, &msg, 1); - if (r == 1) { - if (retries) - dev_err(&client->dev, - "sensor i2c stall encountered. retries: %d\n", - retries); - return 0; - } - - usleep_range(2000, 2000); - } - - dev_err(&client->dev, - "wrote 0x%x to offset 0x%x error %d\n", val, - CCS_REG_ADDR(reg), r); - - return r; -} - -/* - * Write to a 8/16-bit register. - * Returns zero if successful, or non-zero otherwise. - */ -int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val) -{ - int rval; - - rval = ccs_call_quirk(sensor, reg_access, true, ®, &val); - if (rval == -ENOIOCTLCMD) - return 0; - if (rval < 0) - return rval; - - return ccs_write_addr_no_quirk(sensor, reg, val); -} diff --git a/drivers/media/i2c/smiapp/ccs-reg-access.h b/drivers/media/i2c/smiapp/ccs-reg-access.h deleted file mode 100644 index 76ac036a9538..000000000000 --- a/drivers/media/i2c/smiapp/ccs-reg-access.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * include/media/smiapp/ccs-regs.h - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#ifndef SMIAPP_REGS_H -#define SMIAPP_REGS_H - -#include -#include - -#include "ccs-regs.h" - -#define CCS_REG_ADDR(reg) ((u16)reg) - -struct ccs_sensor; - -int ccs_read_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 *val); -int ccs_read_addr(struct ccs_sensor *sensor, u32 reg, u32 *val); -int ccs_read_addr_8only(struct ccs_sensor *sensor, u32 reg, u32 *val); -int ccs_write_addr_no_quirk(struct ccs_sensor *sensor, u32 reg, u32 val); -int ccs_write_addr(struct ccs_sensor *sensor, u32 reg, u32 val); - -unsigned int ccs_reg_width(u32 reg); - -#define ccs_read(sensor, reg_name, val) \ - ccs_read_addr(sensor, CCS_R_##reg_name, val) - -#define ccs_write(sensor, reg_name, val) \ - ccs_write_addr(sensor, CCS_R_##reg_name, val) - -#endif diff --git a/drivers/media/i2c/smiapp/ccs-regs.h b/drivers/media/i2c/smiapp/ccs-regs.h deleted file mode 100644 index 4b3e5df2121f..000000000000 --- a/drivers/media/i2c/smiapp/ccs-regs.h +++ /dev/null @@ -1,954 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */ -/* Copyright (C) 2019--2020 Intel Corporation */ - -#ifndef __CCS_REGS_H__ -#define __CCS_REGS_H__ - -#include - -#define CCS_FL_BASE 16 -#define CCS_FL_16BIT BIT(CCS_FL_BASE) -#define CCS_FL_32BIT BIT(CCS_FL_BASE + 1) -#define CCS_FL_FLOAT_IREAL BIT(CCS_FL_BASE + 2) -#define CCS_FL_IREAL BIT(CCS_FL_BASE + 3) -#define CCS_R_ADDR(r) ((r) & 0xffff) - -#define CCS_R_MODULE_MODEL_ID (0x0000 | CCS_FL_16BIT) -#define CCS_R_MODULE_REVISION_NUMBER_MAJOR 0x0002 -#define CCS_R_FRAME_COUNT 0x0005 -#define CCS_R_PIXEL_ORDER 0x0006 -#define CCS_PIXEL_ORDER_GRBG 0U -#define CCS_PIXEL_ORDER_RGGB 1U -#define CCS_PIXEL_ORDER_BGGR 2U -#define CCS_PIXEL_ORDER_GBRG 3U -#define CCS_R_MIPI_CCS_VERSION 0x0007 -#define CCS_MIPI_CCS_VERSION_V1_0 0x10 -#define CCS_MIPI_CCS_VERSION_V1_1 0x11 -#define CCS_MIPI_CCS_VERSION_MAJOR_SHIFT 4U -#define CCS_MIPI_CCS_VERSION_MAJOR_MASK 0xf0 -#define CCS_MIPI_CCS_VERSION_MINOR_SHIFT 0U -#define CCS_MIPI_CCS_VERSION_MINOR_MASK 0xf -#define CCS_R_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT) -#define CCS_R_MODULE_MANUFACTURER_ID (0x000e | CCS_FL_16BIT) -#define CCS_R_MODULE_REVISION_NUMBER_MINOR 0x0010 -#define CCS_R_MODULE_DATE_YEAR 0x0012 -#define CCS_R_MODULE_DATE_MONTH 0x0013 -#define CCS_R_MODULE_DATE_DAY 0x0014 -#define CCS_R_MODULE_DATE_PHASE 0x0015 -#define CCS_MODULE_DATE_PHASE_SHIFT 0U -#define CCS_MODULE_DATE_PHASE_MASK 0x7 -#define CCS_MODULE_DATE_PHASE_TS 0U -#define CCS_MODULE_DATE_PHASE_ES 1U -#define CCS_MODULE_DATE_PHASE_CS 2U -#define CCS_MODULE_DATE_PHASE_MP 3U -#define CCS_R_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT) -#define CCS_R_SENSOR_REVISION_NUMBER 0x0018 -#define CCS_R_SENSOR_FIRMWARE_VERSION 0x001a -#define CCS_R_SERIAL_NUMBER (0x001c | CCS_FL_32BIT) -#define CCS_R_SENSOR_MANUFACTURER_ID (0x0020 | CCS_FL_16BIT) -#define CCS_R_SENSOR_REVISION_NUMBER_16 (0x0022 | CCS_FL_16BIT) -#define CCS_R_FRAME_FORMAT_MODEL_TYPE 0x0040 -#define CCS_FRAME_FORMAT_MODEL_TYPE_2_BYTE 1U -#define CCS_FRAME_FORMAT_MODEL_TYPE_4_BYTE 2U -#define CCS_R_FRAME_FORMAT_MODEL_SUBTYPE 0x0041 -#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U -#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf -#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U -#define CCS_FRAME_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0 -#define CCS_R_FRAME_FORMAT_DESCRIPTOR(n) ((0x0042 | CCS_FL_16BIT) + (n) * 2) -#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MIN_N 0U -#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_MAX_N 14U -#define CCS_R_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 | CCS_FL_32BIT) + (n) * 4) -#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_SHIFT 0U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PIXELS_MASK 0xfff -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_SHIFT 12U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MASK 0xf000 -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_EMBEDDED 1U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DUMMY_PIXEL 2U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_BLACK_PIXEL 3U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_DARK_PIXEL 4U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_VISIBLE_PIXEL 5U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_0 8U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_1 9U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_2 10U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_3 11U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_4 12U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_5 13U -#define CCS_FRAME_FORMAT_DESCRIPTOR_PCODE_MANUF_SPECIFIC_6 14U -#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_4_MIN_N 0U -#define CCS_LIM_FRAME_FORMAT_DESCRIPTOR_4_MAX_N 7U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_SHIFT 0U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PIXELS_MASK 0xffff -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_SHIFT 28U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MASK 0xf0000000 -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_EMBEDDED 1U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_DUMMY_PIXEL 2U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_BLACK_PIXEL 3U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_DARK_PIXEL 4U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_VISIBLE_PIXEL 5U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_0 8U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_1 9U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_2 10U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_3 11U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_4 12U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_5 13U -#define CCS_FRAME_FORMAT_DESCRIPTOR_4_PCODE_MANUF_SPECIFIC_6 14U -#define CCS_R_ANALOG_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT) -#define CCS_ANALOG_GAIN_CAPABILITY_GLOBAL 0U -#define CCS_ANALOG_GAIN_CAPABILITY_ALTERNATE_GLOBAL 2U -#define CCS_R_ANALOG_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_TYPE (0x008a | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_M0 (0x008c | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_C0 (0x008e | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_M1 (0x0090 | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_C1 (0x0092 | CCS_FL_16BIT) -#define CCS_R_ANALOG_LINEAR_GAIN_MIN (0x0094 | CCS_FL_16BIT) -#define CCS_R_ANALOG_LINEAR_GAIN_MAX (0x0096 | CCS_FL_16BIT) -#define CCS_R_ANALOG_LINEAR_GAIN_STEP_SIZE (0x0098 | CCS_FL_16BIT) -#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MIN (0x009a | CCS_FL_16BIT) -#define CCS_R_ANALOG_EXPONENTIAL_GAIN_MAX (0x009c | CCS_FL_16BIT) -#define CCS_R_ANALOG_EXPONENTIAL_GAIN_STEP_SIZE (0x009e | CCS_FL_16BIT) -#define CCS_R_DATA_FORMAT_MODEL_TYPE 0x00c0 -#define CCS_DATA_FORMAT_MODEL_TYPE_NORMAL 1U -#define CCS_DATA_FORMAT_MODEL_TYPE_EXTENDED 2U -#define CCS_R_DATA_FORMAT_MODEL_SUBTYPE 0x00c1 -#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_SHIFT 0U -#define CCS_DATA_FORMAT_MODEL_SUBTYPE_ROWS_MASK 0xf -#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_SHIFT 4U -#define CCS_DATA_FORMAT_MODEL_SUBTYPE_COLUMNS_MASK 0xf0 -#define CCS_R_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 | CCS_FL_16BIT) + (n) * 2) -#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MIN_N 0U -#define CCS_LIM_DATA_FORMAT_DESCRIPTOR_MAX_N 15U -#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_SHIFT 0U -#define CCS_DATA_FORMAT_DESCRIPTOR_COMPRESSED_MASK 0xff -#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_SHIFT 8U -#define CCS_DATA_FORMAT_DESCRIPTOR_UNCOMPRESSED_MASK 0xff00 -#define CCS_R_MODE_SELECT 0x0100 -#define CCS_MODE_SELECT_SOFTWARE_STANDBY 0U -#define CCS_MODE_SELECT_STREAMING 1U -#define CCS_R_IMAGE_ORIENTATION 0x0101 -#define CCS_IMAGE_ORIENTATION_HORIZONTAL_MIRROR BIT(0) -#define CCS_IMAGE_ORIENTATION_VERTICAL_FLIP BIT(1) -#define CCS_R_SOFTWARE_RESET 0x0103 -#define CCS_SOFTWARE_RESET_OFF 0U -#define CCS_SOFTWARE_RESET_ON 1U -#define CCS_R_GROUPED_PARAMETER_HOLD 0x0104 -#define CCS_R_MASK_CORRUPTED_FRAMES 0x0105 -#define CCS_MASK_CORRUPTED_FRAMES_ALLOW 0U -#define CCS_MASK_CORRUPTED_FRAMES_MASK 1U -#define CCS_R_FAST_STANDBY_CTRL 0x0106 -#define CCS_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0U -#define CCS_FAST_STANDBY_CTRL_FRAME_TRUNCATION 1U -#define CCS_R_CCI_ADDRESS_CTRL 0x0107 -#define CCS_R_2ND_CCI_IF_CTRL 0x0108 -#define CCS_2ND_CCI_IF_CTRL_ENABLE BIT(0) -#define CCS_2ND_CCI_IF_CTRL_ACK BIT(1) -#define CCS_R_2ND_CCI_ADDRESS_CTRL 0x0109 -#define CCS_R_CSI_CHANNEL_IDENTIFIER 0x0110 -#define CCS_R_CSI_SIGNALING_MODE 0x0111 -#define CCS_CSI_SIGNALING_MODE_CSI_2_DPHY 2U -#define CCS_CSI_SIGNALING_MODE_CSI_2_CPHY 3U -#define CCS_R_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT) -#define CCS_R_CSI_LANE_MODE 0x0114 -#define CCS_R_DPCM_FRAME_DT 0x011d -#define CCS_R_BOTTOM_EMBEDDED_DATA_DT 0x011e -#define CCS_R_BOTTOM_EMBEDDED_DATA_VC 0x011f -#define CCS_R_GAIN_MODE 0x0120 -#define CCS_GAIN_MODE_GLOBAL 0U -#define CCS_GAIN_MODE_ALTERNATE 1U -#define CCS_R_ADC_BIT_DEPTH 0x0121 -#define CCS_R_EMB_DATA_CTRL 0x0122 -#define CCS_EMB_DATA_CTRL_RAW8_PACKING_FOR_RAW16 BIT(0) -#define CCS_EMB_DATA_CTRL_RAW10_PACKING_FOR_RAW20 BIT(1) -#define CCS_EMB_DATA_CTRL_RAW12_PACKING_FOR_RAW24 BIT(2) -#define CCS_R_GPIO_TRIG_MODE 0x0130 -#define CCS_R_EXTCLK_FREQUENCY_MHZ (0x0136 | (CCS_FL_16BIT | CCS_FL_IREAL)) -#define CCS_R_TEMP_SENSOR_CTRL 0x0138 -#define CCS_TEMP_SENSOR_CTRL_ENABLE BIT(0) -#define CCS_R_TEMP_SENSOR_MODE 0x0139 -#define CCS_R_TEMP_SENSOR_OUTPUT 0x013a -#define CCS_R_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT) -#define CCS_R_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT) -#define CCS_R_ANALOG_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT) -#define CCS_R_ANALOG_LINEAR_GAIN_GLOBAL (0x0206 | CCS_FL_16BIT) -#define CCS_R_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0208 | CCS_FL_16BIT) -#define CCS_R_DIGITAL_GAIN_GLOBAL (0x020e | CCS_FL_16BIT) -#define CCS_R_SHORT_ANALOG_GAIN_GLOBAL (0x0216 | CCS_FL_16BIT) -#define CCS_R_SHORT_DIGITAL_GAIN_GLOBAL (0x0218 | CCS_FL_16BIT) -#define CCS_R_HDR_MODE 0x0220 -#define CCS_HDR_MODE_ENABLED BIT(0) -#define CCS_HDR_MODE_SEPARATE_ANALOG_GAIN BIT(1) -#define CCS_HDR_MODE_UPSCALING BIT(2) -#define CCS_HDR_MODE_RESET_SYNC BIT(3) -#define CCS_HDR_MODE_TIMING_MODE BIT(4) -#define CCS_HDR_MODE_EXPOSURE_CTRL_DIRECT BIT(5) -#define CCS_HDR_MODE_SEPARATE_DIGITAL_GAIN BIT(6) -#define CCS_R_HDR_RESOLUTION_REDUCTION 0x0221 -#define CCS_HDR_RESOLUTION_REDUCTION_ROW_SHIFT 0U -#define CCS_HDR_RESOLUTION_REDUCTION_ROW_MASK 0xf -#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_SHIFT 4U -#define CCS_HDR_RESOLUTION_REDUCTION_COLUMN_MASK 0xf0 -#define CCS_R_EXPOSURE_RATIO 0x0222 -#define CCS_R_HDR_INTERNAL_BIT_DEPTH 0x0223 -#define CCS_R_DIRECT_SHORT_INTEGRATION_TIME (0x0224 | CCS_FL_16BIT) -#define CCS_R_SHORT_ANALOG_LINEAR_GAIN_GLOBAL (0x0226 | CCS_FL_16BIT) -#define CCS_R_SHORT_ANALOG_EXPONENTIAL_GAIN_GLOBAL (0x0228 | CCS_FL_16BIT) -#define CCS_R_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT) -#define CCS_R_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT) -#define CCS_R_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT) -#define CCS_R_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT) -#define CCS_R_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT) -#define CCS_R_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT) -#define CCS_R_OP_PRE_PLL_CLK_DIV (0x030c | CCS_FL_16BIT) -#define CCS_R_OP_PLL_MULTIPLIER (0x031e | CCS_FL_16BIT) -#define CCS_R_PLL_MODE 0x0310 -#define CCS_PLL_MODE_SHIFT 0U -#define CCS_PLL_MODE_MASK 0x1 -#define CCS_PLL_MODE_SINGLE 0U -#define CCS_PLL_MODE_DUAL 1U -#define CCS_R_OP_PIX_CLK_DIV_REV (0x0312 | CCS_FL_16BIT) -#define CCS_R_OP_SYS_CLK_DIV_REV (0x0314 | CCS_FL_16BIT) -#define CCS_R_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT) -#define CCS_R_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT) -#define CCS_R_X_ADDR_START (0x0344 | CCS_FL_16BIT) -#define CCS_R_Y_ADDR_START (0x0346 | CCS_FL_16BIT) -#define CCS_R_X_ADDR_END (0x0348 | CCS_FL_16BIT) -#define CCS_R_Y_ADDR_END (0x034a | CCS_FL_16BIT) -#define CCS_R_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT) -#define CCS_R_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT) -#define CCS_R_FRAME_LENGTH_CTRL 0x0350 -#define CCS_FRAME_LENGTH_CTRL_AUTOMATIC BIT(0) -#define CCS_R_TIMING_MODE_CTRL 0x0352 -#define CCS_TIMING_MODE_CTRL_MANUAL_READOUT BIT(0) -#define CCS_TIMING_MODE_CTRL_DELAYED_EXPOSURE BIT(1) -#define CCS_R_START_READOUT_RS 0x0353 -#define CCS_START_READOUT_RS_MANUAL_READOUT_START BIT(0) -#define CCS_R_FRAME_MARGIN (0x0354 | CCS_FL_16BIT) -#define CCS_R_X_EVEN_INC (0x0380 | CCS_FL_16BIT) -#define CCS_R_X_ODD_INC (0x0382 | CCS_FL_16BIT) -#define CCS_R_Y_EVEN_INC (0x0384 | CCS_FL_16BIT) -#define CCS_R_Y_ODD_INC (0x0386 | CCS_FL_16BIT) -#define CCS_R_MONOCHROME_EN 0x0390 -#define CCS_MONOCHROME_EN_ENABLED 0U -#define CCS_R_SCALING_MODE (0x0400 | CCS_FL_16BIT) -#define CCS_SCALING_MODE_NO_SCALING 0U -#define CCS_SCALING_MODE_HORIZONTAL 1U -#define CCS_R_SCALE_M (0x0404 | CCS_FL_16BIT) -#define CCS_R_SCALE_N (0x0406 | CCS_FL_16BIT) -#define CCS_R_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT) -#define CCS_R_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT) -#define CCS_R_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT) -#define CCS_R_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT) -#define CCS_R_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT) -#define CCS_COMPRESSION_MODE_NONE 0U -#define CCS_COMPRESSION_MODE_DPCM_PCM_SIMPLE 1U -#define CCS_R_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT) -#define CCS_TEST_PATTERN_MODE_NONE 0U -#define CCS_TEST_PATTERN_MODE_SOLID_COLOR 1U -#define CCS_TEST_PATTERN_MODE_COLOR_BARS 2U -#define CCS_TEST_PATTERN_MODE_FADE_TO_GREY 3U -#define CCS_TEST_PATTERN_MODE_PN9 4U -#define CCS_TEST_PATTERN_MODE_COLOR_TILE 5U -#define CCS_R_TEST_DATA_RED (0x0602 | CCS_FL_16BIT) -#define CCS_R_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT) -#define CCS_R_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT) -#define CCS_R_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT) -#define CCS_R_VALUE_STEP_SIZE_SMOOTH 0x060a -#define CCS_R_VALUE_STEP_SIZE_QUANTISED 0x060b -#define CCS_R_TCLK_POST 0x0800 -#define CCS_R_THS_PREPARE 0x0801 -#define CCS_R_THS_ZERO_MIN 0x0802 -#define CCS_R_THS_TRAIL 0x0803 -#define CCS_R_TCLK_TRAIL_MIN 0x0804 -#define CCS_R_TCLK_PREPARE 0x0805 -#define CCS_R_TCLK_ZERO 0x0806 -#define CCS_R_TLPX 0x0807 -#define CCS_R_PHY_CTRL 0x0808 -#define CCS_PHY_CTRL_AUTO 0U -#define CCS_PHY_CTRL_UI 1U -#define CCS_PHY_CTRL_MANUAL 2U -#define CCS_R_TCLK_POST_EX (0x080a | CCS_FL_16BIT) -#define CCS_R_THS_PREPARE_EX (0x080c | CCS_FL_16BIT) -#define CCS_R_THS_ZERO_MIN_EX (0x080e | CCS_FL_16BIT) -#define CCS_R_THS_TRAIL_EX (0x0810 | CCS_FL_16BIT) -#define CCS_R_TCLK_TRAIL_MIN_EX (0x0812 | CCS_FL_16BIT) -#define CCS_R_TCLK_PREPARE_EX (0x0814 | CCS_FL_16BIT) -#define CCS_R_TCLK_ZERO_EX (0x0816 | CCS_FL_16BIT) -#define CCS_R_TLPX_EX (0x0818 | CCS_FL_16BIT) -#define CCS_R_REQUESTED_LINK_RATE (0x0820 | CCS_FL_32BIT) -#define CCS_R_DPHY_EQUALIZATION_MODE 0x0824 -#define CCS_DPHY_EQUALIZATION_MODE_EQ2 BIT(0) -#define CCS_R_PHY_EQUALIZATION_CTRL 0x0825 -#define CCS_PHY_EQUALIZATION_CTRL_ENABLE BIT(0) -#define CCS_R_DPHY_PREAMBLE_CTRL 0x0826 -#define CCS_DPHY_PREAMBLE_CTRL_ENABLE BIT(0) -#define CCS_R_DPHY_PREAMBLE_LENGTH 0x0826 -#define CCS_R_PHY_SSC_CTRL 0x0828 -#define CCS_PHY_SSC_CTRL_ENABLE BIT(0) -#define CCS_R_MANUAL_LP_CTRL 0x0829 -#define CCS_MANUAL_LP_CTRL_ENABLE BIT(0) -#define CCS_R_TWAKEUP 0x082a -#define CCS_R_TINIT 0x082b -#define CCS_R_THS_EXIT 0x082c -#define CCS_R_THS_EXIT_EX (0x082e | CCS_FL_16BIT) -#define CCS_R_PHY_PERIODIC_CALIBRATION_CTRL 0x0830 -#define CCS_PHY_PERIODIC_CALIBRATION_CTRL_FRAME_BLANKING BIT(0) -#define CCS_R_PHY_PERIODIC_CALIBRATION_INTERVAL 0x0831 -#define CCS_R_PHY_INIT_CALIBRATION_CTRL 0x0832 -#define CCS_PHY_INIT_CALIBRATION_CTRL_STREAM_START BIT(0) -#define CCS_R_DPHY_CALIBRATION_MODE 0x0833 -#define CCS_DPHY_CALIBRATION_MODE_ALSO_ALTERNATE BIT(0) -#define CCS_R_CPHY_CALIBRATION_MODE 0x0834 -#define CCS_CPHY_CALIBRATION_MODE_FORMAT_1 0U -#define CCS_CPHY_CALIBRATION_MODE_FORMAT_2 1U -#define CCS_CPHY_CALIBRATION_MODE_FORMAT_3 2U -#define CCS_R_T3_CALPREAMBLE_LENGTH 0x0835 -#define CCS_R_T3_CALPREAMBLE_LENGTH_PER 0x0836 -#define CCS_R_T3_CALALTSEQ_LENGTH 0x0837 -#define CCS_R_T3_CALALTSEQ_LENGTH_PER 0x0838 -#define CCS_R_FM2_INIT_SEED (0x083a | CCS_FL_16BIT) -#define CCS_R_T3_CALUDEFSEQ_LENGTH (0x083c | CCS_FL_16BIT) -#define CCS_R_T3_CALUDEFSEQ_LENGTH_PER (0x083e | CCS_FL_16BIT) -#define CCS_R_TGR_PREAMBLE_LENGTH 0x0841 -#define CCS_TGR_PREAMBLE_LENGTH_PREAMABLE_PROG_SEQ BIT(7) -#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_SHIFT 0U -#define CCS_TGR_PREAMBLE_LENGTH_BEGIN_PREAMBLE_LENGTH_MASK 0x3f -#define CCS_R_TGR_POST_LENGTH 0x0842 -#define CCS_TGR_POST_LENGTH_POST_LENGTH_SHIFT 0U -#define CCS_TGR_POST_LENGTH_POST_LENGTH_MASK 0x1f -#define CCS_R_TGR_PREAMBLE_PROG_SEQUENCE(n2) (0x0843 + (n2)) -#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MIN_N2 0U -#define CCS_LIM_TGR_PREAMBLE_PROG_SEQUENCE_MAX_N2 6U -#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_SHIFT 3U -#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_1_MASK 0x38 -#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_SHIFT 0U -#define CCS_TGR_PREAMBLE_PROG_SEQUENCE_SYMBOL_N_MASK 0x7 -#define CCS_R_T3_PREPARE (0x084e | CCS_FL_16BIT) -#define CCS_R_T3_LPX (0x0850 | CCS_FL_16BIT) -#define CCS_R_ALPS_CTRL 0x085a -#define CCS_ALPS_CTRL_LVLP_DPHY BIT(0) -#define CCS_ALPS_CTRL_LVLP_CPHY BIT(1) -#define CCS_ALPS_CTRL_ALP_CPHY BIT(2) -#define CCS_R_TX_REG_CSI_EPD_EN_SSP_CPHY (0x0860 | CCS_FL_16BIT) -#define CCS_R_TX_REG_CSI_EPD_OP_SLP_CPHY (0x0862 | CCS_FL_16BIT) -#define CCS_R_TX_REG_CSI_EPD_EN_SSP_DPHY (0x0864 | CCS_FL_16BIT) -#define CCS_R_TX_REG_CSI_EPD_OP_SLP_DPHY (0x0866 | CCS_FL_16BIT) -#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_CPHY 0x0868 -#define CCS_R_TX_REG_CSI_EPD_MISC_OPTION_DPHY 0x0869 -#define CCS_R_SCRAMBLING_CTRL 0x0870 -#define CCS_SCRAMBLING_CTRL_ENABLED BIT(0) -#define CCS_SCRAMBLING_CTRL_SHIFT 2U -#define CCS_SCRAMBLING_CTRL_MASK 0xc -#define CCS_SCRAMBLING_CTRL_1_SEED_CPHY 0U -#define CCS_SCRAMBLING_CTRL_4_SEED_CPHY 3U -#define CCS_R_LANE_SEED_VALUE(seed, lane) ((0x0872 | CCS_FL_16BIT) + (seed) * 16 + (lane) * 2) -#define CCS_LIM_LANE_SEED_VALUE_MIN_SEED 0U -#define CCS_LIM_LANE_SEED_VALUE_MAX_SEED 3U -#define CCS_LIM_LANE_SEED_VALUE_MIN_LANE 0U -#define CCS_LIM_LANE_SEED_VALUE_MAX_LANE 7U -#define CCS_R_TX_USL_REV_ENTRY (0x08c0 | CCS_FL_16BIT) -#define CCS_R_TX_USL_REV_CLOCK_COUNTER (0x08c2 | CCS_FL_16BIT) -#define CCS_R_TX_USL_REV_LP_COUNTER (0x08c4 | CCS_FL_16BIT) -#define CCS_R_TX_USL_REV_FRAME_COUNTER (0x08c6 | CCS_FL_16BIT) -#define CCS_R_TX_USL_REV_CHRONOLOGICAL_TIMER (0x08c8 | CCS_FL_16BIT) -#define CCS_R_TX_USL_FWD_ENTRY (0x08ca | CCS_FL_16BIT) -#define CCS_R_TX_USL_GPIO (0x08cc | CCS_FL_16BIT) -#define CCS_R_TX_USL_OPERATION (0x08ce | CCS_FL_16BIT) -#define CCS_TX_USL_OPERATION_RESET BIT(0) -#define CCS_R_TX_USL_ALP_CTRL (0x08d0 | CCS_FL_16BIT) -#define CCS_TX_USL_ALP_CTRL_CLOCK_PAUSE BIT(0) -#define CCS_R_TX_USL_APP_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT) -#define CCS_R_TX_USL_SNS_BTA_ACK_TIMEOUT (0x08d2 | CCS_FL_16BIT) -#define CCS_R_USL_CLOCK_MODE_D_CTRL 0x08d2 -#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_STANDBY BIT(0) -#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_VBLANK BIT(1) -#define CCS_USL_CLOCK_MODE_D_CTRL_CONT_CLOCK_HBLANK BIT(2) -#define CCS_R_BINNING_MODE 0x0900 -#define CCS_R_BINNING_TYPE 0x0901 -#define CCS_R_BINNING_WEIGHTING 0x0902 -#define CCS_R_DATA_TRANSFER_IF_1_CTRL 0x0a00 -#define CCS_DATA_TRANSFER_IF_1_CTRL_ENABLE BIT(0) -#define CCS_DATA_TRANSFER_IF_1_CTRL_WRITE BIT(1) -#define CCS_DATA_TRANSFER_IF_1_CTRL_CLEAR_ERROR BIT(2) -#define CCS_R_DATA_TRANSFER_IF_1_STATUS 0x0a01 -#define CCS_DATA_TRANSFER_IF_1_STATUS_READ_IF_READY BIT(0) -#define CCS_DATA_TRANSFER_IF_1_STATUS_WRITE_IF_READY BIT(1) -#define CCS_DATA_TRANSFER_IF_1_STATUS_DATA_CORRUPTED BIT(2) -#define CCS_DATA_TRANSFER_IF_1_STATUS_IMPROPER_IF_USAGE BIT(3) -#define CCS_R_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02 -#define CCS_R_DATA_TRANSFER_IF_1_DATA(p) (0x0a04 + (p)) -#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MIN_P 0U -#define CCS_LIM_DATA_TRANSFER_IF_1_DATA_MAX_P 63U -#define CCS_R_SHADING_CORRECTION_EN 0x0b00 -#define CCS_SHADING_CORRECTION_EN_ENABLE BIT(0) -#define CCS_R_LUMINANCE_CORRECTION_LEVEL 0x0b01 -#define CCS_R_GREEN_IMBALANCE_FILTER_EN 0x0b02 -#define CCS_GREEN_IMBALANCE_FILTER_EN_ENABLE BIT(0) -#define CCS_R_MAPPED_DEFECT_CORRECT_EN 0x0b05 -#define CCS_MAPPED_DEFECT_CORRECT_EN_ENABLE BIT(0) -#define CCS_R_SINGLE_DEFECT_CORRECT_EN 0x0b06 -#define CCS_SINGLE_DEFECT_CORRECT_EN_ENABLE BIT(0) -#define CCS_R_DYNAMIC_COUPLET_CORRECT_EN 0x0b08 -#define CCS_DYNAMIC_COUPLET_CORRECT_EN_ENABLE BIT(0) -#define CCS_R_COMBINED_DEFECT_CORRECT_EN 0x0b0a -#define CCS_COMBINED_DEFECT_CORRECT_EN_ENABLE BIT(0) -#define CCS_R_MODULE_SPECIFIC_CORRECTION_EN 0x0b0c -#define CCS_MODULE_SPECIFIC_CORRECTION_EN_ENABLE BIT(0) -#define CCS_R_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN 0x0b13 -#define CCS_DYNAMIC_TRIPLET_DEFECT_CORRECT_EN_ENABLE BIT(0) -#define CCS_R_NF_CTRL 0x0b15 -#define CCS_NF_CTRL_LUMA BIT(0) -#define CCS_NF_CTRL_CHROMA BIT(1) -#define CCS_NF_CTRL_COMBINED BIT(2) -#define CCS_R_OB_READOUT_CONTROL 0x0b30 -#define CCS_OB_READOUT_CONTROL_ENABLE BIT(0) -#define CCS_OB_READOUT_CONTROL_INTERLEAVING BIT(1) -#define CCS_R_OB_VIRTUAL_CHANNEL 0x0b31 -#define CCS_R_OB_DT 0x0b32 -#define CCS_R_OB_DATA_FORMAT 0x0b33 -#define CCS_R_COLOR_TEMPERATURE (0x0b8c | CCS_FL_16BIT) -#define CCS_R_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT) -#define CCS_R_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT) -#define CCS_R_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT) -#define CCS_R_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT) -#define CCS_R_CFA_CONVERSION_CTRL 0x0ba0 -#define CCS_CFA_CONVERSION_CTRL_BAYER_CONVERSION_ENABLE BIT(0) -#define CCS_R_FLASH_STROBE_ADJUSTMENT 0x0c12 -#define CCS_R_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT) -#define CCS_R_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT) -#define CCS_R_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT) -#define CCS_R_FLASH_MODE_RS 0x0c1a -#define CCS_FLASH_MODE_RS_CONTINUOUS BIT(0) -#define CCS_FLASH_MODE_RS_TRUNCATE BIT(1) -#define CCS_FLASH_MODE_RS_ASYNC BIT(3) -#define CCS_R_FLASH_TRIGGER_RS 0x0c1b -#define CCS_R_FLASH_STATUS 0x0c1c -#define CCS_FLASH_STATUS_RETIMED BIT(0) -#define CCS_R_SA_STROBE_MODE 0x0c1d -#define CCS_SA_STROBE_MODE_CONTINUOUS BIT(0) -#define CCS_SA_STROBE_MODE_TRUNCATE BIT(1) -#define CCS_SA_STROBE_MODE_ASYNC BIT(3) -#define CCS_SA_STROBE_MODE_ADJUST_EDGE BIT(4) -#define CCS_R_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT) -#define CCS_R_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT) -#define CCS_R_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT) -#define CCS_R_SA_STROBE_TRIGGER 0x0c24 -#define CCS_R_SA_STROBE_STATUS 0x0c25 -#define CCS_SA_STROBE_STATUS_RETIMED BIT(0) -#define CCS_R_TSA_STROBE_RE_DELAY_CTRL (0x0c30 | CCS_FL_16BIT) -#define CCS_R_TSA_STROBE_FE_DELAY_CTRL (0x0c32 | CCS_FL_16BIT) -#define CCS_R_PDAF_CTRL (0x0d00 | CCS_FL_16BIT) -#define CCS_PDAF_CTRL_ENABLE BIT(0) -#define CCS_PDAF_CTRL_PROCESSED BIT(1) -#define CCS_PDAF_CTRL_INTERLEAVED BIT(2) -#define CCS_PDAF_CTRL_VISIBLE_PDAF_CORRECTION BIT(3) -#define CCS_R_PDAF_VC 0x0d02 -#define CCS_R_PDAF_DT 0x0d03 -#define CCS_R_PD_X_ADDR_START (0x0d04 | CCS_FL_16BIT) -#define CCS_R_PD_Y_ADDR_START (0x0d06 | CCS_FL_16BIT) -#define CCS_R_PD_X_ADDR_END (0x0d08 | CCS_FL_16BIT) -#define CCS_R_PD_Y_ADDR_END (0x0d0a | CCS_FL_16BIT) -#define CCS_R_BRACKETING_LUT_CTRL 0x0e00 -#define CCS_R_BRACKETING_LUT_MODE 0x0e01 -#define CCS_BRACKETING_LUT_MODE_CONTINUE_STREAMING BIT(0) -#define CCS_BRACKETING_LUT_MODE_LOOP_MODE BIT(1) -#define CCS_R_BRACKETING_LUT_ENTRY_CTRL 0x0e02 -#define CCS_R_BRACKETING_LUT_FRAME(n) (0x0e10 + (n)) -#define CCS_LIM_BRACKETING_LUT_FRAME_MIN_N 0U -#define CCS_LIM_BRACKETING_LUT_FRAME_MAX_N 239U -#define CCS_R_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT) -#define CCS_INTEGRATION_TIME_CAPABILITY_FINE BIT(0) -#define CCS_R_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT) -#define CCS_R_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT) -#define CCS_R_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT) -#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT) -#define CCS_R_DIGITAL_GAIN_CAPABILITY 0x1081 -#define CCS_DIGITAL_GAIN_CAPABILITY_NONE 0U -#define CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL 2U -#define CCS_R_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT) -#define CCS_R_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT) -#define CCS_R_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT) -#define CCS_R_PEDESTAL_CAPABILITY 0x10e0 -#define CCS_R_ADC_CAPABILITY 0x10f0 -#define CCS_ADC_CAPABILITY_BIT_DEPTH_CTRL BIT(0) -#define CCS_R_ADC_BIT_DEPTH_CAPABILITY (0x10f4 | CCS_FL_32BIT) -#define CCS_R_MIN_EXT_CLK_FREQ_MHZ (0x1100 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_EXT_CLK_FREQ_MHZ (0x1104 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT) -#define CCS_R_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT) -#define CCS_R_MIN_PLL_IP_CLK_FREQ_MHZ (0x110c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_PLL_IP_CLK_FREQ_MHZ (0x1110 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT) -#define CCS_R_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT) -#define CCS_R_MIN_PLL_OP_CLK_FREQ_MHZ (0x1118 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_PLL_OP_CLK_FREQ_MHZ (0x111c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT) -#define CCS_R_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT) -#define CCS_R_MIN_VT_SYS_CLK_FREQ_MHZ (0x1124 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_VT_SYS_CLK_FREQ_MHZ (0x1128 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_VT_PIX_CLK_FREQ_MHZ (0x112c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_VT_PIX_CLK_FREQ_MHZ (0x1130 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT) -#define CCS_R_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT) -#define CCS_R_CLOCK_CALCULATION 0x1138 -#define CCS_CLOCK_CALCULATION_LANE_SPEED BIT(0) -#define CCS_CLOCK_CALCULATION_LINK_DECOUPLED BIT(1) -#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_SYS_DDR BIT(2) -#define CCS_CLOCK_CALCULATION_DUAL_PLL_OP_PIX_DDR BIT(3) -#define CCS_R_NUM_OF_VT_LANES 0x1139 -#define CCS_R_NUM_OF_OP_LANES 0x113a -#define CCS_R_OP_BITS_PER_LANE 0x113b -#define CCS_R_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT) -#define CCS_R_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT) -#define CCS_R_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT) -#define CCS_R_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT) -#define CCS_R_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT) -#define CCS_R_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT) -#define CCS_R_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c -#define CCS_R_TIMING_MODE_CAPABILITY 0x114d -#define CCS_TIMING_MODE_CAPABILITY_AUTO_FRAME_LENGTH BIT(0) -#define CCS_TIMING_MODE_CAPABILITY_ROLLING_SHUTTER_MANUAL_READOUT BIT(2) -#define CCS_TIMING_MODE_CAPABILITY_DELAYED_EXPOSURE_START BIT(3) -#define CCS_TIMING_MODE_CAPABILITY_MANUAL_EXPOSURE_EMBEDDED_DATA BIT(4) -#define CCS_R_FRAME_MARGIN_MAX_VALUE (0x114e | CCS_FL_16BIT) -#define CCS_R_FRAME_MARGIN_MIN_VALUE 0x1150 -#define CCS_R_GAIN_DELAY_TYPE 0x1151 -#define CCS_GAIN_DELAY_TYPE_FIXED 0U -#define CCS_GAIN_DELAY_TYPE_VARIABLE 1U -#define CCS_R_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT) -#define CCS_R_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT) -#define CCS_R_MIN_OP_SYS_CLK_FREQ_MHZ (0x1164 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_SYS_CLK_FREQ_MHZ (0x1168 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT) -#define CCS_R_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT) -#define CCS_R_MIN_OP_PIX_CLK_FREQ_MHZ (0x1170 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_PIX_CLK_FREQ_MHZ (0x1174 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_X_ADDR_MIN (0x1180 | CCS_FL_16BIT) -#define CCS_R_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT) -#define CCS_R_X_ADDR_MAX (0x1184 | CCS_FL_16BIT) -#define CCS_R_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT) -#define CCS_R_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT) -#define CCS_R_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT) -#define CCS_R_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT) -#define CCS_R_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT) -#define CCS_R_X_ADDR_START_DIV_CONSTANT 0x1190 -#define CCS_R_Y_ADDR_START_DIV_CONSTANT 0x1191 -#define CCS_R_X_ADDR_END_DIV_CONSTANT 0x1192 -#define CCS_R_Y_ADDR_END_DIV_CONSTANT 0x1193 -#define CCS_R_X_SIZE_DIV 0x1194 -#define CCS_R_Y_SIZE_DIV 0x1195 -#define CCS_R_X_OUTPUT_DIV 0x1196 -#define CCS_R_Y_OUTPUT_DIV 0x1197 -#define CCS_R_NON_FLEXIBLE_RESOLUTION_SUPPORT 0x1198 -#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_PIX_ADDR BIT(0) -#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_NEW_OUTPUT_RES BIT(1) -#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_CROP_NO_PAD BIT(2) -#define CCS_NON_FLEXIBLE_RESOLUTION_SUPPORT_OUTPUT_SIZE_LANE_DEP BIT(3) -#define CCS_R_MIN_OP_PRE_PLL_CLK_DIV (0x11a0 | CCS_FL_16BIT) -#define CCS_R_MAX_OP_PRE_PLL_CLK_DIV (0x11a2 | CCS_FL_16BIT) -#define CCS_R_MIN_OP_PLL_IP_CLK_FREQ_MHZ (0x11a4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_PLL_IP_CLK_FREQ_MHZ (0x11a8 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_OP_PLL_MULTIPLIER (0x11ac | CCS_FL_16BIT) -#define CCS_R_MAX_OP_PLL_MULTIPLIER (0x11ae | CCS_FL_16BIT) -#define CCS_R_MIN_OP_PLL_OP_CLK_FREQ_MHZ (0x11b0 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_PLL_OP_CLK_FREQ_MHZ (0x11b4 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_CLOCK_TREE_PLL_CAPABILITY 0x11b8 -#define CCS_CLOCK_TREE_PLL_CAPABILITY_DUAL_PLL BIT(0) -#define CCS_CLOCK_TREE_PLL_CAPABILITY_SINGLE_PLL BIT(1) -#define CCS_CLOCK_TREE_PLL_CAPABILITY_EXT_DIVIDER BIT(2) -#define CCS_CLOCK_TREE_PLL_CAPABILITY_FLEXIBLE_OP_PIX_CLK_DIV BIT(3) -#define CCS_R_CLOCK_CAPA_TYPE_CAPABILITY 0x11b9 -#define CCS_CLOCK_CAPA_TYPE_CAPABILITY_IREAL BIT(0) -#define CCS_R_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT) -#define CCS_R_MIN_ODD_INC (0x11c2 | CCS_FL_16BIT) -#define CCS_R_MAX_EVEN_INC (0x11c4 | CCS_FL_16BIT) -#define CCS_R_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT) -#define CCS_R_AUX_SUBSAMP_CAPABILITY 0x11c8 -#define CCS_AUX_SUBSAMP_CAPABILITY_FACTOR_POWER_OF_2 BIT(1) -#define CCS_R_AUX_SUBSAMP_MONO_CAPABILITY 0x11c9 -#define CCS_AUX_SUBSAMP_MONO_CAPABILITY_FACTOR_POWER_OF_2 BIT(1) -#define CCS_R_MONOCHROME_CAPABILITY 0x11ca -#define CCS_MONOCHROME_CAPABILITY_INC_ODD 0U -#define CCS_MONOCHROME_CAPABILITY_INC_EVEN 1U -#define CCS_R_PIXEL_READOUT_CAPABILITY 0x11cb -#define CCS_PIXEL_READOUT_CAPABILITY_BAYER 0U -#define CCS_PIXEL_READOUT_CAPABILITY_MONOCHROME 1U -#define CCS_PIXEL_READOUT_CAPABILITY_BAYER_AND_MONO 2U -#define CCS_R_MIN_EVEN_INC_MONO (0x11cc | CCS_FL_16BIT) -#define CCS_R_MAX_EVEN_INC_MONO (0x11ce | CCS_FL_16BIT) -#define CCS_R_MIN_ODD_INC_MONO (0x11d0 | CCS_FL_16BIT) -#define CCS_R_MAX_ODD_INC_MONO (0x11d2 | CCS_FL_16BIT) -#define CCS_R_MIN_EVEN_INC_BC2 (0x11d4 | CCS_FL_16BIT) -#define CCS_R_MAX_EVEN_INC_BC2 (0x11d6 | CCS_FL_16BIT) -#define CCS_R_MIN_ODD_INC_BC2 (0x11d8 | CCS_FL_16BIT) -#define CCS_R_MAX_ODD_INC_BC2 (0x11da | CCS_FL_16BIT) -#define CCS_R_MIN_EVEN_INC_MONO_BC2 (0x11dc | CCS_FL_16BIT) -#define CCS_R_MAX_EVEN_INC_MONO_BC2 (0x11de | CCS_FL_16BIT) -#define CCS_R_MIN_ODD_INC_MONO_BC2 (0x11f0 | CCS_FL_16BIT) -#define CCS_R_MAX_ODD_INC_MONO_BC2 (0x11f2 | CCS_FL_16BIT) -#define CCS_R_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT) -#define CCS_SCALING_CAPABILITY_NONE 0U -#define CCS_SCALING_CAPABILITY_HORIZONTAL 1U -#define CCS_SCALING_CAPABILITY_RESERVED 2U -#define CCS_R_SCALER_M_MIN (0x1204 | CCS_FL_16BIT) -#define CCS_R_SCALER_M_MAX (0x1206 | CCS_FL_16BIT) -#define CCS_R_SCALER_N_MIN (0x1208 | CCS_FL_16BIT) -#define CCS_R_SCALER_N_MAX (0x120a | CCS_FL_16BIT) -#define CCS_R_DIGITAL_CROP_CAPABILITY 0x120e -#define CCS_DIGITAL_CROP_CAPABILITY_NONE 0U -#define CCS_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1U -#define CCS_R_HDR_CAPABILITY_1 0x1210 -#define CCS_HDR_CAPABILITY_1_2X2_BINNING BIT(0) -#define CCS_HDR_CAPABILITY_1_COMBINED_ANALOG_GAIN BIT(1) -#define CCS_HDR_CAPABILITY_1_SEPARATE_ANALOG_GAIN BIT(2) -#define CCS_HDR_CAPABILITY_1_UPSCALING BIT(3) -#define CCS_HDR_CAPABILITY_1_RESET_SYNC BIT(4) -#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_TIMING BIT(5) -#define CCS_HDR_CAPABILITY_1_DIRECT_SHORT_EXP_SYNTHESIS BIT(6) -#define CCS_R_MIN_HDR_BIT_DEPTH 0x1211 -#define CCS_R_HDR_RESOLUTION_SUB_TYPES 0x1212 -#define CCS_R_HDR_RESOLUTION_SUB_TYPE(n) (0x1213 + (n)) -#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MIN_N 0U -#define CCS_LIM_HDR_RESOLUTION_SUB_TYPE_MAX_N 1U -#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_SHIFT 0U -#define CCS_HDR_RESOLUTION_SUB_TYPE_ROW_MASK 0xf -#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_SHIFT 4U -#define CCS_HDR_RESOLUTION_SUB_TYPE_COLUMN_MASK 0xf0 -#define CCS_R_HDR_CAPABILITY_2 0x121b -#define CCS_HDR_CAPABILITY_2_COMBINED_DIGITAL_GAIN BIT(0) -#define CCS_HDR_CAPABILITY_2_SEPARATE_DIGITAL_GAIN BIT(1) -#define CCS_HDR_CAPABILITY_2_TIMING_MODE BIT(3) -#define CCS_HDR_CAPABILITY_2_SYNTHESIS_MODE BIT(4) -#define CCS_R_MAX_HDR_BIT_DEPTH 0x121c -#define CCS_R_USL_SUPPORT_CAPABILITY 0x1230 -#define CCS_USL_SUPPORT_CAPABILITY_CLOCK_TREE BIT(0) -#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_TREE BIT(1) -#define CCS_USL_SUPPORT_CAPABILITY_REV_CLOCK_CALC BIT(2) -#define CCS_R_USL_CLOCK_MODE_D_CAPABILITY 0x1231 -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_STANDBY BIT(0) -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_VBLANK BIT(1) -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_CONT_CLOCK_HBLANK BIT(2) -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_STANDBY BIT(3) -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_VBLANK BIT(4) -#define CCS_USL_CLOCK_MODE_D_CAPABILITY_NONCONT_CLOCK_HBLANK BIT(5) -#define CCS_R_MIN_OP_SYS_CLK_DIV_REV 0x1234 -#define CCS_R_MAX_OP_SYS_CLK_DIV_REV 0x1236 -#define CCS_R_MIN_OP_PIX_CLK_DIV_REV 0x1238 -#define CCS_R_MAX_OP_PIX_CLK_DIV_REV 0x123a -#define CCS_R_MIN_OP_SYS_CLK_FREQ_REV_MHZ (0x123c | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_SYS_CLK_FREQ_REV_MHZ (0x1240 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MIN_OP_PIX_CLK_FREQ_REV_MHZ (0x1244 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_OP_PIX_CLK_FREQ_REV_MHZ (0x1248 | (CCS_FL_32BIT | CCS_FL_FLOAT_IREAL)) -#define CCS_R_MAX_BITRATE_REV_D_MODE_MBPS (0x124c | (CCS_FL_32BIT | CCS_FL_IREAL)) -#define CCS_R_MAX_SYMRATE_REV_C_MODE_MSPS (0x1250 | (CCS_FL_32BIT | CCS_FL_IREAL)) -#define CCS_R_COMPRESSION_CAPABILITY 0x1300 -#define CCS_COMPRESSION_CAPABILITY_DPCM_PCM_SIMPLE BIT(0) -#define CCS_R_TEST_MODE_CAPABILITY (0x1310 | CCS_FL_16BIT) -#define CCS_TEST_MODE_CAPABILITY_SOLID_COLOR BIT(0) -#define CCS_TEST_MODE_CAPABILITY_COLOR_BARS BIT(1) -#define CCS_TEST_MODE_CAPABILITY_FADE_TO_GREY BIT(2) -#define CCS_TEST_MODE_CAPABILITY_PN9 BIT(3) -#define CCS_TEST_MODE_CAPABILITY_COLOR_TILE BIT(5) -#define CCS_R_PN9_DATA_FORMAT1 0x1312 -#define CCS_R_PN9_DATA_FORMAT2 0x1313 -#define CCS_R_PN9_DATA_FORMAT3 0x1314 -#define CCS_R_PN9_DATA_FORMAT4 0x1315 -#define CCS_R_PN9_MISC_CAPABILITY 0x1316 -#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_SHIFT 0U -#define CCS_PN9_MISC_CAPABILITY_NUM_PIXELS_MASK 0x7 -#define CCS_PN9_MISC_CAPABILITY_COMPRESSION BIT(3) -#define CCS_R_TEST_PATTERN_CAPABILITY 0x1317 -#define CCS_TEST_PATTERN_CAPABILITY_NO_REPEAT BIT(1) -#define CCS_R_PATTERN_SIZE_DIV_M1 0x1318 -#define CCS_R_FIFO_SUPPORT_CAPABILITY 0x1502 -#define CCS_FIFO_SUPPORT_CAPABILITY_NONE 0U -#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING 1U -#define CCS_FIFO_SUPPORT_CAPABILITY_DERATING_OVERRATING 2U -#define CCS_R_PHY_CTRL_CAPABILITY 0x1600 -#define CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL BIT(0) -#define CCS_PHY_CTRL_CAPABILITY_UI_PHY_CTL BIT(1) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_UI_REG_1_CTL BIT(2) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_UI_REG_2_CTL BIT(3) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_TIME_CTL BIT(4) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_1_CTL BIT(5) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_UI_REG_2_CTL BIT(6) -#define CCS_PHY_CTRL_CAPABILITY_DPHY_EXT_TIME_CTL BIT(7) -#define CCS_R_CSI_DPHY_LANE_MODE_CAPABILITY 0x1601 -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_4_LANE BIT(3) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_5_LANE BIT(4) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6) -#define CCS_CSI_DPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7) -#define CCS_R_CSI_SIGNALING_MODE_CAPABILITY 0x1602 -#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_DPHY BIT(2) -#define CCS_CSI_SIGNALING_MODE_CAPABILITY_CSI_CPHY BIT(3) -#define CCS_R_FAST_STANDBY_CAPABILITY 0x1603 -#define CCS_FAST_STANDBY_CAPABILITY_NO_FRAME_TRUNCATION 0U -#define CCS_FAST_STANDBY_CAPABILITY_FRAME_TRUNCATION 1U -#define CCS_R_CSI_ADDRESS_CONTROL_CAPABILITY 0x1604 -#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_CCI_ADDR_CHANGE BIT(0) -#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_2ND_CCI_ADDR BIT(1) -#define CCS_CSI_ADDRESS_CONTROL_CAPABILITY_SW_CHANGEABLE_2ND_CCI_ADDR BIT(2) -#define CCS_R_DATA_TYPE_CAPABILITY 0x1605 -#define CCS_DATA_TYPE_CAPABILITY_DPCM_PROGRAMMABLE BIT(0) -#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_DT_PROGRAMMABLE BIT(1) -#define CCS_DATA_TYPE_CAPABILITY_BOTTOM_EMBEDDED_VC_PROGRAMMABLE BIT(2) -#define CCS_DATA_TYPE_CAPABILITY_EXT_VC_RANGE BIT(3) -#define CCS_R_CSI_CPHY_LANE_MODE_CAPABILITY 0x1606 -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_1_LANE BIT(0) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_2_LANE BIT(1) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_3_LANE BIT(2) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_4_LANE BIT(3) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_5_LANE BIT(4) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_6_LANE BIT(5) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_7_LANE BIT(6) -#define CCS_CSI_CPHY_LANE_MODE_CAPABILITY_8_LANE BIT(7) -#define CCS_R_EMB_DATA_CAPABILITY 0x1607 -#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW16 BIT(0) -#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW20 BIT(1) -#define CCS_EMB_DATA_CAPABILITY_TWO_BYTES_PER_RAW24 BIT(2) -#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW16 BIT(3) -#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW20 BIT(4) -#define CCS_EMB_DATA_CAPABILITY_NO_ONE_BYTE_PER_RAW24 BIT(5) -#define CCS_R_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS(n) ((0x1608 | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x32 + ((n) - 4) * 4)) -#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MIN_N 0U -#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_D_MODE_MBPS_MAX_N 7U -#define CCS_R_TEMP_SENSOR_CAPABILITY 0x1618 -#define CCS_TEMP_SENSOR_CAPABILITY_SUPPORTED BIT(0) -#define CCS_TEMP_SENSOR_CAPABILITY_CCS_FORMAT BIT(1) -#define CCS_TEMP_SENSOR_CAPABILITY_RESET_0X80 BIT(2) -#define CCS_R_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS(n) ((0x161a | (CCS_FL_32BIT | CCS_FL_IREAL)) + ((n) < 4 ? (n) * 4 : 0x30 + ((n) - 4) * 4)) -#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MIN_N 0U -#define CCS_LIM_MAX_PER_LANE_BITRATE_LANE_C_MODE_MBPS_MAX_N 7U -#define CCS_R_DPHY_EQUALIZATION_CAPABILITY 0x162b -#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0) -#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ1 BIT(1) -#define CCS_DPHY_EQUALIZATION_CAPABILITY_EQ2 BIT(2) -#define CCS_R_CPHY_EQUALIZATION_CAPABILITY 0x162c -#define CCS_CPHY_EQUALIZATION_CAPABILITY_EQUALIZATION_CTRL BIT(0) -#define CCS_R_DPHY_PREAMBLE_CAPABILITY 0x162d -#define CCS_DPHY_PREAMBLE_CAPABILITY_PREAMBLE_SEQ_CTRL BIT(0) -#define CCS_R_DPHY_SSC_CAPABILITY 0x162e -#define CCS_DPHY_SSC_CAPABILITY_SUPPORTED BIT(0) -#define CCS_R_CPHY_CALIBRATION_CAPABILITY 0x162f -#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0) -#define CCS_CPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1) -#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_1_CTRL BIT(2) -#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_2_CTRL BIT(3) -#define CCS_CPHY_CALIBRATION_CAPABILITY_FORMAT_3_CTRL BIT(4) -#define CCS_R_DPHY_CALIBRATION_CAPABILITY 0x1630 -#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL BIT(0) -#define CCS_DPHY_CALIBRATION_CAPABILITY_MANUAL_STREAMING BIT(1) -#define CCS_DPHY_CALIBRATION_CAPABILITY_ALTERNATE_SEQ BIT(2) -#define CCS_R_PHY_CTRL_CAPABILITY_2 0x1631 -#define CCS_PHY_CTRL_CAPABILITY_2_TGR_LENGTH BIT(0) -#define CCS_PHY_CTRL_CAPABILITY_2_TGR_PREAMBLE_PROG_SEQ BIT(1) -#define CCS_PHY_CTRL_CAPABILITY_2_EXTRA_CPHY_MANUAL_TIMING BIT(2) -#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_CDPHY BIT(3) -#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_DPHY BIT(4) -#define CCS_PHY_CTRL_CAPABILITY_2_CLOCK_BASED_MANUAL_CPHY BIT(5) -#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY BIT(6) -#define CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY BIT(7) -#define CCS_R_LRTE_CPHY_CAPABILITY 0x1632 -#define CCS_LRTE_CPHY_CAPABILITY_PDQ_SHORT BIT(0) -#define CCS_LRTE_CPHY_CAPABILITY_SPACER_SHORT BIT(1) -#define CCS_LRTE_CPHY_CAPABILITY_PDQ_LONG BIT(2) -#define CCS_LRTE_CPHY_CAPABILITY_SPACER_LONG BIT(3) -#define CCS_LRTE_CPHY_CAPABILITY_SPACER_NO_PDQ BIT(4) -#define CCS_R_LRTE_DPHY_CAPABILITY 0x1633 -#define CCS_LRTE_DPHY_CAPABILITY_PDQ_SHORT_OPT1 BIT(0) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_SHORT_OPT1 BIT(1) -#define CCS_LRTE_DPHY_CAPABILITY_PDQ_LONG_OPT1 BIT(2) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_LONG_OPT1 BIT(3) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_SHORT_OPT2 BIT(4) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_LONG_OPT2 BIT(5) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_NO_PDQ_OPT1 BIT(6) -#define CCS_LRTE_DPHY_CAPABILITY_SPACER_VARIABLE_OPT2 BIT(7) -#define CCS_R_ALPS_CAPABILITY_DPHY 0x1634 -#define CCS_ALPS_CAPABILITY_DPHY_LVLP_NOT_SUPPORTED 0U -#define CCS_ALPS_CAPABILITY_DPHY_LVLP_SUPPORTED 1U -#define CCS_ALPS_CAPABILITY_DPHY_CONTROLLABLE_LVLP 2U -#define CCS_R_ALPS_CAPABILITY_CPHY 0x1635 -#define CCS_ALPS_CAPABILITY_CPHY_LVLP_NOT_SUPPORTED 0U -#define CCS_ALPS_CAPABILITY_CPHY_LVLP_SUPPORTED 1U -#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_LVLP 2U -#define CCS_ALPS_CAPABILITY_CPHY_ALP_NOT_SUPPORTED 0xc -#define CCS_ALPS_CAPABILITY_CPHY_ALP_SUPPORTED 0xd -#define CCS_ALPS_CAPABILITY_CPHY_CONTROLLABLE_ALP 0xe -#define CCS_R_SCRAMBLING_CAPABILITY 0x1636 -#define CCS_SCRAMBLING_CAPABILITY_SCRAMBLING_SUPPORTED BIT(0) -#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_SHIFT 1U -#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_MASK 0x6 -#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_1 0U -#define CCS_SCRAMBLING_CAPABILITY_MAX_SEEDS_PER_LANE_C_4 3U -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_SHIFT 3U -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_MASK 0x38 -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_0 0U -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_1 1U -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_REGS_4 4U -#define CCS_SCRAMBLING_CAPABILITY_NUM_SEED_PER_LANE BIT(6) -#define CCS_R_DPHY_MANUAL_CONSTANT 0x1637 -#define CCS_R_CPHY_MANUAL_CONSTANT 0x1638 -#define CCS_R_CSI2_INTERFACE_CAPABILITY_MISC 0x1639 -#define CCS_CSI2_INTERFACE_CAPABILITY_MISC_EOTP_SHORT_PKT_OPT2 BIT(0) -#define CCS_R_PHY_CTRL_CAPABILITY_3 0x165c -#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_TIMING_NOT_MULTIPLE BIT(0) -#define CCS_PHY_CTRL_CAPABILITY_3_DPHY_MIN_TIMING_VALUE_1 BIT(1) -#define CCS_PHY_CTRL_CAPABILITY_3_TWAKEUP_SUPPORTED BIT(2) -#define CCS_PHY_CTRL_CAPABILITY_3_TINIT_SUPPORTED BIT(3) -#define CCS_PHY_CTRL_CAPABILITY_3_THS_EXIT_SUPPORTED BIT(4) -#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_TIMING_NOT_MULTIPLE BIT(5) -#define CCS_PHY_CTRL_CAPABILITY_3_CPHY_MIN_TIMING_VALUE_1 BIT(6) -#define CCS_R_DPHY_SF 0x165d -#define CCS_R_CPHY_SF 0x165e -#define CCS_CPHY_SF_TWAKEUP_SHIFT 0U -#define CCS_CPHY_SF_TWAKEUP_MASK 0xf -#define CCS_CPHY_SF_TINIT_SHIFT 4U -#define CCS_CPHY_SF_TINIT_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_1 0x165f -#define CCS_DPHY_LIMITS_1_THS_PREPARE_SHIFT 0U -#define CCS_DPHY_LIMITS_1_THS_PREPARE_MASK 0xf -#define CCS_DPHY_LIMITS_1_THS_ZERO_SHIFT 4U -#define CCS_DPHY_LIMITS_1_THS_ZERO_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_2 0x1660 -#define CCS_DPHY_LIMITS_2_THS_TRAIL_SHIFT 0U -#define CCS_DPHY_LIMITS_2_THS_TRAIL_MASK 0xf -#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_SHIFT 4U -#define CCS_DPHY_LIMITS_2_TCLK_TRAIL_MIN_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_3 0x1661 -#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_SHIFT 0U -#define CCS_DPHY_LIMITS_3_TCLK_PREPARE_MASK 0xf -#define CCS_DPHY_LIMITS_3_TCLK_ZERO_SHIFT 4U -#define CCS_DPHY_LIMITS_3_TCLK_ZERO_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_4 0x1662 -#define CCS_DPHY_LIMITS_4_TCLK_POST_SHIFT 0U -#define CCS_DPHY_LIMITS_4_TCLK_POST_MASK 0xf -#define CCS_DPHY_LIMITS_4_TLPX_SHIFT 4U -#define CCS_DPHY_LIMITS_4_TLPX_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_5 0x1663 -#define CCS_DPHY_LIMITS_5_THS_EXIT_SHIFT 0U -#define CCS_DPHY_LIMITS_5_THS_EXIT_MASK 0xf -#define CCS_DPHY_LIMITS_5_TWAKEUP_SHIFT 4U -#define CCS_DPHY_LIMITS_5_TWAKEUP_MASK 0xf0 -#define CCS_R_DPHY_LIMITS_6 0x1664 -#define CCS_DPHY_LIMITS_6_TINIT_SHIFT 0U -#define CCS_DPHY_LIMITS_6_TINIT_MASK 0xf -#define CCS_R_CPHY_LIMITS_1 0x1665 -#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_SHIFT 0U -#define CCS_CPHY_LIMITS_1_T3_PREPARE_MAX_MASK 0xf -#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_SHIFT 4U -#define CCS_CPHY_LIMITS_1_T3_LPX_MAX_MASK 0xf0 -#define CCS_R_CPHY_LIMITS_2 0x1666 -#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_SHIFT 0U -#define CCS_CPHY_LIMITS_2_THS_EXIT_MAX_MASK 0xf -#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_SHIFT 4U -#define CCS_CPHY_LIMITS_2_TWAKEUP_MAX_MASK 0xf0 -#define CCS_R_CPHY_LIMITS_3 0x1667 -#define CCS_CPHY_LIMITS_3_TINIT_MAX_SHIFT 0U -#define CCS_CPHY_LIMITS_3_TINIT_MAX_MASK 0xf -#define CCS_R_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT) -#define CCS_R_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT) -#define CCS_R_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT) -#define CCS_R_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT) -#define CCS_R_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT) -#define CCS_R_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT) -#define CCS_R_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT) -#define CCS_R_BINNING_CAPABILITY 0x1710 -#define CCS_BINNING_CAPABILITY_UNSUPPORTED 0U -#define CCS_BINNING_CAPABILITY_BINNING_THEN_SUBSAMPLING 1U -#define CCS_BINNING_CAPABILITY_SUBSAMPLING_THEN_BINNING 2U -#define CCS_R_BINNING_WEIGHTING_CAPABILITY 0x1711 -#define CCS_BINNING_WEIGHTING_CAPABILITY_AVERAGED BIT(0) -#define CCS_BINNING_WEIGHTING_CAPABILITY_SUMMED BIT(1) -#define CCS_BINNING_WEIGHTING_CAPABILITY_BAYER_CORRECTED BIT(2) -#define CCS_BINNING_WEIGHTING_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3) -#define CCS_R_BINNING_SUB_TYPES 0x1712 -#define CCS_R_BINNING_SUB_TYPE(n) (0x1713 + (n)) -#define CCS_LIM_BINNING_SUB_TYPE_MIN_N 0U -#define CCS_LIM_BINNING_SUB_TYPE_MAX_N 63U -#define CCS_BINNING_SUB_TYPE_ROW_SHIFT 0U -#define CCS_BINNING_SUB_TYPE_ROW_MASK 0xf -#define CCS_BINNING_SUB_TYPE_COLUMN_SHIFT 4U -#define CCS_BINNING_SUB_TYPE_COLUMN_MASK 0xf0 -#define CCS_R_BINNING_WEIGHTING_MONO_CAPABILITY 0x1771 -#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_AVERAGED BIT(0) -#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_SUMMED BIT(1) -#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_BAYER_CORRECTED BIT(2) -#define CCS_BINNING_WEIGHTING_MONO_CAPABILITY_MODULE_SPECIFIC_WEIGHT BIT(3) -#define CCS_R_BINNING_SUB_TYPES_MONO 0x1772 -#define CCS_R_BINNING_SUB_TYPE_MONO(n) (0x1773 + (n)) -#define CCS_LIM_BINNING_SUB_TYPE_MONO_MIN_N 0U -#define CCS_LIM_BINNING_SUB_TYPE_MONO_MAX_N 63U -#define CCS_R_DATA_TRANSFER_IF_CAPABILITY 0x1800 -#define CCS_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED BIT(0) -#define CCS_DATA_TRANSFER_IF_CAPABILITY_POLLING BIT(2) -#define CCS_R_SHADING_CORRECTION_CAPABILITY 0x1900 -#define CCS_SHADING_CORRECTION_CAPABILITY_COLOR_SHADING BIT(0) -#define CCS_SHADING_CORRECTION_CAPABILITY_LUMINANCE_CORRECTION BIT(1) -#define CCS_R_GREEN_IMBALANCE_CAPABILITY 0x1901 -#define CCS_GREEN_IMBALANCE_CAPABILITY_SUPPORTED BIT(0) -#define CCS_R_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903 -#define CCS_R_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT) -#define CCS_DEFECT_CORRECTION_CAPABILITY_MAPPED_DEFECT BIT(0) -#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_COUPLET BIT(2) -#define CCS_DEFECT_CORRECTION_CAPABILITY_DYNAMIC_SINGLE BIT(5) -#define CCS_DEFECT_CORRECTION_CAPABILITY_COMBINED_DYNAMIC BIT(8) -#define CCS_R_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT) -#define CCS_DEFECT_CORRECTION_CAPABILITY_2_DYNAMIC_TRIPLET BIT(3) -#define CCS_R_NF_CAPABILITY 0x1908 -#define CCS_NF_CAPABILITY_LUMA BIT(0) -#define CCS_NF_CAPABILITY_CHROMA BIT(1) -#define CCS_NF_CAPABILITY_COMBINED BIT(2) -#define CCS_R_OB_READOUT_CAPABILITY 0x1980 -#define CCS_OB_READOUT_CAPABILITY_CONTROLLABLE_READOUT BIT(0) -#define CCS_OB_READOUT_CAPABILITY_VISIBLE_PIXEL_READOUT BIT(1) -#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_VC_READOUT BIT(2) -#define CCS_OB_READOUT_CAPABILITY_DIFFERENT_DT_READOUT BIT(3) -#define CCS_OB_READOUT_CAPABILITY_PROG_DATA_FORMAT BIT(4) -#define CCS_R_COLOR_FEEDBACK_CAPABILITY 0x1987 -#define CCS_COLOR_FEEDBACK_CAPABILITY_KELVIN BIT(0) -#define CCS_COLOR_FEEDBACK_CAPABILITY_AWB_GAIN BIT(1) -#define CCS_R_CFA_PATTERN_CAPABILITY 0x1990 -#define CCS_CFA_PATTERN_CAPABILITY_BAYER 0U -#define CCS_CFA_PATTERN_CAPABILITY_MONOCHROME 1U -#define CCS_CFA_PATTERN_CAPABILITY_4X4_QUAD_BAYER 2U -#define CCS_CFA_PATTERN_CAPABILITY_VENDOR_SPECIFIC 3U -#define CCS_R_CFA_PATTERN_CONVERSION_CAPABILITY 0x1991 -#define CCS_CFA_PATTERN_CONVERSION_CAPABILITY_BAYER BIT(0) -#define CCS_R_FLASH_MODE_CAPABILITY 0x1a02 -#define CCS_FLASH_MODE_CAPABILITY_SINGLE_STROBE BIT(0) -#define CCS_R_SA_STROBE_MODE_CAPABILITY 0x1a03 -#define CCS_SA_STROBE_MODE_CAPABILITY_FIXED_WIDTH BIT(0) -#define CCS_SA_STROBE_MODE_CAPABILITY_EDGE_CTRL BIT(1) -#define CCS_R_RESET_MAX_DELAY 0x1a10 -#define CCS_R_RESET_MIN_TIME 0x1a11 -#define CCS_R_PDAF_CAPABILITY_1 0x1b80 -#define CCS_PDAF_CAPABILITY_1_SUPPORTED BIT(0) -#define CCS_PDAF_CAPABILITY_1_PROCESSED_BOTTOM_EMBEDDED BIT(1) -#define CCS_PDAF_CAPABILITY_1_PROCESSED_INTERLEAVED BIT(2) -#define CCS_PDAF_CAPABILITY_1_RAW_BOTTOM_EMBEDDED BIT(3) -#define CCS_PDAF_CAPABILITY_1_RAW_INTERLEAVED BIT(4) -#define CCS_PDAF_CAPABILITY_1_VISIBLE_PDAF_CORRECTION BIT(5) -#define CCS_PDAF_CAPABILITY_1_VC_INTERLEAVING BIT(6) -#define CCS_PDAF_CAPABILITY_1_DT_INTERLEAVING BIT(7) -#define CCS_R_PDAF_CAPABILITY_2 0x1b81 -#define CCS_PDAF_CAPABILITY_2_ROI BIT(0) -#define CCS_PDAF_CAPABILITY_2_AFTER_DIGITAL_CROP BIT(1) -#define CCS_PDAF_CAPABILITY_2_CTRL_RETIMED BIT(2) -#define CCS_R_BRACKETING_LUT_CAPABILITY_1 0x1c00 -#define CCS_BRACKETING_LUT_CAPABILITY_1_COARSE_INTEGRATION BIT(0) -#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_ANALOG_GAIN BIT(1) -#define CCS_BRACKETING_LUT_CAPABILITY_1_FLASH BIT(4) -#define CCS_BRACKETING_LUT_CAPABILITY_1_GLOBAL_DIGITAL_GAIN BIT(5) -#define CCS_BRACKETING_LUT_CAPABILITY_1_ALTERNATE_GLOBAL_ANALOG_GAIN BIT(6) -#define CCS_R_BRACKETING_LUT_CAPABILITY_2 0x1c01 -#define CCS_BRACKETING_LUT_CAPABILITY_2_SINGLE_BRACKETING_MODE BIT(0) -#define CCS_BRACKETING_LUT_CAPABILITY_2_LOOPED_BRACKETING_MODE BIT(1) -#define CCS_R_BRACKETING_LUT_SIZE 0x1c02 - -#endif /* __CCS_REGS_H__ */ diff --git a/drivers/media/i2c/smiapp/ccs.h b/drivers/media/i2c/smiapp/ccs.h deleted file mode 100644 index 20b1125d87dc..000000000000 --- a/drivers/media/i2c/smiapp/ccs.h +++ /dev/null @@ -1,280 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * drivers/media/i2c/smiapp/ccs.h - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2010--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#ifndef __CCS_H__ -#define __CCS_H__ - -#include -#include -#include - -#include "ccs-quirk.h" -#include "ccs-regs.h" -#include "ccs-reg-access.h" -#include "../smiapp-pll.h" -#include "smiapp-reg-defs.h" - -/* - * Standard SMIA++ constants - */ -#define SMIA_VERSION_1 10 -#define SMIAPP_VERSION_0_8 8 /* Draft 0.8 */ -#define SMIAPP_VERSION_0_9 9 /* Draft 0.9 */ -#define SMIAPP_VERSION_1 10 - -#define SMIAPP_PROFILE_0 0 -#define SMIAPP_PROFILE_1 1 -#define SMIAPP_PROFILE_2 2 - -#define SMIAPP_NVM_PAGE_SIZE 64 /* bytes */ - -#define SMIAPP_RESET_DELAY_CLOCKS 2400 -#define SMIAPP_RESET_DELAY(clk) \ - (1000 + (SMIAPP_RESET_DELAY_CLOCKS * 1000 \ - + (clk) / 1000 - 1) / ((clk) / 1000)) - -#define CCS_COLOUR_COMPONENTS 4 - -#define SMIAPP_NAME "smiapp" -#define CCS_NAME "ccs" - -#define CCS_DFL_I2C_ADDR (0x20 >> 1) /* Default I2C Address */ -#define CCS_ALT_I2C_ADDR (0x6e >> 1) /* Alternate I2C Address */ - -/* - * Sometimes due to board layout considerations the camera module can be - * mounted rotated. The typical rotation used is 180 degrees which can be - * corrected by giving a default H-FLIP and V-FLIP in the sensor readout. - * FIXME: rotation also changes the bayer pattern. - */ -enum ccs_module_board_orient { - CCS_MODULE_BOARD_ORIENT_0 = 0, - CCS_MODULE_BOARD_ORIENT_180, -}; - -struct ccs_flash_strobe_parms { - u8 mode; - u32 strobe_width_high_us; - u16 strobe_delay; - u16 stobe_start_point; - u8 trigger; -}; - -struct ccs_hwconfig { - /* - * Change the cci address if i2c_addr_alt is set. - * Both default and alternate cci addr need to be present - */ - unsigned short i2c_addr_dfl; /* Default i2c addr */ - unsigned short i2c_addr_alt; /* Alternate i2c addr */ - - uint32_t ext_clk; /* sensor external clk */ - - unsigned int lanes; /* Number of CSI-2 lanes */ - uint32_t csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */ - uint64_t *op_sys_clock; - - enum ccs_module_board_orient module_board_orient; - - struct ccs_flash_strobe_parms *strobe_setup; -}; - -struct ccs_quirk; - -#define CCS_MODULE_IDENT_FLAG_REV_LE (1 << 0) - -struct ccs_module_ident { - u16 mipi_manufacturer_id; - u16 model_id; - u8 smia_manufacturer_id; - u8 revision_number_major; - - u8 flags; - - char *name; - const struct ccs_quirk *quirk; -}; - -struct ccs_module_info { - u32 smia_manufacturer_id; - u32 mipi_manufacturer_id; - u32 model_id; - u32 revision_number_major; - u32 revision_number_minor; - - u32 module_year; - u32 module_month; - u32 module_day; - - u32 sensor_smia_manufacturer_id; - u32 sensor_mipi_manufacturer_id; - u32 sensor_model_id; - u32 sensor_revision_number; - u32 sensor_firmware_version; - - u32 smia_version; - u32 smiapp_version; - u32 ccs_version; - - u32 smiapp_profile; - - char *name; - const struct ccs_quirk *quirk; -}; - -#define CCS_IDENT_FQ(manufacturer, model, rev, fl, _name, _quirk) \ - { .smia_manufacturer_id = manufacturer, \ - .model_id = model, \ - .revision_number_major = rev, \ - .flags = fl, \ - .name = _name, \ - .quirk = _quirk, } - -#define CCS_IDENT_LQ(manufacturer, model, rev, _name, _quirk) \ - { .smia_manufacturer_id = manufacturer, \ - .model_id = model, \ - .revision_number_major = rev, \ - .flags = CCS_MODULE_IDENT_FLAG_REV_LE, \ - .name = _name, \ - .quirk = _quirk, } - -#define CCS_IDENT_L(manufacturer, model, rev, _name) \ - { .smia_manufacturer_id = manufacturer, \ - .model_id = model, \ - .revision_number_major = rev, \ - .flags = CCS_MODULE_IDENT_FLAG_REV_LE, \ - .name = _name, } - -#define CCS_IDENT_Q(manufacturer, model, rev, _name, _quirk) \ - { .smia_manufacturer_id = manufacturer, \ - .model_id = model, \ - .revision_number_major = rev, \ - .flags = 0, \ - .name = _name, \ - .quirk = _quirk, } - -#define CCS_IDENT(manufacturer, model, rev, _name) \ - { .smia_manufacturer_id = manufacturer, \ - .model_id = model, \ - .revision_number_major = rev, \ - .flags = 0, \ - .name = _name, } - -struct ccs_csi_data_format { - u32 code; - u8 width; - u8 compressed; - u8 pixel_order; -}; - -#define CCS_SUBDEVS 3 - -#define CCS_PA_PAD_SRC 0 -#define CCS_PAD_SINK 0 -#define CCS_PAD_SRC 1 -#define CCS_PADS 2 - -struct ccs_binning_subtype { - u8 horizontal:4; - u8 vertical:4; -} __packed; - -struct ccs_subdev { - struct v4l2_subdev sd; - struct media_pad pads[CCS_PADS]; - struct v4l2_rect sink_fmt; - struct v4l2_rect crop[CCS_PADS]; - struct v4l2_rect compose; /* compose on sink */ - unsigned short sink_pad; - unsigned short source_pad; - int npads; - struct ccs_sensor *sensor; - struct v4l2_ctrl_handler ctrl_handler; -}; - -/* - * struct ccs_sensor - Main device structure - */ -struct ccs_sensor { - /* - * "mutex" is used to serialise access to all fields here - * except v4l2_ctrls at the end of the struct. "mutex" is also - * used to serialise access to file handle specific - * information. - */ - struct mutex mutex; - struct ccs_subdev ssds[CCS_SUBDEVS]; - u32 ssds_used; - struct ccs_subdev *src; - struct ccs_subdev *binner; - struct ccs_subdev *scaler; - struct ccs_subdev *pixel_array; - struct ccs_hwconfig *hwcfg; - struct regulator *vana; - struct clk *ext_clk; - struct gpio_desc *xshutdown; - void *ccs_limits; - u8 nbinning_subtypes; - struct ccs_binning_subtype binning_subtypes[CCS_LIM_BINNING_SUB_TYPE_MAX_N + 1]; - u32 mbus_frame_fmts; - const struct ccs_csi_data_format *csi_format; - const struct ccs_csi_data_format *internal_csi_format; - u32 default_mbus_frame_fmts; - int default_pixel_order; - - u8 binning_horizontal; - u8 binning_vertical; - - u8 scale_m; - u8 scaling_mode; - - u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ - u8 frame_skip; - u16 embedded_start; /* embedded data start line */ - u16 embedded_end; - u16 image_start; /* image data start line */ - u16 visible_pixel_start; /* start pixel of the visible image */ - - bool streaming; - bool dev_init_done; - u8 compressed_min_bpp; - - struct ccs_module_info minfo; - - struct smiapp_pll pll; - - /* Is a default format supported for a given BPP? */ - unsigned long *valid_link_freqs; - - /* Pixel array controls */ - struct v4l2_ctrl *analog_gain; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - struct v4l2_ctrl *vblank; - struct v4l2_ctrl *hblank; - struct v4l2_ctrl *pixel_rate_parray; - /* src controls */ - struct v4l2_ctrl *link_freq; - struct v4l2_ctrl *pixel_rate_csi; - /* test pattern colour components */ - struct v4l2_ctrl *test_data[CCS_COLOUR_COMPONENTS]; -}; - -#define to_ccs_subdev(_sd) \ - container_of(_sd, struct ccs_subdev, sd) - -#define to_ccs_sensor(_sd) \ - (to_ccs_subdev(_sd)->sensor) - -void ccs_replace_limit(struct ccs_sensor *sensor, - unsigned int limit, unsigned int offset, u32 val); - -#endif /* __CCS_H__ */ diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h deleted file mode 100644 index 06b69b1ab55f..000000000000 --- a/drivers/media/i2c/smiapp/smiapp-reg-defs.h +++ /dev/null @@ -1,579 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * drivers/media/i2c/smiapp/smiapp-reg-defs.h - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#ifndef __SMIAPP_REG_DEFS_H__ -#define __SMIAPP_REG_DEFS_H__ - -/* Register addresses */ -#define SMIAPP_REG_U16_MODEL_ID (0x0000 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR 0x0002 -#define SMIAPP_REG_U8_MANUFACTURER_ID 0x0003 -#define SMIAPP_REG_U8_SMIA_VERSION 0x0004 -#define SMIAPP_REG_U8_FRAME_COUNT 0x0005 -#define SMIAPP_REG_U8_PIXEL_ORDER 0x0006 -#define SMIAPP_REG_U16_DATA_PEDESTAL (0x0008 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_PIXEL_DEPTH 0x000c -#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR 0x0010 -#define SMIAPP_REG_U8_SMIAPP_VERSION 0x0011 -#define SMIAPP_REG_U8_MODULE_DATE_YEAR 0x0012 -#define SMIAPP_REG_U8_MODULE_DATE_MONTH 0x0013 -#define SMIAPP_REG_U8_MODULE_DATE_DAY 0x0014 -#define SMIAPP_REG_U8_MODULE_DATE_PHASE 0x0015 -#define SMIAPP_REG_U16_SENSOR_MODEL_ID (0x0016 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER 0x0018 -#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID 0x0019 -#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION 0x001a -#define SMIAPP_REG_U32_SERIAL_NUMBER (0x001c | CCS_FL_32BIT) -#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE 0x0040 -#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE 0x0041 -#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n) ((0x0042 + ((n) << 1)) | CCS_FL_16BIT) /* 0 <= n <= 14 */ -#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n) ((0x0060 + ((n) << 2)) | CCS_FL_32BIT) /* 0 <= n <= 7 */ -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY (0x0080 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN (0x0084 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX (0x0086 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP (0x0088 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE (0x008a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0 (0x008c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0 (0x008e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1 (0x0090 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1 (0x0092 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE 0x00c0 -#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE 0x00c1 -#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n) ((0x00c2 + ((n) << 1)) | CCS_FL_16BIT) -#define SMIAPP_REG_U8_MODE_SELECT 0x0100 -#define SMIAPP_REG_U8_IMAGE_ORIENTATION 0x0101 -#define SMIAPP_REG_U8_SOFTWARE_RESET 0x0103 -#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD 0x0104 -#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES 0x0105 -#define SMIAPP_REG_U8_FAST_STANDBY_CTRL 0x0106 -#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL 0x0107 -#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL 0x0108 -#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL 0x0109 -#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER 0x0110 -#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE 0x0111 -#define SMIAPP_REG_U16_CSI_DATA_FORMAT (0x0112 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_CSI_LANE_MODE 0x0114 -#define SMIAPP_REG_U8_CSI2_10_TO_8_DT 0x0115 -#define SMIAPP_REG_U8_CSI2_10_TO_7_DT 0x0116 -#define SMIAPP_REG_U8_CSI2_10_TO_6_DT 0x0117 -#define SMIAPP_REG_U8_CSI2_12_TO_8_DT 0x0118 -#define SMIAPP_REG_U8_CSI2_12_TO_7_DT 0x0119 -#define SMIAPP_REG_U8_CSI2_12_TO_6_DT 0x011a -#define SMIAPP_REG_U8_CSI2_14_TO_10_DT 0x011b -#define SMIAPP_REG_U8_CSI2_14_TO_8_DT 0x011c -#define SMIAPP_REG_U8_CSI2_16_TO_10_DT 0x011d -#define SMIAPP_REG_U8_CSI2_16_TO_8_DT 0x011e -#define SMIAPP_REG_U8_GAIN_MODE 0x0120 -#define SMIAPP_REG_U16_VANA_VOLTAGE (0x0130 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VDIG_VOLTAGE (0x0132 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VIO_VOLTAGE (0x0134 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ (0x0136 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL 0x0138 -#define SMIAPP_REG_U8_TEMP_SENSOR_MODE 0x0139 -#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT 0x013a -#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME (0x0200 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME (0x0202 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL (0x0204 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR (0x0206 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED (0x0208 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE (0x020a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB (0x020c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR (0x020e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_RED (0x0210 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE (0x0212 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB (0x0214 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VT_PIX_CLK_DIV (0x0300 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VT_SYS_CLK_DIV (0x0302 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV (0x0304 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_PLL_MULTIPLIER (0x0306 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_OP_PIX_CLK_DIV (0x0308 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_OP_SYS_CLK_DIV (0x030a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FRAME_LENGTH_LINES (0x0340 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_LINE_LENGTH_PCK (0x0342 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_ADDR_START (0x0344 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_ADDR_START (0x0346 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_ADDR_END (0x0348 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_ADDR_END (0x034a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_OUTPUT_SIZE (0x034c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_OUTPUT_SIZE (0x034e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_EVEN_INC (0x0380 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_ODD_INC (0x0382 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_EVEN_INC (0x0384 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_ODD_INC (0x0386 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALING_MODE (0x0400 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SPATIAL_SAMPLING (0x0402 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALE_M (0x0404 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALE_N (0x0406 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET (0x0408 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET (0x040a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH (0x040c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT (0x040e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_COMPRESSION_MODE (0x0500 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TEST_PATTERN_MODE (0x0600 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TEST_DATA_RED (0x0602 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TEST_DATA_GREENR (0x0604 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TEST_DATA_BLUE (0x0606 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TEST_DATA_GREENB (0x0608 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH (0x060a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION (0x060c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH (0x060e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION (0x0610 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS (0x0700 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_TCLK_POST 0x0800 -#define SMIAPP_REG_U8_THS_PREPARE 0x0801 -#define SMIAPP_REG_U8_THS_ZERO_MIN 0x0802 -#define SMIAPP_REG_U8_THS_TRAIL 0x0803 -#define SMIAPP_REG_U8_TCLK_TRAIL_MIN 0x0804 -#define SMIAPP_REG_U8_TCLK_PREPARE 0x0805 -#define SMIAPP_REG_U8_TCLK_ZERO 0x0806 -#define SMIAPP_REG_U8_TLPX 0x0807 -#define SMIAPP_REG_U8_DPHY_CTRL 0x0808 -#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS (0x0820 | CCS_FL_32BIT) -#define SMIAPP_REG_U8_BINNING_MODE 0x0900 -#define SMIAPP_REG_U8_BINNING_TYPE 0x0901 -#define SMIAPP_REG_U8_BINNING_WEIGHTING 0x0902 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL 0x0a00 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS 0x0a01 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT 0x0a02 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 0x0a04 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1 0x0a05 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2 0x0a06 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3 0x0a07 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4 0x0a08 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5 0x0a09 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12 0x0a10 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13 0x0a11 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14 0x0a12 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15 0x0a13 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16 0x0a14 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17 0x0a15 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18 0x0a16 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19 0x0a17 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20 0x0a18 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21 0x0a19 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22 0x0a1a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23 0x0a1b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24 0x0a1c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25 0x0a1d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26 0x0a1e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27 0x0a1f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28 0x0a20 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29 0x0a21 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30 0x0a22 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31 0x0a23 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32 0x0a24 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33 0x0a25 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34 0x0a26 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35 0x0a27 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36 0x0a28 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37 0x0a29 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38 0x0a2a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39 0x0a2b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40 0x0a2c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41 0x0a2d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42 0x0a2e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43 0x0a2f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44 0x0a30 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45 0x0a31 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46 0x0a32 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47 0x0a33 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48 0x0a34 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49 0x0a35 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50 0x0a36 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51 0x0a37 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52 0x0a38 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53 0x0a39 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54 0x0a3a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55 0x0a3b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56 0x0a3c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57 0x0a3d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58 0x0a3e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59 0x0a3f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60 0x0a40 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61 0x0a41 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62 0x0a42 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63 0x0a43 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL 0x0a44 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS 0x0a45 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT 0x0a46 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0 0x0a48 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1 0x0a49 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2 0x0a4a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3 0x0a4b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4 0x0a4c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5 0x0a4d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6 0x0a4e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7 0x0a4f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8 0x0a50 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9 0x0a51 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10 0x0a52 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11 0x0a53 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12 0x0a54 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13 0x0a55 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14 0x0a56 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15 0x0a57 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16 0x0a58 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17 0x0a59 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18 0x0a5a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19 0x0a5b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20 0x0a5c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21 0x0a5d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22 0x0a5e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23 0x0a5f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24 0x0a60 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25 0x0a61 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26 0x0a62 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27 0x0a63 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28 0x0a64 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29 0x0a65 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30 0x0a66 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31 0x0a67 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32 0x0a68 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33 0x0a69 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34 0x0a6a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35 0x0a6b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36 0x0a6c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37 0x0a6d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38 0x0a6e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39 0x0a6f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40 0x0a70 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41 0x0a71 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42 0x0a72 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43 0x0a73 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44 0x0a74 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45 0x0a75 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46 0x0a76 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47 0x0a77 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48 0x0a78 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49 0x0a79 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50 0x0a7a -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51 0x0a7b -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52 0x0a7c -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53 0x0a7d -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54 0x0a7e -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55 0x0a7f -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56 0x0a80 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57 0x0a81 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58 0x0a82 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59 0x0a83 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60 0x0a84 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61 0x0a85 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62 0x0a86 -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63 0x0a87 -#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE 0x0b00 -#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL 0x0b01 -#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE 0x0b02 -#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT 0x0b03 -#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE 0x0b04 -#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE 0x0b05 -#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE 0x0b06 -#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT 0x0b07 -#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE 0x0b08 -#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT 0x0b09 -#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE 0x0b0a -#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT 0x0b0b -#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE 0x0b0c -#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT 0x0b0d -#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE 0x0b0e -#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST 0x0b0f -#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST 0x0b10 -#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b11 -#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b12 -#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE 0x0b13 -#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST 0x0b14 -#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE 0x0b15 -#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST 0x0b16 -#define SMIAPP_REG_U8_EDOF_MODE 0x0b80 -#define SMIAPP_REG_U8_SHARPNESS 0x0b83 -#define SMIAPP_REG_U8_DENOISING 0x0b84 -#define SMIAPP_REG_U8_MODULE_SPECIFIC 0x0b85 -#define SMIAPP_REG_U16_DEPTH_OF_FIELD (0x0b86 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FOCUS_DISTANCE (0x0b88 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL 0x0b8a -#define SMIAPP_REG_U16_COLOUR_TEMPERATURE (0x0b8c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR (0x0b8e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED (0x0b90 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE (0x0b92 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB (0x0b94 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE 0x0bc0 -#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING (0x0bc2 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START (0x0bc4 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START (0x0bc6 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH (0x0bc8 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT (0x0bca | CCS_FL_16BIT) -#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1 0x0c00 -#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2 0x0c01 -#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1 0x0c02 -#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2 0x0c03 -#define SMIAPP_REG_U16_TRDY_CTRL (0x0c04 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TRDOUT_CTRL (0x0c06 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL (0x0c08 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL (0x0c0a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL (0x0c0c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL (0x0c0e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL (0x0c10 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT 0x0c12 -#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT (0x0c14 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL (0x0c16 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL (0x0c18 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_FLASH_MODE_RS 0x0c1a -#define SMIAPP_REG_U8_FLASH_TRIGGER_RS 0x0c1b -#define SMIAPP_REG_U8_FLASH_STATUS 0x0c1c -#define SMIAPP_REG_U8_SA_STROBE_MODE 0x0c1d -#define SMIAPP_REG_U16_SA_STROBE_START_POINT (0x0c1e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL (0x0c20 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL (0x0c22 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_SA_STROBE_TRIGGER 0x0c24 -#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS 0x0c25 -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL (0x0c26 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL (0x0c28 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL 0x0c2a -#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL 0x0c2b -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL (0x0c2c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL (0x0c2e | CCS_FL_16BIT) -#define SMIAPP_REG_U8_LOW_LEVEL_CTRL 0x0c80 -#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT (0x0c82 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAIN_TRIGGER_T3 (0x0c84 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT 0x0c86 -#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3 (0x0c88 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT 0x0c8a -#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3 (0x0c8c | CCS_FL_16BIT) -#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT 0x0c8e -#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL 0x0d00 -#define SMIAPP_REG_U8_OPERATION_MODE 0x0d01 -#define SMIAPP_REG_U8_ACT_STATE1 0x0d02 -#define SMIAPP_REG_U8_ACT_STATE2 0x0d03 -#define SMIAPP_REG_U16_FOCUS_CHANGE (0x0d80 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL (0x0d82 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1 (0x0d84 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2 (0x0d86 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1 0x0d88 -#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2 0x0d89 -#define SMIAPP_REG_U8_POSITION 0x0d8a -#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL 0x0e00 -#define SMIAPP_REG_U8_BRACKETING_LUT_MODE 0x0e01 -#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL 0x0e02 -#define SMIAPP_REG_U8_LUT_PARAMETERS_START 0x0e10 -#define SMIAPP_REG_U8_LUT_PARAMETERS_END 0x0eff -#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY (0x1000 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN (0x1004 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN (0x1006 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN (0x1008 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN (0x100a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY (0x1080 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN (0x1084 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX (0x1086 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE (0x1088 | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ (0x1100 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ (0x1104 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV (0x1108 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV (0x110a | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ (0x110c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ (0x1110 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER (0x1114 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER (0x1116 | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ (0x1118 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ (0x111c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV (0x1120 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV (0x1122 | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ (0x1124 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ (0x1128 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ (0x112c | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ (0x1130 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV (0x1134 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV (0x1136 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES (0x1140 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES (0x1142 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK (0x1144 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK (0x1146 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK (0x1148 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES (0x114a | CCS_FL_16BIT) -#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE 0x114c -#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV (0x1160 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV (0x1162 | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ (0x1164 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ (0x1168 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV (0x116c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV (0x116e | CCS_FL_16BIT) -#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ (0x1170 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ (0x1174 | CCS_FL_FLOAT_IREAL | CCS_FL_32BIT) -#define SMIAPP_REG_U16_X_ADDR_MIN (0x1180 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_ADDR_MIN (0x1182 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_X_ADDR_MAX (0x1184 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_Y_ADDR_MAX (0x1186 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE (0x1188 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE (0x118a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE (0x118c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE (0x118e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_EVEN_INC (0x11c0 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_EVEN_INC (0x11c2 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_ODD_INC (0x11c4 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_ODD_INC (0x11c6 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALING_CAPABILITY (0x1200 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALER_M_MIN (0x1204 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALER_M_MAX (0x1206 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALER_N_MIN (0x1208 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SCALER_N_MAX (0x120a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY (0x120c | CCS_FL_16BIT) -#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY 0x120e -#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY (0x1300 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED (0x1400 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED (0x1402 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED (0x1404 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN (0x1406 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN (0x1408 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN (0x140a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE (0x140c | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE (0x140e | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE (0x1410 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS (0x1500 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY 0x1502 -#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY 0x1600 -#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY 0x1601 -#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY 0x1602 -#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY 0x1603 -#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY 0x1604 -#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS (0x1608 | CCS_FL_32BIT) -#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS (0x160c | CCS_FL_32BIT) -#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS (0x1610 | CCS_FL_32BIT) -#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS (0x1614 | CCS_FL_32BIT) -#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY 0x1618 -#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN (0x1700 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN (0x1702 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN (0x1704 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN (0x1706 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN (0x1708 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN (0x170a | CCS_FL_16BIT) -#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN (0x170c | CCS_FL_16BIT) -#define SMIAPP_REG_U8_BINNING_CAPABILITY 0x1710 -#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY 0x1711 -#define SMIAPP_REG_U8_BINNING_SUBTYPES 0x1712 -#define SMIAPP_REG_U8_BINNING_TYPE_n(n) (0x1713 + (n)) /* 1 <= n <= 237 */ -#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY 0x1800 -#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY 0x1900 -#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY 0x1901 -#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY 0x1902 -#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY 0x1903 -#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY (0x1904 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2 (0x1906 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_EDOF_CAPABILITY 0x1980 -#define SMIAPP_REG_U8_ESTIMATION_FRAMES 0x1981 -#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ 0x1982 -#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ 0x1983 -#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ 0x1984 -#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ 0x1985 -#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ 0x1986 -#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY 0x1987 -#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM 0x1988 -#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY 0x19c0 -#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY 0x19c1 -#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD (0x19c2 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE (0x19c4 | CCS_FL_16BIT) -#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN (0x1a00 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY 0x1a02 -#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR (0x1b02 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY 0x1b04 -#define SMIAPP_REG_U16_ACTUATOR_TYPE (0x1b40 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS 0x1b42 -#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS (0x1b44 | CCS_FL_16BIT) -#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1 0x1c00 -#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2 0x1c01 -#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE 0x1c02 - -/* Register bit definitions */ -#define SMIAPP_IMAGE_ORIENTATION_HFLIP BIT(0) -#define SMIAPP_IMAGE_ORIENTATION_VFLIP BIT(1) - -#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN BIT(0) -#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_WR_EN BIT(1) -#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_ERR_CLEAR BIT(2) -#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY BIT(0) -#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_WR_READY BIT(1) -#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EDATA BIT(2) -#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE BIT(3) - -#define SMIAPP_DATA_TRANSFER_IF_CAPABILITY_SUPPORTED BIT(0) -#define SMIAPP_DATA_TRANSFER_IF_CAPABILITY_POLL BIT(2) - -#define SMIAPP_SOFTWARE_RESET BIT(0) - -#define SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE BIT(0) -#define SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE BIT(1) - -#define SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK 0 -#define SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE 1 -#define SMIAPP_CSI_SIGNALLING_MODE_CSI2 2 - -#define SMIAPP_DPHY_CTRL_AUTOMATIC 0 -/* DPHY control based on REQUESTED_LINK_BIT_RATE_MBPS */ -#define SMIAPP_DPHY_CTRL_UI 1 -#define SMIAPP_DPHY_CTRL_REGISTER 2 - -#define SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR 1 -#define SMIAPP_COMPRESSION_MODE_ADVANCED_PREDICTOR 2 - -#define SMIAPP_MODE_SELECT_SOFTWARE_STANDBY 0 -#define SMIAPP_MODE_SELECT_STREAMING 1 - -#define SMIAPP_SCALING_MODE_NONE 0 -#define SMIAPP_SCALING_MODE_HORIZONTAL 1 -#define SMIAPP_SCALING_MODE_BOTH 2 - -#define SMIAPP_SCALING_CAPABILITY_NONE 0 -#define SMIAPP_SCALING_CAPABILITY_HORIZONTAL 1 -#define SMIAPP_SCALING_CAPABILITY_BOTH 2 /* horizontal/both */ - -/* digital crop right before scaler */ -#define SMIAPP_DIGITAL_CROP_CAPABILITY_NONE 0 -#define SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1 - -#define SMIAPP_BINNING_CAPABILITY_NO 0 -#define SMIAPP_BINNING_CAPABILITY_YES 1 - -/* Maximum number of binning subtypes */ -#define SMIAPP_BINNING_SUBTYPES 253 - -#define SMIAPP_PIXEL_ORDER_GRBG 0 -#define SMIAPP_PIXEL_ORDER_RGGB 1 -#define SMIAPP_PIXEL_ORDER_BGGR 2 -#define SMIAPP_PIXEL_ORDER_GBRG 3 - -#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL 1 -#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED 2 -#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N 8 -#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N 16 - -#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE 0x01 -#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE 0x02 -#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK 0x0f -#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK 0xf0 -#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT 4 - -#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK 0xf000 -#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT 12 -#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK 0x0fff - -#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK 0xf0000000 -#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT 28 -#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK 0x0000ffff - -#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED 1 -#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY 2 -#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK 3 -#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK 4 -#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE 5 - -#define SMIAPP_FAST_STANDBY_CTRL_COMPLETE_FRAMES 0 -#define SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE 1 - -/* Scaling N factor */ -#define SMIAPP_SCALE_N 16 - -#endif /* __SMIAPP_REG_DEFS_H__ */ -- cgit v1.2.3 From 8265d427eddcfcfe01cd98f6fa3a5acb79f76fe8 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 29 Sep 2020 13:32:17 +0200 Subject: media: dt-bindings: nokia,smia: Convert to YAML Convert nokia,smia DT bindings to YAML. Also add explicit license to bindings. Signed-off-by: Sakari Ailus Reviewed-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/nokia,smia.txt | 67 ------------- .../devicetree/bindings/media/i2c/nokia,smia.yaml | 106 +++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 107 insertions(+), 68 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/i2c/nokia,smia.txt create mode 100644 Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt b/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt deleted file mode 100644 index 5f39a7070c51..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/nokia,smia.txt +++ /dev/null @@ -1,67 +0,0 @@ -SMIA/SMIA++ sensor - -SMIA (Standard Mobile Imaging Architecture) is an image sensor standard -defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension -of that. These definitions are valid for both types of sensors. - -More detailed documentation can be found in -Documentation/devicetree/bindings/media/video-interfaces.txt . - -The device node should contain a "port" node which may contain one or more -endpoint nodes, in accordance with video interface bindings defined in -Documentation/devicetree/bindings/media/video-interfaces.txt . - -Mandatory properties --------------------- - -- compatible: "nokia,smia" -- reg: I2C address (0x10, or an alternative address) -- clocks: External clock to the sensor -- clock-frequency: Frequency of the external clock to the sensor - - -Optional properties -------------------- - -- reset-gpios: XSHUTDOWN GPIO -- flash-leds: See ../video-interfaces.txt -- lens-focus: See ../video-interfaces.txt -- rotation: Integer property; valid values are 0 (sensor mounted upright) - and 180 (sensor mounted upside down). See - ../video-interfaces.txt . -- vana-supply: Analogue voltage supply (VANA), typically 2,8 volts (sensor - dependent). - - -Endpoint node mandatory properties ----------------------------------- - -- data-lanes: <1..n> -- link-frequencies: List of allowed data link frequencies. An array of - 64-bit elements. - - -Example -------- - -&i2c2 { - clock-frequency = <400000>; - - camera-sensor@10 { - compatible = "nokia,smia"; - reg = <0x10>; - reset-gpios = <&gpio3 20 0>; - vana-supply = <&vaux3>; - clocks = <&omap3_isp 0>; - clock-frequency = <9600000>; - port { - smiapp_ep: endpoint { - data-lanes = <1 2>; - remote-endpoint = <&csi2a_ep>; - link-frequencies = - /bits/ 64 <199200000 210000000 - 499200000>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml b/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml new file mode 100644 index 000000000000..ee552489fa2b --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2014--2020 Intel Corporation + +$id: http://devicetree.org/schemas/media/i2c/nokia,smia.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SMIA/SMIA++ sensor + +maintainers: + - Sakari Ailus + +description: + + SMIA (Standard Mobile Imaging Architecture) is an image sensor standard + defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension of + that. These definitions are valid for both types of sensors. + + More detailed documentation can be found in + Documentation/devicetree/bindings/media/video-interfaces.txt . + +properties: + compatible: + const: nokia,smia + + reg: + maxItems: 1 + + vana-supply: + description: Analogue voltage supply (VANA), typically 2,8 volts (sensor + dependent). + maxItems: 1 + + clocks: + description: External clock to the sensor. + maxItems: 1 + + clock-frequency: + description: Frequency of the external clock to the sensor in Hz. + + reset-gpios: + description: Reset GPIO. Also commonly called XSHUTDOWN in hardware + documentation. + maxItems: 1 + + flash-leds: + description: Flash LED phandles. See ../video-interfaces.txt for details. + + lens-focus: + description: Lens focus controller phandles. See ../video-interfaces.txt + for details. + + rotation: + description: Rotation of the sensor. See ../video-interfaces.txt for + details. + enum: [ 0, 180 ] + + port: + type: object + properties: + endpoint: + type: object + properties: + link-frequencies: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: List of allowed data link frequencies. + data-lanes: + minItems: 1 + maxItems: 8 + required: + - link-frequencies + - data-lanes + +required: + - compatible + - reg + - clock-frequency + - clocks + +additionalProperties: false + +examples: + - | + i2c2 { + #address-cells = <1>; + #size-cells = <0>; + + clock-frequency = <400000>; + + camera-sensor@10 { + compatible = "nokia,smia"; + reg = <0x10>; + reset-gpios = <&gpio3 20 0>; + vana-supply = <&vaux3>; + clocks = <&omap3_isp 0>; + clock-frequency = <9600000>; + port { + smiapp_ep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csi2a_ep>; + link-frequencies = /bits/ 64 <199200000 210000000 + 499200000>; + }; + }; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index e23b3e4d9a9d..38faf82ef766 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11634,7 +11634,7 @@ MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER M: Sakari Ailus L: linux-media@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt +F: Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml F: Documentation/driver-api/media/drivers/ccs/ F: drivers/media/i2c/ccs/ F: drivers/media/i2c/smiapp-pll.c -- cgit v1.2.3 From 72051783cd736d82711fe6fd1df2b71a0d4d6e82 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 11 Feb 2020 22:26:25 +0100 Subject: media: dt-bindings: nokia,smia: Amend SMIA bindings with MIPI CCS support Amend the existing SMIA bindings by adding MIPI CCS support, with separate compatible strings for CCS 1.0 and CCS 1.1. Rename the old bindings accordingly as CCS is the current standard. Signed-off-by: Sakari Ailus Reviewed-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/mipi-ccs.yaml | 119 +++++++++++++++++++++ .../devicetree/bindings/media/i2c/nokia,smia.yaml | 108 ------------------- MAINTAINERS | 2 +- 3 files changed, 120 insertions(+), 109 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml delete mode 100644 Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml new file mode 100644 index 000000000000..a386ee246956 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2014--2020 Intel Corporation + +$id: http://devicetree.org/schemas/media/i2c/mipi-ccs.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MIPI CCS, SMIA++ and SMIA compliant camera sensors + +maintainers: + - Sakari Ailus + +description: + + CCS (Camera Command Set) is a raw Bayer camera sensor standard defined by the + MIPI Alliance; see + . + + SMIA (Standard Mobile Imaging Architecture) is an image sensor standard + defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension of + that. + + More detailed documentation can be found in + Documentation/devicetree/bindings/media/video-interfaces.txt . + +properties: + compatible: + oneOf: + - items: + - const: mipi-ccs-1.1 + - const: mipi-ccs + - items: + - const: mipi-ccs-1.0 + - const: mipi-ccs + - const: nokia,smia + + reg: + maxItems: 1 + + vana-supply: + description: Analogue voltage supply (VANA), typically 2,8 volts (sensor + dependent). + maxItems: 1 + + clocks: + description: External clock to the sensor. + maxItems: 1 + + clock-frequency: + description: Frequency of the external clock to the sensor in Hz. + + reset-gpios: + description: Reset GPIO. Also commonly called XSHUTDOWN in hardware + documentation. + maxItems: 1 + + flash-leds: + description: Flash LED phandles. See ../video-interfaces.txt for details. + + lens-focus: + description: Lens focus controller phandles. See ../video-interfaces.txt + for details. + + rotation: + description: Rotation of the sensor. See ../video-interfaces.txt for + details. + enum: [ 0, 180 ] + + port: + type: object + properties: + endpoint: + type: object + properties: + link-frequencies: + $ref: /schemas/types.yaml#/definitions/uint64-array + description: List of allowed data link frequencies. + data-lanes: + minItems: 1 + maxItems: 8 + required: + - link-frequencies + - data-lanes + +required: + - compatible + - reg + - clock-frequency + - clocks + +additionalProperties: false + +examples: + - | + #include + + i2c2 { + #address-cells = <1>; + #size-cells = <0>; + + clock-frequency = <400000>; + + camera-sensor@10 { + compatible = "mipi-ccs-1.0", "mipi-ccs"; + reg = <0x10>; + reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; + vana-supply = <&vaux3>; + clocks = <&omap3_isp 0>; + clock-frequency = <9600000>; + port { + ccs_ep: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&csi2a_ep>; + link-frequencies = /bits/ 64 <199200000 210000000 + 499200000>; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml b/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml deleted file mode 100644 index 47df08338a42..000000000000 --- a/Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml +++ /dev/null @@ -1,108 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# Copyright (C) 2014--2020 Intel Corporation - -$id: http://devicetree.org/schemas/media/i2c/nokia,smia.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: SMIA/SMIA++ sensor - -maintainers: - - Sakari Ailus - -description: - - SMIA (Standard Mobile Imaging Architecture) is an image sensor standard - defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension of - that. These definitions are valid for both types of sensors. - - More detailed documentation can be found in - Documentation/devicetree/bindings/media/video-interfaces.txt . - -properties: - compatible: - const: nokia,smia - - reg: - maxItems: 1 - - vana-supply: - description: Analogue voltage supply (VANA), typically 2,8 volts (sensor - dependent). - maxItems: 1 - - clocks: - description: External clock to the sensor. - maxItems: 1 - - clock-frequency: - description: Frequency of the external clock to the sensor in Hz. - - reset-gpios: - description: Reset GPIO. Also commonly called XSHUTDOWN in hardware - documentation. - maxItems: 1 - - flash-leds: - description: Flash LED phandles. See ../video-interfaces.txt for details. - - lens-focus: - description: Lens focus controller phandles. See ../video-interfaces.txt - for details. - - rotation: - description: Rotation of the sensor. See ../video-interfaces.txt for - details. - enum: [ 0, 180 ] - - port: - type: object - properties: - endpoint: - type: object - properties: - link-frequencies: - $ref: /schemas/types.yaml#/definitions/uint64-array - description: List of allowed data link frequencies. - data-lanes: - minItems: 1 - maxItems: 8 - required: - - link-frequencies - - data-lanes - -required: - - compatible - - reg - - clock-frequency - - clocks - -additionalProperties: false - -examples: - - | - #include - - i2c2 { - #address-cells = <1>; - #size-cells = <0>; - - clock-frequency = <400000>; - - camera-sensor@10 { - compatible = "nokia,smia"; - reg = <0x10>; - reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; - vana-supply = <&vaux3>; - clocks = <&omap3_isp 0>; - clock-frequency = <9600000>; - port { - smiapp_ep: endpoint { - data-lanes = <1 2>; - remote-endpoint = <&csi2a_ep>; - link-frequencies = /bits/ 64 <199200000 210000000 - 499200000>; - }; - }; - }; - }; -... diff --git a/MAINTAINERS b/MAINTAINERS index 38faf82ef766..5c05e7bf7ffd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11634,7 +11634,7 @@ MIPI CCS, SMIA AND SMIA++ IMAGE SENSOR DRIVER M: Sakari Ailus L: linux-media@vger.kernel.org S: Maintained -F: Documentation/devicetree/bindings/media/i2c/nokia,smia.yaml +F: Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml F: Documentation/driver-api/media/drivers/ccs/ F: drivers/media/i2c/ccs/ F: drivers/media/i2c/smiapp-pll.c -- cgit v1.2.3 From 34487ad0c0aedc32ab18a25a274025e73ea00834 Mon Sep 17 00:00:00 2001 From: Dongchun Zhu Date: Wed, 25 Nov 2020 15:17:55 +0100 Subject: media: dt-bindings: media: i2c: document OV02A10 DT bindings Add device-tree binding documentation for OV02A10 image sensor driver, and the relevant MAINTAINERS entries. Signed-off-by: Dongchun Zhu Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/i2c/ovti,ov02a10.yaml | 159 +++++++++++++++++++++ MAINTAINERS | 7 + 2 files changed, 166 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml (limited to 'MAINTAINERS') diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml new file mode 100644 index 000000000000..1c3879ec4122 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (c) 2020 MediaTek Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/ovti,ov02a10.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Omnivision OV02A10 CMOS Sensor Device Tree Bindings + +maintainers: + - Dongchun Zhu + +description: |- + The Omnivision OV02A10 is a low-cost, high performance, 1/5-inch, 2 megapixel + image sensor, which is the latest production derived from Omnivision's CMOS + image sensor technology. Ihis chip supports high frame rate speeds up to 30fps + @ 1600x1200 (UXGA) resolution transferred over a 1-lane MIPI interface. The + sensor output is available via CSI-2 serial data output. + +properties: + compatible: + const: ovti,ov02a10 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + description: + External clock for the sensor. + items: + - const: eclk + + clock-frequency: + description: + Frequency of the eclk clock in Hz. + + dovdd-supply: + description: + Definition of the regulator used as Digital I/O voltage supply. + + avdd-supply: + description: + Definition of the regulator used as Analog voltage supply. + + dvdd-supply: + description: + Definition of the regulator used as Digital core voltage supply. + + powerdown-gpios: + description: + Must be the device tree identifier of the GPIO connected to the + PD_PAD pin. This pin is used to place the OV02A10 into standby mode + or shutdown mode. As the line needs to be high for the powerdown mode + to be active, it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + reset-gpios: + description: + Must be the device tree identifier of the GPIO connected to the + RST_PD pin. If specified, it will be asserted during driver probe. + As the line needs to be low for the reset to be active, it should be + marked GPIO_ACTIVE_LOW. + maxItems: 1 + + rotation: + description: + Definition of the sensor's placement. + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - enum: + - 0 # Sensor Mounted Upright + - 180 # Sensor Mounted Upside Down + default: 0 + + # See ../video-interfaces.txt for details + port: + type: object + additionalProperties: false + description: + Output port node, single endpoint describing the CSI-2 transmitter. + + properties: + endpoint: + type: object + additionalProperties: false + + properties: + link-frequencies: true + ovti,mipi-clock-voltage: + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + description: + Definition of MIPI clock voltage unit. This entry corresponds to + the link speed defined by the 'link-frequencies' property. + If present, the value shall be in the range of 0-4. + default: 4 + remote-endpoint: true + + required: + - link-frequencies + - remote-endpoint + + required: + - endpoint + +required: + - compatible + - reg + - clocks + - clock-names + - clock-frequency + - dovdd-supply + - avdd-supply + - dvdd-supply + - powerdown-gpios + - reset-gpios + - port + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + ov02a10: camera-sensor@3d { + compatible = "ovti,ov02a10"; + reg = <0x3d>; + + powerdown-gpios = <&pio 107 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pio 109 GPIO_ACTIVE_LOW>; + + clocks = <&ov02a10_clk>; + clock-names = "eclk"; + clock-frequency = <24000000>; + + rotation = <180>; + + dovdd-supply = <&ov02a10_dovdd>; + avdd-supply = <&ov02a10_avdd>; + dvdd-supply = <&ov02a10_dvdd>; + + port { + wcam_out: endpoint { + link-frequencies = /bits/ 64 <390000000>; + ovti,mipi-clock-voltage = <3>; + remote-endpoint = <&mipi_in_wcam>; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 5c05e7bf7ffd..b3ee9d9cc976 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12856,6 +12856,13 @@ M: Harald Welte S: Maintained F: drivers/char/pcmcia/cm4040_cs.* +OMNIVISION OV02A10 SENSOR DRIVER +M: Dongchun Zhu +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml + OMNIVISION OV13858 SENSOR DRIVER M: Sakari Ailus L: linux-media@vger.kernel.org -- cgit v1.2.3 From 91807efbe8ec7f591085067d9f96a112e015274b Mon Sep 17 00:00:00 2001 From: Dongchun Zhu Date: Wed, 25 Nov 2020 15:17:56 +0100 Subject: media: i2c: add OV02A10 image sensor driver Add a V4L2 sub-device driver for OmniVision OV02A10 image sensor. Signed-off-by: Dongchun Zhu Reviewed-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + drivers/media/i2c/Kconfig | 13 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ov02a10.c | 1013 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1028 insertions(+) create mode 100644 drivers/media/i2c/ov02a10.c (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index b3ee9d9cc976..02437abc94c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12862,6 +12862,7 @@ L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml +F: drivers/media/i2c/ov02a10.c OMNIVISION OV13858 SENSOR DRIVER M: Sakari Ailus diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3787c22767d9..92ff66c34f93 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -825,6 +825,19 @@ config VIDEO_IMX355 To compile this driver as a module, choose M here: the module will be called imx355. +config VIDEO_OV02A10 + tristate "OmniVision OV02A10 sensor support" + depends on VIDEO_V4L2 && I2C + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OV02A10 camera. + + To compile this driver as a module, choose M here: the + module will be called ov02a10. + config VIDEO_OV2640 tristate "OmniVision OV2640 sensor support" depends on VIDEO_V4L2 && I2C diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 5c733394171d..bf9fd1bb6bc9 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o +obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o obj-$(CONFIG_VIDEO_OV2640) += ov2640.o obj-$(CONFIG_VIDEO_OV2680) += ov2680.o obj-$(CONFIG_VIDEO_OV2685) += ov2685.o diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c new file mode 100644 index 000000000000..391718136ade --- /dev/null +++ b/drivers/media/i2c/ov02a10.c @@ -0,0 +1,1013 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OV02A10_ID 0x2509 +#define OV02A10_ID_MASK GENMASK(15, 0) + +#define OV02A10_REG_CHIP_ID 0x02 + +/* Bit[1] vertical upside down */ +/* Bit[0] horizontal mirror */ +#define REG_MIRROR_FLIP_CONTROL 0x3f + +/* Orientation */ +#define REG_MIRROR_FLIP_ENABLE 0x03 + +/* Bit[2:0] MIPI transmission speed select */ +#define TX_SPEED_AREA_SEL 0xa1 +#define OV02A10_MIPI_TX_SPEED_DEFAULT 0x04 + +#define REG_PAGE_SWITCH 0xfd +#define REG_GLOBAL_EFFECTIVE 0x01 +#define REG_ENABLE BIT(0) + +#define REG_SC_CTRL_MODE 0xac +#define SC_CTRL_MODE_STANDBY 0x00 +#define SC_CTRL_MODE_STREAMING 0x01 + +/* Exposure control */ +#define OV02A10_EXP_SHIFT 8 +#define OV02A10_REG_EXPOSURE_H 0x03 +#define OV02A10_REG_EXPOSURE_L 0x04 +#define OV02A10_EXPOSURE_MIN 4 +#define OV02A10_EXPOSURE_MAX_MARGIN 4 +#define OV02A10_EXPOSURE_STEP 1 + +/* Vblanking control */ +#define OV02A10_VTS_SHIFT 8 +#define OV02A10_REG_VTS_H 0x05 +#define OV02A10_REG_VTS_L 0x06 +#define OV02A10_VTS_MAX 0x209f +#define OV02A10_BASE_LINES 1224 + +/* Analog gain control */ +#define OV02A10_REG_GAIN 0x24 +#define OV02A10_GAIN_MIN 0x10 +#define OV02A10_GAIN_MAX 0xf8 +#define OV02A10_GAIN_STEP 0x01 +#define OV02A10_GAIN_DEFAULT 0x40 + +/* Test pattern control */ +#define OV02A10_REG_TEST_PATTERN 0xb6 + +#define HZ_PER_MHZ 1000000L +#define OV02A10_LINK_FREQ_390MHZ (390 * HZ_PER_MHZ) +#define OV02A10_ECLK_FREQ (24 * HZ_PER_MHZ) + +/* Number of lanes supported by this driver */ +#define OV02A10_DATA_LANES 1 + +/* Bits per sample of sensor output */ +#define OV02A10_BITS_PER_SAMPLE 10 + +static const char * const ov02a10_supply_names[] = { + "dovdd", /* Digital I/O power */ + "avdd", /* Analog power */ + "dvdd", /* Digital core power */ +}; + +struct ov02a10_reg { + u8 addr; + u8 val; +}; + +struct ov02a10_reg_list { + u32 num_of_regs; + const struct ov02a10_reg *regs; +}; + +struct ov02a10_mode { + u32 width; + u32 height; + u32 exp_def; + u32 hts_def; + u32 vts_def; + const struct ov02a10_reg_list reg_list; +}; + +struct ov02a10 { + u32 eclk_freq; + /* Indication of MIPI transmission speed select */ + u32 mipi_clock_voltage; + + struct clk *eclk; + struct gpio_desc *pd_gpio; + struct gpio_desc *rst_gpio; + struct regulator_bulk_data supplies[ARRAY_SIZE(ov02a10_supply_names)]; + + bool streaming; + bool upside_down; + + /* + * Serialize control access, get/set format, get selection + * and start streaming. + */ + struct mutex mutex; + struct v4l2_subdev subdev; + struct media_pad pad; + struct v4l2_mbus_framefmt fmt; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *exposure; + + const struct ov02a10_mode *cur_mode; +}; + +static inline struct ov02a10 *to_ov02a10(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ov02a10, subdev); +} + +/* + * eclk 24Mhz + * pclk 39Mhz + * linelength 934(0x3a6) + * framelength 1390(0x56E) + * grabwindow_width 1600 + * grabwindow_height 1200 + * max_framerate 30fps + * mipi_datarate per lane 780Mbps + */ +static const struct ov02a10_reg ov02a10_1600x1200_regs[] = { + {0xfd, 0x01}, + {0xac, 0x00}, + {0xfd, 0x00}, + {0x2f, 0x29}, + {0x34, 0x00}, + {0x35, 0x21}, + {0x30, 0x15}, + {0x33, 0x01}, + {0xfd, 0x01}, + {0x44, 0x00}, + {0x2a, 0x4c}, + {0x2b, 0x1e}, + {0x2c, 0x60}, + {0x25, 0x11}, + {0x03, 0x01}, + {0x04, 0xae}, + {0x09, 0x00}, + {0x0a, 0x02}, + {0x06, 0xa6}, + {0x31, 0x00}, + {0x24, 0x40}, + {0x01, 0x01}, + {0xfb, 0x73}, + {0xfd, 0x01}, + {0x16, 0x04}, + {0x1c, 0x09}, + {0x21, 0x42}, + {0x12, 0x04}, + {0x13, 0x10}, + {0x11, 0x40}, + {0x33, 0x81}, + {0xd0, 0x00}, + {0xd1, 0x01}, + {0xd2, 0x00}, + {0x50, 0x10}, + {0x51, 0x23}, + {0x52, 0x20}, + {0x53, 0x10}, + {0x54, 0x02}, + {0x55, 0x20}, + {0x56, 0x02}, + {0x58, 0x48}, + {0x5d, 0x15}, + {0x5e, 0x05}, + {0x66, 0x66}, + {0x68, 0x68}, + {0x6b, 0x00}, + {0x6c, 0x00}, + {0x6f, 0x40}, + {0x70, 0x40}, + {0x71, 0x0a}, + {0x72, 0xf0}, + {0x73, 0x10}, + {0x75, 0x80}, + {0x76, 0x10}, + {0x84, 0x00}, + {0x85, 0x10}, + {0x86, 0x10}, + {0x87, 0x00}, + {0x8a, 0x22}, + {0x8b, 0x22}, + {0x19, 0xf1}, + {0x29, 0x01}, + {0xfd, 0x01}, + {0x9d, 0x16}, + {0xa0, 0x29}, + {0xa1, 0x04}, + {0xad, 0x62}, + {0xae, 0x00}, + {0xaf, 0x85}, + {0xb1, 0x01}, + {0x8e, 0x06}, + {0x8f, 0x40}, + {0x90, 0x04}, + {0x91, 0xb0}, + {0x45, 0x01}, + {0x46, 0x00}, + {0x47, 0x6c}, + {0x48, 0x03}, + {0x49, 0x8b}, + {0x4a, 0x00}, + {0x4b, 0x07}, + {0x4c, 0x04}, + {0x4d, 0xb7}, + {0xf0, 0x40}, + {0xf1, 0x40}, + {0xf2, 0x40}, + {0xf3, 0x40}, + {0x3f, 0x00}, + {0xfd, 0x01}, + {0x05, 0x00}, + {0x06, 0xa6}, + {0xfd, 0x01}, +}; + +static const char * const ov02a10_test_pattern_menu[] = { + "Disabled", + "Eight Vertical Colour Bars", +}; + +static const s64 link_freq_menu_items[] = { + OV02A10_LINK_FREQ_390MHZ, +}; + +static u64 to_pixel_rate(u32 f_index) +{ + u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV02A10_DATA_LANES; + + do_div(pixel_rate, OV02A10_BITS_PER_SAMPLE); + + return pixel_rate; +} + +static const struct ov02a10_mode supported_modes[] = { + { + .width = 1600, + .height = 1200, + .exp_def = 0x01ae, + .hts_def = 0x03a6, + .vts_def = 0x056e, + .reg_list = { + .num_of_regs = ARRAY_SIZE(ov02a10_1600x1200_regs), + .regs = ov02a10_1600x1200_regs, + }, + }, +}; + +static int ov02a10_write_array(struct ov02a10 *ov02a10, + const struct ov02a10_reg_list *r_list) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + unsigned int i; + int ret; + + for (i = 0; i < r_list->num_of_regs; i++) { + ret = i2c_smbus_write_byte_data(client, r_list->regs[i].addr, + r_list->regs[i].val); + if (ret < 0) + return ret; + } + + return 0; +} + +static void ov02a10_fill_fmt(const struct ov02a10_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->width = mode->width; + fmt->height = mode->height; + fmt->field = V4L2_FIELD_NONE; +} + +static int ov02a10_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ov02a10 *ov02a10 = to_ov02a10(sd); + struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; + struct v4l2_mbus_framefmt *frame_fmt; + int ret = 0; + + mutex_lock(&ov02a10->mutex); + + if (ov02a10->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + ret = -EBUSY; + goto out_unlock; + } + + /* Only one sensor mode supported */ + mbus_fmt->code = ov02a10->fmt.code; + ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + frame_fmt = v4l2_subdev_get_try_format(sd, cfg, 0); + else + frame_fmt = &ov02a10->fmt; + + *frame_fmt = *mbus_fmt; + +out_unlock: + mutex_unlock(&ov02a10->mutex); + return ret; +} + +static int ov02a10_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct ov02a10 *ov02a10 = to_ov02a10(sd); + struct v4l2_mbus_framefmt *mbus_fmt = &fmt->format; + + mutex_lock(&ov02a10->mutex); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + } else { + fmt->format = ov02a10->fmt; + mbus_fmt->code = ov02a10->fmt.code; + ov02a10_fill_fmt(ov02a10->cur_mode, mbus_fmt); + } + + mutex_unlock(&ov02a10->mutex); + + return 0; +} + +static int ov02a10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct ov02a10 *ov02a10 = to_ov02a10(sd); + + if (code->index != 0) + return -EINVAL; + + code->code = ov02a10->fmt.code; + + return 0; +} + +static int ov02a10_enum_frame_sizes(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = supported_modes[fse->index].width; + fse->max_height = supported_modes[fse->index].height; + fse->min_height = supported_modes[fse->index].height; + + return 0; +} + +static int ov02a10_check_sensor_id(struct ov02a10 *ov02a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + u16 chip_id; + int ret; + + /* Validate the chip ID */ + ret = i2c_smbus_read_word_swapped(client, OV02A10_REG_CHIP_ID); + if (ret < 0) + return ret; + + chip_id = le16_to_cpu(ret); + + if ((chip_id & OV02A10_ID_MASK) != OV02A10_ID) { + dev_err(&client->dev, "unexpected sensor id(0x%04x)\n", chip_id); + return -EINVAL; + } + + return 0; +} + +static int ov02a10_power_on(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov02a10 *ov02a10 = to_ov02a10(sd); + int ret; + + gpiod_set_value_cansleep(ov02a10->rst_gpio, 1); + gpiod_set_value_cansleep(ov02a10->pd_gpio, 1); + + ret = clk_prepare_enable(ov02a10->eclk); + if (ret < 0) { + dev_err(dev, "failed to enable eclk\n"); + return ret; + } + + ret = regulator_bulk_enable(ARRAY_SIZE(ov02a10_supply_names), + ov02a10->supplies); + if (ret < 0) { + dev_err(dev, "failed to enable regulators\n"); + goto disable_clk; + } + usleep_range(5000, 6000); + + gpiod_set_value_cansleep(ov02a10->pd_gpio, 0); + usleep_range(5000, 6000); + + gpiod_set_value_cansleep(ov02a10->rst_gpio, 0); + usleep_range(5000, 6000); + + ret = ov02a10_check_sensor_id(ov02a10); + if (ret) + goto disable_regulator; + + return 0; + +disable_regulator: + regulator_bulk_disable(ARRAY_SIZE(ov02a10_supply_names), + ov02a10->supplies); +disable_clk: + clk_disable_unprepare(ov02a10->eclk); + + return ret; +} + +static int ov02a10_power_off(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov02a10 *ov02a10 = to_ov02a10(sd); + + gpiod_set_value_cansleep(ov02a10->rst_gpio, 1); + clk_disable_unprepare(ov02a10->eclk); + gpiod_set_value_cansleep(ov02a10->pd_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(ov02a10_supply_names), + ov02a10->supplies); + + return 0; +} + +static int __ov02a10_start_stream(struct ov02a10 *ov02a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + const struct ov02a10_reg_list *reg_list; + int ret; + + /* Apply default values of current mode */ + reg_list = &ov02a10->cur_mode->reg_list; + ret = ov02a10_write_array(ov02a10, reg_list); + if (ret) + return ret; + + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(ov02a10->subdev.ctrl_handler); + if (ret) + return ret; + + /* Set orientation to 180 degree */ + if (ov02a10->upside_down) { + ret = i2c_smbus_write_byte_data(client, REG_MIRROR_FLIP_CONTROL, + REG_MIRROR_FLIP_ENABLE); + if (ret < 0) { + dev_err(&client->dev, "failed to set orientation\n"); + return ret; + } + ret = i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, + REG_ENABLE); + if (ret < 0) + return ret; + } + + /* Set MIPI TX speed according to DT property */ + if (ov02a10->mipi_clock_voltage != OV02A10_MIPI_TX_SPEED_DEFAULT) { + ret = i2c_smbus_write_byte_data(client, TX_SPEED_AREA_SEL, + ov02a10->mipi_clock_voltage); + if (ret < 0) + return ret; + } + + /* Set stream on register */ + return i2c_smbus_write_byte_data(client, REG_SC_CTRL_MODE, + SC_CTRL_MODE_STREAMING); +} + +static int __ov02a10_stop_stream(struct ov02a10 *ov02a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + + return i2c_smbus_write_byte_data(client, REG_SC_CTRL_MODE, + SC_CTRL_MODE_STANDBY); +} + +static int ov02a10_entity_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .format = { + .width = 1600, + .height = 1200, + } + }; + + ov02a10_set_fmt(sd, cfg, &fmt); + + return 0; +} + +static int ov02a10_s_stream(struct v4l2_subdev *sd, int on) +{ + struct ov02a10 *ov02a10 = to_ov02a10(sd); + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + int ret; + + mutex_lock(&ov02a10->mutex); + + if (ov02a10->streaming == on) + goto unlock_and_return; + + if (on) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto unlock_and_return; + } + + ret = __ov02a10_start_stream(ov02a10); + if (ret) { + __ov02a10_stop_stream(ov02a10); + ov02a10->streaming = !on; + goto err_rpm_put; + } + } else { + __ov02a10_stop_stream(ov02a10); + pm_runtime_put(&client->dev); + } + + ov02a10->streaming = on; + mutex_unlock(&ov02a10->mutex); + + return 0; + +err_rpm_put: + pm_runtime_put(&client->dev); +unlock_and_return: + mutex_unlock(&ov02a10->mutex); + + return ret; +} + +static const struct dev_pm_ops ov02a10_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(ov02a10_power_off, ov02a10_power_on, NULL) +}; + +static int ov02a10_set_exposure(struct ov02a10 *ov02a10, int val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + int ret; + + ret = i2c_smbus_write_byte_data(client, REG_PAGE_SWITCH, REG_ENABLE); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_EXPOSURE_H, + val >> OV02A10_EXP_SHIFT); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_EXPOSURE_L, val); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, + REG_ENABLE); +} + +static int ov02a10_set_gain(struct ov02a10 *ov02a10, int val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + int ret; + + ret = i2c_smbus_write_byte_data(client, REG_PAGE_SWITCH, REG_ENABLE); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_GAIN, val); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, + REG_ENABLE); +} + +static int ov02a10_set_vblank(struct ov02a10 *ov02a10, int val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + u32 vts = val + ov02a10->cur_mode->height - OV02A10_BASE_LINES; + int ret; + + ret = i2c_smbus_write_byte_data(client, REG_PAGE_SWITCH, REG_ENABLE); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_VTS_H, + vts >> OV02A10_VTS_SHIFT); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_VTS_L, vts); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, + REG_ENABLE); +} + +static int ov02a10_set_test_pattern(struct ov02a10 *ov02a10, int pattern) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + int ret; + + ret = i2c_smbus_write_byte_data(client, REG_PAGE_SWITCH, REG_ENABLE); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, OV02A10_REG_TEST_PATTERN, + pattern); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte_data(client, REG_GLOBAL_EFFECTIVE, + REG_ENABLE); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(client, REG_SC_CTRL_MODE, + SC_CTRL_MODE_STREAMING); +} + +static int ov02a10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov02a10 *ov02a10 = container_of(ctrl->handler, + struct ov02a10, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + s64 max_expo; + int ret; + + /* Propagate change of current control to all related controls */ + if (ctrl->id == V4L2_CID_VBLANK) { + /* Update max exposure while meeting expected vblanking */ + max_expo = ov02a10->cur_mode->height + ctrl->val - + OV02A10_EXPOSURE_MAX_MARGIN; + __v4l2_ctrl_modify_range(ov02a10->exposure, + ov02a10->exposure->minimum, max_expo, + ov02a10->exposure->step, + ov02a10->exposure->default_value); + } + + /* V4L2 controls values will be applied only when power is already up */ + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + ret = ov02a10_set_exposure(ov02a10, ctrl->val); + break; + case V4L2_CID_ANALOGUE_GAIN: + ret = ov02a10_set_gain(ov02a10, ctrl->val); + break; + case V4L2_CID_VBLANK: + ret = ov02a10_set_vblank(ov02a10, ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: + ret = ov02a10_set_test_pattern(ov02a10, ctrl->val); + break; + default: + ret = -EINVAL; + break; + }; + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_subdev_video_ops ov02a10_video_ops = { + .s_stream = ov02a10_s_stream, +}; + +static const struct v4l2_subdev_pad_ops ov02a10_pad_ops = { + .init_cfg = ov02a10_entity_init_cfg, + .enum_mbus_code = ov02a10_enum_mbus_code, + .enum_frame_size = ov02a10_enum_frame_sizes, + .get_fmt = ov02a10_get_fmt, + .set_fmt = ov02a10_set_fmt, +}; + +static const struct v4l2_subdev_ops ov02a10_subdev_ops = { + .video = &ov02a10_video_ops, + .pad = &ov02a10_pad_ops, +}; + +static const struct media_entity_operations ov02a10_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_ctrl_ops ov02a10_ctrl_ops = { + .s_ctrl = ov02a10_set_ctrl, +}; + +static int ov02a10_initialize_controls(struct ov02a10 *ov02a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov02a10->subdev); + const struct ov02a10_mode *mode; + struct v4l2_ctrl_handler *handler; + struct v4l2_ctrl *ctrl; + s64 exposure_max; + s64 vblank_def; + s64 pixel_rate; + s64 h_blank; + int ret; + + handler = &ov02a10->ctrl_handler; + mode = ov02a10->cur_mode; + ret = v4l2_ctrl_handler_init(handler, 7); + if (ret) + return ret; + + handler->lock = &ov02a10->mutex; + + ctrl = v4l2_ctrl_new_int_menu(handler, NULL, V4L2_CID_LINK_FREQ, 0, 0, + link_freq_menu_items); + if (ctrl) + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + pixel_rate = to_pixel_rate(0); + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 0, pixel_rate, 1, + pixel_rate); + + h_blank = mode->hts_def - mode->width; + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_HBLANK, h_blank, h_blank, 1, + h_blank); + + vblank_def = mode->vts_def - mode->height; + v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops, V4L2_CID_VBLANK, + vblank_def, OV02A10_VTS_MAX - mode->height, 1, + vblank_def); + + exposure_max = mode->vts_def - 4; + ov02a10->exposure = v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops, + V4L2_CID_EXPOSURE, + OV02A10_EXPOSURE_MIN, + exposure_max, + OV02A10_EXPOSURE_STEP, + mode->exp_def); + + v4l2_ctrl_new_std(handler, &ov02a10_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, OV02A10_GAIN_MIN, + OV02A10_GAIN_MAX, OV02A10_GAIN_STEP, + OV02A10_GAIN_DEFAULT); + + v4l2_ctrl_new_std_menu_items(handler, &ov02a10_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov02a10_test_pattern_menu) - 1, + 0, 0, ov02a10_test_pattern_menu); + + if (handler->error) { + ret = handler->error; + dev_err(&client->dev, "failed to init controls(%d)\n", ret); + goto err_free_handler; + } + + ov02a10->subdev.ctrl_handler = handler; + + return 0; + +err_free_handler: + v4l2_ctrl_handler_free(handler); + + return ret; +} + +static int ov02a10_check_hwcfg(struct device *dev, struct ov02a10 *ov02a10) +{ + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + unsigned int i, j; + u32 clk_volt; + int ret; + + if (!fwnode) + return -EINVAL; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return -ENXIO; + + 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] == + bus_cfg.link_frequencies[j]) + break; + } + + if (j == bus_cfg.nr_of_link_frequencies) { + dev_err(dev, "no link frequency %lld supported\n", + link_freq_menu_items[i]); + ret = -EINVAL; + break; + } + } + + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int ov02a10_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct ov02a10 *ov02a10; + unsigned int i; + unsigned int rotation; + int ret; + + ov02a10 = devm_kzalloc(dev, sizeof(*ov02a10), GFP_KERNEL); + if (!ov02a10) + return -ENOMEM; + + ret = ov02a10_check_hwcfg(dev, ov02a10); + if (ret) + return dev_err_probe(dev, ret, + "failed to check HW configuration\n"); + + v4l2_i2c_subdev_init(&ov02a10->subdev, client, &ov02a10_subdev_ops); + + ov02a10->mipi_clock_voltage = OV02A10_MIPI_TX_SPEED_DEFAULT; + ov02a10->fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; + + /* Optional indication of physical rotation of sensor */ + rotation = 0; + device_property_read_u32(dev, "rotation", &rotation); + if (rotation == 180) { + ov02a10->upside_down = true; + ov02a10->fmt.code = MEDIA_BUS_FMT_SRGGB10_1X10; + } + + ov02a10->eclk = devm_clk_get(dev, "eclk"); + if (IS_ERR(ov02a10->eclk)) + return dev_err_probe(dev, PTR_ERR(ov02a10->eclk), + "failed to get eclk\n"); + + ret = device_property_read_u32(dev, "clock-frequency", + &ov02a10->eclk_freq); + if (ret < 0) + return dev_err_probe(dev, ret, + "failed to get eclk frequency\n"); + + ret = clk_set_rate(ov02a10->eclk, ov02a10->eclk_freq); + if (ret < 0) + return dev_err_probe(dev, ret, + "failed to set eclk frequency (24MHz)\n"); + + if (clk_get_rate(ov02a10->eclk) != OV02A10_ECLK_FREQ) + dev_warn(dev, "eclk mismatched, mode is based on 24MHz\n"); + + ov02a10->pd_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_HIGH); + if (IS_ERR(ov02a10->pd_gpio)) + return dev_err_probe(dev, PTR_ERR(ov02a10->pd_gpio), + "failed to get powerdown-gpios\n"); + + ov02a10->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ov02a10->rst_gpio)) + return dev_err_probe(dev, PTR_ERR(ov02a10->rst_gpio), + "failed to get reset-gpios\n"); + + for (i = 0; i < ARRAY_SIZE(ov02a10_supply_names); i++) + ov02a10->supplies[i].supply = ov02a10_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov02a10_supply_names), + ov02a10->supplies); + if (ret) + return dev_err_probe(dev, ret, "failed to get regulators\n"); + + mutex_init(&ov02a10->mutex); + + /* Set default mode */ + ov02a10->cur_mode = &supported_modes[0]; + + ret = ov02a10_initialize_controls(ov02a10); + if (ret) { + dev_err_probe(dev, ret, "failed to initialize controls\n"); + goto err_destroy_mutex; + } + + /* Initialize subdev */ + ov02a10->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + ov02a10->subdev.entity.ops = &ov02a10_subdev_entity_ops; + ov02a10->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov02a10->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&ov02a10->subdev.entity, 1, &ov02a10->pad); + if (ret < 0) { + dev_err_probe(dev, ret, "failed to initialize entity pads\n"); + goto err_free_handler; + } + + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = ov02a10_power_on(dev); + if (ret < 0) { + dev_err_probe(dev, ret, "failed to power on\n"); + goto err_clean_entity; + } + } + + ret = v4l2_async_register_subdev(&ov02a10->subdev); + if (ret) { + dev_err_probe(dev, ret, "failed to register V4L2 subdev\n"); + goto err_power_off; + } + + return 0; + +err_power_off: + if (pm_runtime_enabled(dev)) + pm_runtime_disable(dev); + else + ov02a10_power_off(dev); +err_clean_entity: + media_entity_cleanup(&ov02a10->subdev.entity); +err_free_handler: + v4l2_ctrl_handler_free(ov02a10->subdev.ctrl_handler); +err_destroy_mutex: + mutex_destroy(&ov02a10->mutex); + + return ret; +} + +static int ov02a10_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov02a10 *ov02a10 = to_ov02a10(sd); + + v4l2_async_unregister_subdev(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)) + ov02a10_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + mutex_destroy(&ov02a10->mutex); + + return 0; +} + +static const struct of_device_id ov02a10_of_match[] = { + { .compatible = "ovti,ov02a10" }, + {} +}; +MODULE_DEVICE_TABLE(of, ov02a10_of_match); + +static struct i2c_driver ov02a10_i2c_driver = { + .driver = { + .name = "ov02a10", + .pm = &ov02a10_pm_ops, + .of_match_table = ov02a10_of_match, + }, + .probe_new = &ov02a10_probe, + .remove = &ov02a10_remove, +}; +module_i2c_driver(ov02a10_i2c_driver); + +MODULE_AUTHOR("Dongchun Zhu "); +MODULE_DESCRIPTION("OmniVision OV02A10 sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0b6a3bf8f5630eced6bf04b3416ebaadc8d153cf Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 30 Nov 2020 23:52:21 +0100 Subject: media: stop pretending to maintain cafe and ov7670 It's been a long time since I could credibly claim to be maintaining these drivers; I'm not even sure my hardware works anymore. Mark them orphan. Signed-off-by: Jonathan Corbet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 02437abc94c9..dce790484d29 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3862,9 +3862,8 @@ T: git git://linuxtv.org/media_tree.git F: drivers/media/radio/radio-cadet* CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER -M: Jonathan Corbet L: linux-media@vger.kernel.org -S: Maintained +S: Orphan T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/cafe_ccic* F: drivers/media/platform/marvell-ccic/ @@ -12934,9 +12933,8 @@ T: git git://linuxtv.org/media_tree.git F: drivers/media/i2c/ov5695.c OMNIVISION OV7670 SENSOR DRIVER -M: Jonathan Corbet L: linux-media@vger.kernel.org -S: Maintained +S: Orphan T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/ov7670.txt F: drivers/media/i2c/ov7670.c -- cgit v1.2.3 From 9e05bbac43ebfc2fd1ff95e072730ceed807d149 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 27 May 2020 23:59:40 +0200 Subject: media: smiapp-pll: Rename as ccs-pll MIPI CCS replaces SMIA and SMIA++ as the current standard. CCS brings new features while existing functionality will be supported. Rename the smiapp-pll as ccs-pll accordingly. Also add Intel copyright to the files. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 4 +- drivers/media/i2c/Kconfig | 2 +- drivers/media/i2c/Makefile | 2 +- drivers/media/i2c/ccs-pll.c | 480 +++++++++++++++++++++++++++++++++++++ drivers/media/i2c/ccs-pll.h | 99 ++++++++ drivers/media/i2c/ccs/Kconfig | 2 +- drivers/media/i2c/ccs/ccs-core.c | 18 +- drivers/media/i2c/ccs/ccs-quirk.c | 2 +- drivers/media/i2c/ccs/ccs.h | 4 +- drivers/media/i2c/smiapp-pll.c | 482 -------------------------------------- drivers/media/i2c/smiapp-pll.h | 99 -------- 11 files changed, 596 insertions(+), 598 deletions(-) create mode 100644 drivers/media/i2c/ccs-pll.c create mode 100644 drivers/media/i2c/ccs-pll.h delete mode 100644 drivers/media/i2c/smiapp-pll.c delete mode 100644 drivers/media/i2c/smiapp-pll.h (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index dce790484d29..6380b54bf726 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11635,9 +11635,9 @@ L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml F: Documentation/driver-api/media/drivers/ccs/ +F: drivers/media/i2c/ccs-pll.c +F: drivers/media/i2c/ccs-pll.h F: drivers/media/i2c/ccs/ -F: drivers/media/i2c/smiapp-pll.c -F: drivers/media/i2c/smiapp-pll.h F: include/uapi/linux/smiapp.h MIPS diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 92ff66c34f93..2b9d81e4794a 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -722,7 +722,7 @@ menu "Camera sensor devices" config VIDEO_APTINA_PLL tristate -config VIDEO_SMIAPP_PLL +config VIDEO_CCS_PLL tristate config VIDEO_HI556 diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index bf9fd1bb6bc9..a3149dce21bb 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -106,7 +106,7 @@ obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o obj-$(CONFIG_VIDEO_LM3560) += lm3560.o obj-$(CONFIG_VIDEO_LM3646) += lm3646.o -obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o +obj-$(CONFIG_VIDEO_CCS_PLL) += ccs-pll.o obj-$(CONFIG_VIDEO_AK881X) += ak881x.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_I2C) += video-i2c.o diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c new file mode 100644 index 000000000000..d2f0f7375f5c --- /dev/null +++ b/drivers/media/i2c/ccs-pll.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * drivers/media/i2c/ccs-pll.c + * + * Generic MIPI CCS/SMIA/SMIA++ PLL calculator + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2011--2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#include +#include +#include +#include + +#include "ccs-pll.h" + +/* Return an even number or one. */ +static inline uint32_t clk_div_even(uint32_t a) +{ + return max_t(uint32_t, 1, a & ~1); +} + +/* Return an even number or one. */ +static inline uint32_t clk_div_even_up(uint32_t a) +{ + if (a == 1) + return 1; + return (a + 1) & ~1; +} + +static inline uint32_t is_one_or_even(uint32_t a) +{ + if (a == 1) + return 1; + if (a & 1) + return 0; + + return 1; +} + +static int bounds_check(struct device *dev, uint32_t val, + uint32_t min, uint32_t max, char *str) +{ + if (val >= min && val <= max) + return 0; + + dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max); + + return -EINVAL; +} + +static void print_pll(struct device *dev, struct ccs_pll *pll) +{ + dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->pre_pll_clk_div); + dev_dbg(dev, "pll_multiplier \t%u\n", pll->pll_multiplier); + if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div); + dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div); + } + dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt.sys_clk_div); + dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt.pix_clk_div); + + dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz); + dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz); + dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz); + if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)) { + dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n", + pll->op.sys_clk_freq_hz); + dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n", + pll->op.pix_clk_freq_hz); + } + dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz); + dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz); +} + +static int check_all_bounds(struct device *dev, + const struct ccs_pll_limits *limits, + const struct ccs_pll_branch_limits *op_limits, + struct ccs_pll *pll, struct ccs_pll_branch *op_pll) +{ + int rval; + + rval = bounds_check(dev, pll->pll_ip_clk_freq_hz, + limits->min_pll_ip_freq_hz, + limits->max_pll_ip_freq_hz, + "pll_ip_clk_freq_hz"); + if (!rval) + rval = bounds_check( + dev, pll->pll_multiplier, + limits->min_pll_multiplier, limits->max_pll_multiplier, + "pll_multiplier"); + if (!rval) + rval = bounds_check( + dev, pll->pll_op_clk_freq_hz, + limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz, + "pll_op_clk_freq_hz"); + if (!rval) + rval = bounds_check( + dev, op_pll->sys_clk_div, + op_limits->min_sys_clk_div, op_limits->max_sys_clk_div, + "op_sys_clk_div"); + if (!rval) + rval = bounds_check( + dev, op_pll->sys_clk_freq_hz, + op_limits->min_sys_clk_freq_hz, + op_limits->max_sys_clk_freq_hz, + "op_sys_clk_freq_hz"); + if (!rval) + rval = bounds_check( + dev, op_pll->pix_clk_freq_hz, + op_limits->min_pix_clk_freq_hz, + op_limits->max_pix_clk_freq_hz, + "op_pix_clk_freq_hz"); + + /* + * If there are no OP clocks, the VT clocks are contained in + * the OP clock struct. + */ + if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) + return rval; + + if (!rval) + rval = bounds_check( + dev, pll->vt.sys_clk_freq_hz, + limits->vt.min_sys_clk_freq_hz, + limits->vt.max_sys_clk_freq_hz, + "vt_sys_clk_freq_hz"); + if (!rval) + rval = bounds_check( + dev, pll->vt.pix_clk_freq_hz, + limits->vt.min_pix_clk_freq_hz, + limits->vt.max_pix_clk_freq_hz, + "vt_pix_clk_freq_hz"); + + return rval; +} + +/* + * Heuristically guess the PLL tree for a given common multiplier and + * divisor. Begin with the operational timing and continue to video + * timing once operational timing has been verified. + * + * @mul is the PLL multiplier and @div is the common divisor + * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL + * multiplier will be a multiple of @mul. + * + * @return Zero on success, error code on error. + */ +static int +__ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, + const struct ccs_pll_branch_limits *op_limits, + struct ccs_pll *pll, struct ccs_pll_branch *op_pll, + uint32_t mul, uint32_t div, uint32_t lane_op_clock_ratio) +{ + uint32_t sys_div; + uint32_t best_pix_div = INT_MAX >> 1; + uint32_t vt_op_binning_div; + /* + * Higher multipliers (and divisors) are often required than + * necessitated by the external clock and the output clocks. + * There are limits for all values in the clock tree. These + * are the minimum and maximum multiplier for mul. + */ + uint32_t more_mul_min, more_mul_max; + uint32_t more_mul_factor; + uint32_t min_vt_div, max_vt_div, vt_div; + uint32_t min_sys_div, max_sys_div; + unsigned int i; + + /* + * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be + * too high. + */ + dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div); + + /* Don't go above max pll multiplier. */ + more_mul_max = limits->max_pll_multiplier / mul; + dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n", + more_mul_max); + /* Don't go above max pll op frequency. */ + more_mul_max = + min_t(uint32_t, + more_mul_max, + limits->max_pll_op_freq_hz + / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul)); + dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n", + more_mul_max); + /* Don't go above the division capability of op sys clock divider. */ + more_mul_max = min(more_mul_max, + op_limits->max_sys_clk_div * pll->pre_pll_clk_div + / div); + dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", + more_mul_max); + /* Ensure we won't go above min_pll_multiplier. */ + more_mul_max = min(more_mul_max, + DIV_ROUND_UP(limits->max_pll_multiplier, mul)); + dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", + more_mul_max); + + /* Ensure we won't go below min_pll_op_freq_hz. */ + more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz, + pll->ext_clk_freq_hz / pll->pre_pll_clk_div + * mul); + dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n", + more_mul_min); + /* Ensure we won't go below min_pll_multiplier. */ + more_mul_min = max(more_mul_min, + DIV_ROUND_UP(limits->min_pll_multiplier, mul)); + dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n", + more_mul_min); + + if (more_mul_min > more_mul_max) { + dev_dbg(dev, + "unable to compute more_mul_min and more_mul_max\n"); + return -EINVAL; + } + + more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div; + dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor); + more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div); + dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n", + more_mul_factor); + i = roundup(more_mul_min, more_mul_factor); + if (!is_one_or_even(i)) + i <<= 1; + + dev_dbg(dev, "final more_mul: %u\n", i); + if (i > more_mul_max) { + dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max); + return -EINVAL; + } + + pll->pll_multiplier = mul * i; + op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div; + dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div); + + pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz + / pll->pre_pll_clk_div; + + pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz + * pll->pll_multiplier; + + /* Derive pll_op_clk_freq_hz. */ + op_pll->sys_clk_freq_hz = + pll->pll_op_clk_freq_hz / op_pll->sys_clk_div; + + op_pll->pix_clk_div = pll->bits_per_pixel; + dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div); + + op_pll->pix_clk_freq_hz = + op_pll->sys_clk_freq_hz / op_pll->pix_clk_div; + + if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { + /* No OP clocks --- VT clocks are used instead. */ + goto out_skip_vt_calc; + } + + /* + * Some sensors perform analogue binning and some do this + * digitally. The ones doing this digitally can be roughly be + * found out using this formula. The ones doing this digitally + * should run at higher clock rate, so smaller divisor is used + * on video timing side. + */ + if (limits->min_line_length_pck_bin > limits->min_line_length_pck + / pll->binning_horizontal) + vt_op_binning_div = pll->binning_horizontal; + else + vt_op_binning_div = 1; + dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div); + + /* + * Profile 2 supports vt_pix_clk_div E [4, 10] + * + * Horizontal binning can be used as a base for difference in + * divisors. One must make sure that horizontal blanking is + * enough to accommodate the CSI-2 sync codes. + * + * Take scaling factor into account as well. + * + * Find absolute limits for the factor of vt divider. + */ + dev_dbg(dev, "scale_m: %u\n", pll->scale_m); + min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div + * pll->scale_n, + lane_op_clock_ratio * vt_op_binning_div + * pll->scale_m); + + /* Find smallest and biggest allowed vt divisor. */ + dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); + min_vt_div = max(min_vt_div, + DIV_ROUND_UP(pll->pll_op_clk_freq_hz, + limits->vt.max_pix_clk_freq_hz)); + dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n", + min_vt_div); + min_vt_div = max_t(uint32_t, min_vt_div, + limits->vt.min_pix_clk_div + * limits->vt.min_sys_clk_div); + dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div); + + max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div; + dev_dbg(dev, "max_vt_div: %u\n", max_vt_div); + max_vt_div = min(max_vt_div, + DIV_ROUND_UP(pll->pll_op_clk_freq_hz, + limits->vt.min_pix_clk_freq_hz)); + dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", + max_vt_div); + + /* + * Find limitsits for sys_clk_div. Not all values are possible + * with all values of pix_clk_div. + */ + min_sys_div = limits->vt.min_sys_clk_div; + dev_dbg(dev, "min_sys_div: %u\n", min_sys_div); + min_sys_div = max(min_sys_div, + DIV_ROUND_UP(min_vt_div, + limits->vt.max_pix_clk_div)); + dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); + min_sys_div = max(min_sys_div, + pll->pll_op_clk_freq_hz + / limits->vt.max_sys_clk_freq_hz); + dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); + min_sys_div = clk_div_even_up(min_sys_div); + dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div); + + max_sys_div = limits->vt.max_sys_clk_div; + dev_dbg(dev, "max_sys_div: %u\n", max_sys_div); + max_sys_div = min(max_sys_div, + DIV_ROUND_UP(max_vt_div, + limits->vt.min_pix_clk_div)); + dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); + max_sys_div = min(max_sys_div, + DIV_ROUND_UP(pll->pll_op_clk_freq_hz, + limits->vt.min_pix_clk_freq_hz)); + dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); + + /* + * Find pix_div such that a legal pix_div * sys_div results + * into a value which is not smaller than div, the desired + * divisor. + */ + for (vt_div = min_vt_div; vt_div <= max_vt_div; + vt_div += 2 - (vt_div & 1)) { + for (sys_div = min_sys_div; + sys_div <= max_sys_div; + sys_div += 2 - (sys_div & 1)) { + uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div); + + if (pix_div < limits->vt.min_pix_clk_div + || pix_div > limits->vt.max_pix_clk_div) { + dev_dbg(dev, + "pix_div %u too small or too big (%u--%u)\n", + pix_div, + limits->vt.min_pix_clk_div, + limits->vt.max_pix_clk_div); + continue; + } + + /* Check if this one is better. */ + if (pix_div * sys_div + <= roundup(min_vt_div, best_pix_div)) + best_pix_div = pix_div; + } + if (best_pix_div < INT_MAX >> 1) + break; + } + + pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); + pll->vt.pix_clk_div = best_pix_div; + + pll->vt.sys_clk_freq_hz = + pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div; + pll->vt.pix_clk_freq_hz = + pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div; + +out_skip_vt_calc: + pll->pixel_rate_csi = + op_pll->pix_clk_freq_hz * lane_op_clock_ratio; + pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz; + + return check_all_bounds(dev, limits, op_limits, pll, op_pll); +} + +int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, + struct ccs_pll *pll) +{ + const struct ccs_pll_branch_limits *op_limits = &limits->op; + struct ccs_pll_branch *op_pll = &pll->op; + uint16_t min_pre_pll_clk_div; + uint16_t max_pre_pll_clk_div; + uint32_t lane_op_clock_ratio; + uint32_t mul, div; + unsigned int i; + int rval = -EINVAL; + + if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { + /* + * If there's no OP PLL at all, use the VT values + * instead. The OP values are ignored for the rest of + * the PLL calculation. + */ + op_limits = &limits->vt; + op_pll = &pll->vt; + } + + if (pll->flags & CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE) + lane_op_clock_ratio = pll->csi2.lanes; + else + lane_op_clock_ratio = 1; + dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio); + + dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, + pll->binning_vertical); + + switch (pll->bus_type) { + case CCS_PLL_BUS_TYPE_CSI2: + /* CSI transfers 2 bits per clock per lane; thus times 2 */ + pll->pll_op_clk_freq_hz = pll->link_freq * 2 + * (pll->csi2.lanes / lane_op_clock_ratio); + break; + case CCS_PLL_BUS_TYPE_PARALLEL: + pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel + / DIV_ROUND_UP(pll->bits_per_pixel, + pll->parallel.bus_width); + break; + default: + return -EINVAL; + } + + /* Figure out limits for pre-pll divider based on extclk */ + dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n", + limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); + max_pre_pll_clk_div = + min_t(uint16_t, limits->max_pre_pll_clk_div, + clk_div_even(pll->ext_clk_freq_hz / + limits->min_pll_ip_freq_hz)); + min_pre_pll_clk_div = + max_t(uint16_t, limits->min_pre_pll_clk_div, + clk_div_even_up( + DIV_ROUND_UP(pll->ext_clk_freq_hz, + limits->max_pll_ip_freq_hz))); + dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n", + min_pre_pll_clk_div, max_pre_pll_clk_div); + + i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); + mul = div_u64(pll->pll_op_clk_freq_hz, i); + div = pll->ext_clk_freq_hz / i; + dev_dbg(dev, "mul %u / div %u\n", mul, div); + + min_pre_pll_clk_div = + max_t(uint16_t, min_pre_pll_clk_div, + clk_div_even_up( + DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, + limits->max_pll_op_freq_hz))); + dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n", + min_pre_pll_clk_div, max_pre_pll_clk_div); + + for (pll->pre_pll_clk_div = min_pre_pll_clk_div; + pll->pre_pll_clk_div <= max_pre_pll_clk_div; + pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) { + rval = __ccs_pll_calculate(dev, limits, op_limits, pll, op_pll, + mul, div, lane_op_clock_ratio); + if (rval) + continue; + + print_pll(dev, pll); + return 0; + } + + dev_dbg(dev, "unable to compute pre_pll divisor\n"); + + return rval; +} +EXPORT_SYMBOL_GPL(ccs_pll_calculate); + +MODULE_AUTHOR("Sakari Ailus "); +MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ PLL calculator"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/ccs-pll.h b/drivers/media/i2c/ccs-pll.h new file mode 100644 index 000000000000..88d641ee3fa1 --- /dev/null +++ b/drivers/media/i2c/ccs-pll.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * drivers/media/i2c/ccs-pll.h + * + * Generic MIPI CCS/SMIA/SMIA++ PLL calculator + * + * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2012 Nokia Corporation + * Contact: Sakari Ailus + */ + +#ifndef CCS_PLL_H +#define CCS_PLL_H + +/* CSI-2 or CCP-2 */ +#define CCS_PLL_BUS_TYPE_CSI2 0x00 +#define CCS_PLL_BUS_TYPE_PARALLEL 0x01 + +/* op pix clock is for all lanes in total normally */ +#define CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) +#define CCS_PLL_FLAG_NO_OP_CLOCKS (1 << 1) + +struct ccs_pll_branch { + uint16_t sys_clk_div; + uint16_t pix_clk_div; + uint32_t sys_clk_freq_hz; + uint32_t pix_clk_freq_hz; +}; + +struct ccs_pll { + /* input values */ + uint8_t bus_type; + union { + struct { + uint8_t lanes; + } csi2; + struct { + uint8_t bus_width; + } parallel; + }; + unsigned long flags; + uint8_t binning_horizontal; + uint8_t binning_vertical; + uint8_t scale_m; + uint8_t scale_n; + uint8_t bits_per_pixel; + uint32_t link_freq; + uint32_t ext_clk_freq_hz; + + /* output values */ + uint16_t pre_pll_clk_div; + uint16_t pll_multiplier; + uint32_t pll_ip_clk_freq_hz; + uint32_t pll_op_clk_freq_hz; + struct ccs_pll_branch vt; + struct ccs_pll_branch op; + + uint32_t pixel_rate_csi; + uint32_t pixel_rate_pixel_array; +}; + +struct ccs_pll_branch_limits { + uint16_t min_sys_clk_div; + uint16_t max_sys_clk_div; + uint32_t min_sys_clk_freq_hz; + uint32_t max_sys_clk_freq_hz; + uint16_t min_pix_clk_div; + uint16_t max_pix_clk_div; + uint32_t min_pix_clk_freq_hz; + uint32_t max_pix_clk_freq_hz; +}; + +struct ccs_pll_limits { + /* Strict PLL limits */ + uint32_t min_ext_clk_freq_hz; + uint32_t max_ext_clk_freq_hz; + uint16_t min_pre_pll_clk_div; + uint16_t max_pre_pll_clk_div; + uint32_t min_pll_ip_freq_hz; + uint32_t max_pll_ip_freq_hz; + uint16_t min_pll_multiplier; + uint16_t max_pll_multiplier; + uint32_t min_pll_op_freq_hz; + uint32_t max_pll_op_freq_hz; + + struct ccs_pll_branch_limits vt; + struct ccs_pll_branch_limits op; + + /* Other relevant limits */ + uint32_t min_line_length_pck_bin; + uint32_t min_line_length_pck; +}; + +struct device; + +int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *limits, + struct ccs_pll *pll); + +#endif /* CCS_PLL_H */ diff --git a/drivers/media/i2c/ccs/Kconfig b/drivers/media/i2c/ccs/Kconfig index b4f8b10da420..59f35b33ddc1 100644 --- a/drivers/media/i2c/ccs/Kconfig +++ b/drivers/media/i2c/ccs/Kconfig @@ -4,7 +4,7 @@ config VIDEO_CCS depends on I2C && VIDEO_V4L2 && HAVE_CLK select MEDIA_CONTROLLER select VIDEO_V4L2_SUBDEV_API - select VIDEO_SMIAPP_PLL + select VIDEO_CCS_PLL select V4L2_FWNODE help This is a generic driver for MIPI CCS, SMIA++ and SMIA compliant diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 074b246538d2..6c8528e6ac96 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -363,7 +363,7 @@ static int ccs_read_frame_fmt(struct ccs_sensor *sensor) static int ccs_pll_configure(struct ccs_sensor *sensor) { - struct smiapp_pll *pll = &sensor->pll; + struct ccs_pll *pll = &sensor->pll; int rval; rval = ccs_write(sensor, VT_PIX_CLK_DIV, pll->vt.pix_clk_div); @@ -386,7 +386,7 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) rval = ccs_write(sensor, REQUESTED_LINK_RATE, DIV_ROUND_UP(pll->op.sys_clk_freq_hz, 1000000 / 256 / 256)); - if (rval < 0 || sensor->pll.flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) + if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS) return rval; rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op.pix_clk_div); @@ -396,10 +396,10 @@ static int ccs_pll_configure(struct ccs_sensor *sensor) return ccs_write(sensor, OP_SYS_CLK_DIV, pll->op.sys_clk_div); } -static int ccs_pll_try(struct ccs_sensor *sensor, struct smiapp_pll *pll) +static int ccs_pll_try(struct ccs_sensor *sensor, struct ccs_pll *pll) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct smiapp_pll_limits lim = { + struct ccs_pll_limits lim = { .min_pre_pll_clk_div = CCS_LIM(sensor, MIN_PRE_PLL_CLK_DIV), .max_pre_pll_clk_div = CCS_LIM(sensor, MAX_PRE_PLL_CLK_DIV), .min_pll_ip_freq_hz = CCS_LIM(sensor, MIN_PLL_IP_CLK_FREQ_MHZ), @@ -431,12 +431,12 @@ static int ccs_pll_try(struct ccs_sensor *sensor, struct smiapp_pll *pll) .min_line_length_pck = CCS_LIM(sensor, MIN_LINE_LENGTH_PCK), }; - return smiapp_pll_calculate(&client->dev, &lim, pll); + return ccs_pll_calculate(&client->dev, &lim, pll); } static int ccs_pll_update(struct ccs_sensor *sensor) { - struct smiapp_pll *pll = &sensor->pll; + struct ccs_pll *pll = &sensor->pll; int rval; pll->binning_horizontal = sensor->binning_horizontal; @@ -829,7 +829,7 @@ static void ccs_free_controls(struct ccs_sensor *sensor) static int ccs_get_mbus_formats(struct ccs_sensor *sensor) { struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); - struct smiapp_pll *pll = &sensor->pll; + struct ccs_pll *pll = &sensor->pll; u8 compressed_max_bpp = 0; unsigned int type, n; unsigned int i, pixel_order; @@ -3155,7 +3155,7 @@ static int ccs_probe(struct i2c_client *client) !CCS_LIM(sensor, MIN_OP_PIX_CLK_DIV) || !CCS_LIM(sensor, MAX_OP_PIX_CLK_DIV)) { /* No OP clock branch */ - sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; + sensor->pll.flags |= CCS_PLL_FLAG_NO_OP_CLOCKS; } else if (CCS_LIM(sensor, SCALING_CAPABILITY) != CCS_SCALING_CAPABILITY_NONE || CCS_LIM(sensor, DIGITAL_CROP_CAPABILITY) @@ -3172,7 +3172,7 @@ static int ccs_probe(struct i2c_client *client) sensor->scale_m = CCS_LIM(sensor, SCALER_N_MIN); /* prepare PLL configuration input values */ - sensor->pll.bus_type = SMIAPP_PLL_BUS_TYPE_CSI2; + sensor->pll.bus_type = CCS_PLL_BUS_TYPE_CSI2; sensor->pll.csi2.lanes = sensor->hwcfg.lanes; sensor->pll.ext_clk_freq_hz = sensor->hwcfg.ext_clk; sensor->pll.scale_n = CCS_LIM(sensor, SCALER_N_MIN); diff --git a/drivers/media/i2c/ccs/ccs-quirk.c b/drivers/media/i2c/ccs/ccs-quirk.c index 07c5733b4244..8b4fa60044b2 100644 --- a/drivers/media/i2c/ccs/ccs-quirk.c +++ b/drivers/media/i2c/ccs/ccs-quirk.c @@ -190,7 +190,7 @@ static int jt8ev1_post_streamoff(struct ccs_sensor *sensor) static int jt8ev1_init(struct ccs_sensor *sensor) { - sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; + sensor->pll.flags |= CCS_PLL_FLAG_OP_PIX_CLOCK_PER_LANE; return 0; } diff --git a/drivers/media/i2c/ccs/ccs.h b/drivers/media/i2c/ccs/ccs.h index f60d1801c469..c8a9f4ee093e 100644 --- a/drivers/media/i2c/ccs/ccs.h +++ b/drivers/media/i2c/ccs/ccs.h @@ -21,7 +21,7 @@ #include "ccs-quirk.h" #include "ccs-regs.h" #include "ccs-reg-access.h" -#include "../smiapp-pll.h" +#include "../ccs-pll.h" #include "smiapp-reg-defs.h" /* @@ -256,7 +256,7 @@ struct ccs_sensor { struct ccs_module_info minfo; - struct smiapp_pll pll; + struct ccs_pll pll; /* Is a default format supported for a given BPP? */ unsigned long *valid_link_freqs; diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c deleted file mode 100644 index 690abe8cbdb2..000000000000 --- a/drivers/media/i2c/smiapp-pll.c +++ /dev/null @@ -1,482 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/media/i2c/smiapp-pll.c - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2011--2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#include -#include -#include -#include - -#include "smiapp-pll.h" - -/* Return an even number or one. */ -static inline uint32_t clk_div_even(uint32_t a) -{ - return max_t(uint32_t, 1, a & ~1); -} - -/* Return an even number or one. */ -static inline uint32_t clk_div_even_up(uint32_t a) -{ - if (a == 1) - return 1; - return (a + 1) & ~1; -} - -static inline uint32_t is_one_or_even(uint32_t a) -{ - if (a == 1) - return 1; - if (a & 1) - return 0; - - return 1; -} - -static int bounds_check(struct device *dev, uint32_t val, - uint32_t min, uint32_t max, char *str) -{ - if (val >= min && val <= max) - return 0; - - dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max); - - return -EINVAL; -} - -static void print_pll(struct device *dev, struct smiapp_pll *pll) -{ - dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->pre_pll_clk_div); - dev_dbg(dev, "pll_multiplier \t%u\n", pll->pll_multiplier); - if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { - dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div); - dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div); - } - dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt.sys_clk_div); - dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt.pix_clk_div); - - dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz); - dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz); - dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz); - if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) { - dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n", - pll->op.sys_clk_freq_hz); - dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n", - pll->op.pix_clk_freq_hz); - } - dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz); - dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz); -} - -static int check_all_bounds(struct device *dev, - const struct smiapp_pll_limits *limits, - const struct smiapp_pll_branch_limits *op_limits, - struct smiapp_pll *pll, - struct smiapp_pll_branch *op_pll) -{ - int rval; - - rval = bounds_check(dev, pll->pll_ip_clk_freq_hz, - limits->min_pll_ip_freq_hz, - limits->max_pll_ip_freq_hz, - "pll_ip_clk_freq_hz"); - if (!rval) - rval = bounds_check( - dev, pll->pll_multiplier, - limits->min_pll_multiplier, limits->max_pll_multiplier, - "pll_multiplier"); - if (!rval) - rval = bounds_check( - dev, pll->pll_op_clk_freq_hz, - limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz, - "pll_op_clk_freq_hz"); - if (!rval) - rval = bounds_check( - dev, op_pll->sys_clk_div, - op_limits->min_sys_clk_div, op_limits->max_sys_clk_div, - "op_sys_clk_div"); - if (!rval) - rval = bounds_check( - dev, op_pll->sys_clk_freq_hz, - op_limits->min_sys_clk_freq_hz, - op_limits->max_sys_clk_freq_hz, - "op_sys_clk_freq_hz"); - if (!rval) - rval = bounds_check( - dev, op_pll->pix_clk_freq_hz, - op_limits->min_pix_clk_freq_hz, - op_limits->max_pix_clk_freq_hz, - "op_pix_clk_freq_hz"); - - /* - * If there are no OP clocks, the VT clocks are contained in - * the OP clock struct. - */ - if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) - return rval; - - if (!rval) - rval = bounds_check( - dev, pll->vt.sys_clk_freq_hz, - limits->vt.min_sys_clk_freq_hz, - limits->vt.max_sys_clk_freq_hz, - "vt_sys_clk_freq_hz"); - if (!rval) - rval = bounds_check( - dev, pll->vt.pix_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz, - limits->vt.max_pix_clk_freq_hz, - "vt_pix_clk_freq_hz"); - - return rval; -} - -/* - * Heuristically guess the PLL tree for a given common multiplier and - * divisor. Begin with the operational timing and continue to video - * timing once operational timing has been verified. - * - * @mul is the PLL multiplier and @div is the common divisor - * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL - * multiplier will be a multiple of @mul. - * - * @return Zero on success, error code on error. - */ -static int __smiapp_pll_calculate( - struct device *dev, const struct smiapp_pll_limits *limits, - const struct smiapp_pll_branch_limits *op_limits, - struct smiapp_pll *pll, struct smiapp_pll_branch *op_pll, uint32_t mul, - uint32_t div, uint32_t lane_op_clock_ratio) -{ - uint32_t sys_div; - uint32_t best_pix_div = INT_MAX >> 1; - uint32_t vt_op_binning_div; - /* - * Higher multipliers (and divisors) are often required than - * necessitated by the external clock and the output clocks. - * There are limits for all values in the clock tree. These - * are the minimum and maximum multiplier for mul. - */ - uint32_t more_mul_min, more_mul_max; - uint32_t more_mul_factor; - uint32_t min_vt_div, max_vt_div, vt_div; - uint32_t min_sys_div, max_sys_div; - unsigned int i; - - /* - * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be - * too high. - */ - dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div); - - /* Don't go above max pll multiplier. */ - more_mul_max = limits->max_pll_multiplier / mul; - dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n", - more_mul_max); - /* Don't go above max pll op frequency. */ - more_mul_max = - min_t(uint32_t, - more_mul_max, - limits->max_pll_op_freq_hz - / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul)); - dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n", - more_mul_max); - /* Don't go above the division capability of op sys clock divider. */ - more_mul_max = min(more_mul_max, - op_limits->max_sys_clk_div * pll->pre_pll_clk_div - / div); - dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n", - more_mul_max); - /* Ensure we won't go above min_pll_multiplier. */ - more_mul_max = min(more_mul_max, - DIV_ROUND_UP(limits->max_pll_multiplier, mul)); - dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n", - more_mul_max); - - /* Ensure we won't go below min_pll_op_freq_hz. */ - more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz, - pll->ext_clk_freq_hz / pll->pre_pll_clk_div - * mul); - dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n", - more_mul_min); - /* Ensure we won't go below min_pll_multiplier. */ - more_mul_min = max(more_mul_min, - DIV_ROUND_UP(limits->min_pll_multiplier, mul)); - dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n", - more_mul_min); - - if (more_mul_min > more_mul_max) { - dev_dbg(dev, - "unable to compute more_mul_min and more_mul_max\n"); - return -EINVAL; - } - - more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div; - dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor); - more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div); - dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n", - more_mul_factor); - i = roundup(more_mul_min, more_mul_factor); - if (!is_one_or_even(i)) - i <<= 1; - - dev_dbg(dev, "final more_mul: %u\n", i); - if (i > more_mul_max) { - dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max); - return -EINVAL; - } - - pll->pll_multiplier = mul * i; - op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div; - dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div); - - pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz - / pll->pre_pll_clk_div; - - pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz - * pll->pll_multiplier; - - /* Derive pll_op_clk_freq_hz. */ - op_pll->sys_clk_freq_hz = - pll->pll_op_clk_freq_hz / op_pll->sys_clk_div; - - op_pll->pix_clk_div = pll->bits_per_pixel; - dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div); - - op_pll->pix_clk_freq_hz = - op_pll->sys_clk_freq_hz / op_pll->pix_clk_div; - - if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { - /* No OP clocks --- VT clocks are used instead. */ - goto out_skip_vt_calc; - } - - /* - * Some sensors perform analogue binning and some do this - * digitally. The ones doing this digitally can be roughly be - * found out using this formula. The ones doing this digitally - * should run at higher clock rate, so smaller divisor is used - * on video timing side. - */ - if (limits->min_line_length_pck_bin > limits->min_line_length_pck - / pll->binning_horizontal) - vt_op_binning_div = pll->binning_horizontal; - else - vt_op_binning_div = 1; - dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div); - - /* - * Profile 2 supports vt_pix_clk_div E [4, 10] - * - * Horizontal binning can be used as a base for difference in - * divisors. One must make sure that horizontal blanking is - * enough to accommodate the CSI-2 sync codes. - * - * Take scaling factor into account as well. - * - * Find absolute limits for the factor of vt divider. - */ - dev_dbg(dev, "scale_m: %u\n", pll->scale_m); - min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div - * pll->scale_n, - lane_op_clock_ratio * vt_op_binning_div - * pll->scale_m); - - /* Find smallest and biggest allowed vt divisor. */ - dev_dbg(dev, "min_vt_div: %u\n", min_vt_div); - min_vt_div = max(min_vt_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.max_pix_clk_freq_hz)); - dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n", - min_vt_div); - min_vt_div = max_t(uint32_t, min_vt_div, - limits->vt.min_pix_clk_div - * limits->vt.min_sys_clk_div); - dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div); - - max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div; - dev_dbg(dev, "max_vt_div: %u\n", max_vt_div); - max_vt_div = min(max_vt_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz)); - dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n", - max_vt_div); - - /* - * Find limitsits for sys_clk_div. Not all values are possible - * with all values of pix_clk_div. - */ - min_sys_div = limits->vt.min_sys_clk_div; - dev_dbg(dev, "min_sys_div: %u\n", min_sys_div); - min_sys_div = max(min_sys_div, - DIV_ROUND_UP(min_vt_div, - limits->vt.max_pix_clk_div)); - dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div); - min_sys_div = max(min_sys_div, - pll->pll_op_clk_freq_hz - / limits->vt.max_sys_clk_freq_hz); - dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div); - min_sys_div = clk_div_even_up(min_sys_div); - dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div); - - max_sys_div = limits->vt.max_sys_clk_div; - dev_dbg(dev, "max_sys_div: %u\n", max_sys_div); - max_sys_div = min(max_sys_div, - DIV_ROUND_UP(max_vt_div, - limits->vt.min_pix_clk_div)); - dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div); - max_sys_div = min(max_sys_div, - DIV_ROUND_UP(pll->pll_op_clk_freq_hz, - limits->vt.min_pix_clk_freq_hz)); - dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div); - - /* - * Find pix_div such that a legal pix_div * sys_div results - * into a value which is not smaller than div, the desired - * divisor. - */ - for (vt_div = min_vt_div; vt_div <= max_vt_div; - vt_div += 2 - (vt_div & 1)) { - for (sys_div = min_sys_div; - sys_div <= max_sys_div; - sys_div += 2 - (sys_div & 1)) { - uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div); - - if (pix_div < limits->vt.min_pix_clk_div - || pix_div > limits->vt.max_pix_clk_div) { - dev_dbg(dev, - "pix_div %u too small or too big (%u--%u)\n", - pix_div, - limits->vt.min_pix_clk_div, - limits->vt.max_pix_clk_div); - continue; - } - - /* Check if this one is better. */ - if (pix_div * sys_div - <= roundup(min_vt_div, best_pix_div)) - best_pix_div = pix_div; - } - if (best_pix_div < INT_MAX >> 1) - break; - } - - pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); - pll->vt.pix_clk_div = best_pix_div; - - pll->vt.sys_clk_freq_hz = - pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div; - pll->vt.pix_clk_freq_hz = - pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div; - -out_skip_vt_calc: - pll->pixel_rate_csi = - op_pll->pix_clk_freq_hz * lane_op_clock_ratio; - pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz; - - return check_all_bounds(dev, limits, op_limits, pll, op_pll); -} - -int smiapp_pll_calculate(struct device *dev, - const struct smiapp_pll_limits *limits, - struct smiapp_pll *pll) -{ - const struct smiapp_pll_branch_limits *op_limits = &limits->op; - struct smiapp_pll_branch *op_pll = &pll->op; - uint16_t min_pre_pll_clk_div; - uint16_t max_pre_pll_clk_div; - uint32_t lane_op_clock_ratio; - uint32_t mul, div; - unsigned int i; - int rval = -EINVAL; - - if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { - /* - * If there's no OP PLL at all, use the VT values - * instead. The OP values are ignored for the rest of - * the PLL calculation. - */ - op_limits = &limits->vt; - op_pll = &pll->vt; - } - - if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE) - lane_op_clock_ratio = pll->csi2.lanes; - else - lane_op_clock_ratio = 1; - dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio); - - dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, - pll->binning_vertical); - - switch (pll->bus_type) { - case SMIAPP_PLL_BUS_TYPE_CSI2: - /* CSI transfers 2 bits per clock per lane; thus times 2 */ - pll->pll_op_clk_freq_hz = pll->link_freq * 2 - * (pll->csi2.lanes / lane_op_clock_ratio); - break; - case SMIAPP_PLL_BUS_TYPE_PARALLEL: - pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel - / DIV_ROUND_UP(pll->bits_per_pixel, - pll->parallel.bus_width); - break; - default: - return -EINVAL; - } - - /* Figure out limits for pre-pll divider based on extclk */ - dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n", - limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); - max_pre_pll_clk_div = - min_t(uint16_t, limits->max_pre_pll_clk_div, - clk_div_even(pll->ext_clk_freq_hz / - limits->min_pll_ip_freq_hz)); - min_pre_pll_clk_div = - max_t(uint16_t, limits->min_pre_pll_clk_div, - clk_div_even_up( - DIV_ROUND_UP(pll->ext_clk_freq_hz, - limits->max_pll_ip_freq_hz))); - dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n", - min_pre_pll_clk_div, max_pre_pll_clk_div); - - i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); - mul = div_u64(pll->pll_op_clk_freq_hz, i); - div = pll->ext_clk_freq_hz / i; - dev_dbg(dev, "mul %u / div %u\n", mul, div); - - min_pre_pll_clk_div = - max_t(uint16_t, min_pre_pll_clk_div, - clk_div_even_up( - DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, - limits->max_pll_op_freq_hz))); - dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n", - min_pre_pll_clk_div, max_pre_pll_clk_div); - - for (pll->pre_pll_clk_div = min_pre_pll_clk_div; - pll->pre_pll_clk_div <= max_pre_pll_clk_div; - pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) { - rval = __smiapp_pll_calculate(dev, limits, op_limits, pll, - op_pll, mul, div, - lane_op_clock_ratio); - if (rval) - continue; - - print_pll(dev, pll); - return 0; - } - - dev_dbg(dev, "unable to compute pre_pll divisor\n"); - - return rval; -} -EXPORT_SYMBOL_GPL(smiapp_pll_calculate); - -MODULE_AUTHOR("Sakari Ailus "); -MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h deleted file mode 100644 index bd6902f54539..000000000000 --- a/drivers/media/i2c/smiapp-pll.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * drivers/media/i2c/smiapp-pll.h - * - * Generic driver for SMIA/SMIA++ compliant camera modules - * - * Copyright (C) 2012 Nokia Corporation - * Contact: Sakari Ailus - */ - -#ifndef SMIAPP_PLL_H -#define SMIAPP_PLL_H - -/* CSI-2 or CCP-2 */ -#define SMIAPP_PLL_BUS_TYPE_CSI2 0x00 -#define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01 - -/* op pix clock is for all lanes in total normally */ -#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0) -#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS (1 << 1) - -struct smiapp_pll_branch { - uint16_t sys_clk_div; - uint16_t pix_clk_div; - uint32_t sys_clk_freq_hz; - uint32_t pix_clk_freq_hz; -}; - -struct smiapp_pll { - /* input values */ - uint8_t bus_type; - union { - struct { - uint8_t lanes; - } csi2; - struct { - uint8_t bus_width; - } parallel; - }; - unsigned long flags; - uint8_t binning_horizontal; - uint8_t binning_vertical; - uint8_t scale_m; - uint8_t scale_n; - uint8_t bits_per_pixel; - uint32_t link_freq; - uint32_t ext_clk_freq_hz; - - /* output values */ - uint16_t pre_pll_clk_div; - uint16_t pll_multiplier; - uint32_t pll_ip_clk_freq_hz; - uint32_t pll_op_clk_freq_hz; - struct smiapp_pll_branch vt; - struct smiapp_pll_branch op; - - uint32_t pixel_rate_csi; - uint32_t pixel_rate_pixel_array; -}; - -struct smiapp_pll_branch_limits { - uint16_t min_sys_clk_div; - uint16_t max_sys_clk_div; - uint32_t min_sys_clk_freq_hz; - uint32_t max_sys_clk_freq_hz; - uint16_t min_pix_clk_div; - uint16_t max_pix_clk_div; - uint32_t min_pix_clk_freq_hz; - uint32_t max_pix_clk_freq_hz; -}; - -struct smiapp_pll_limits { - /* Strict PLL limits */ - uint32_t min_ext_clk_freq_hz; - uint32_t max_ext_clk_freq_hz; - uint16_t min_pre_pll_clk_div; - uint16_t max_pre_pll_clk_div; - uint32_t min_pll_ip_freq_hz; - uint32_t max_pll_ip_freq_hz; - uint16_t min_pll_multiplier; - uint16_t max_pll_multiplier; - uint32_t min_pll_op_freq_hz; - uint32_t max_pll_op_freq_hz; - - struct smiapp_pll_branch_limits vt; - struct smiapp_pll_branch_limits op; - - /* Other relevant limits */ - uint32_t min_line_length_pck_bin; - uint32_t min_line_length_pck; -}; - -struct device; - -int smiapp_pll_calculate(struct device *dev, - const struct smiapp_pll_limits *limits, - struct smiapp_pll *pll); - -#endif /* SMIAPP_PLL_H */ -- cgit v1.2.3 From aa821b2b92699692d7479567481bd807fc8a6d2d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 2 Dec 2020 18:44:16 +0100 Subject: media: MAINTAINERS: Add myself as maintainer of the Amlogic GE2D driver Add new entry to MAINTAINERS. [hverkuil: added changelog] Signed-off-by: Neil Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'MAINTAINERS') diff --git a/MAINTAINERS b/MAINTAINERS index 6380b54bf726..e97d4d9d741e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11380,6 +11380,15 @@ F: Documentation/devicetree/bindings/media/amlogic,meson-gx-ao-cec.yaml F: drivers/media/cec/platform/meson/ao-cec-g12a.c F: drivers/media/cec/platform/meson/ao-cec.c +MESON GE2D DRIVER FOR AMLOGIC SOCS +M: Neil Armstrong +L: linux-media@vger.kernel.org +L: linux-amlogic@lists.infradead.org +S: Supported +T: git git://linuxtv.org/media_tree.git +F: Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml +F: drivers/media/meson/ge2d/ + MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS M: Liang Yang L: linux-mtd@lists.infradead.org -- cgit v1.2.3