Devicetree
 help / color / mirror / Atom feed
* [PATCH 3/6] dt-bindings: arm: amlogic: add bindings for the Amlogic G12B based A311D SoC
From: Neil Armstrong @ 2019-07-31 12:39 UTC (permalink / raw)
  To: khilman, devicetree
  Cc: Neil Armstrong, linux-amlogic, linux-arm-kernel, linux-kernel,
	christianshewitt
In-Reply-To: <20190731124000.22072-1-narmstrong@baylibre.com>

Add a specific compatible for the Amlogic G12B bases A311D SoC used
in the Khadas VIM3.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 3c3bc806cd23..efa032d12402 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -135,6 +135,11 @@ properties:
               - amlogic,u200
           - const: amlogic,g12a
 
+      - description: Boards with the Amlogic Meson G12B A311D SoC
+        items:
+          - const: amlogic,a311d
+          - const: amlogic,g12b
+
       - description: Boards with the Amlogic Meson G12B S922X SoC
         items:
           - enum:
-- 
2.22.0

^ permalink raw reply related

* [PATCH 4/6] dt-bindings: arm: amlogic: add support for the Khadas VIM3
From: Neil Armstrong @ 2019-07-31 12:39 UTC (permalink / raw)
  To: khilman, devicetree
  Cc: Christian Hewitt, linux-amlogic, linux-arm-kernel, linux-kernel,
	Neil Armstrong
In-Reply-To: <20190731124000.22072-1-narmstrong@baylibre.com>

From: Christian Hewitt <christianshewitt@gmail.com>

The Khadas VIM3 uses the Amlogic S922X or A311S SoC, both based on the
Amlogic G12B SoC family, on a board with the same form factor as the
VIM/VIM2 models. It ships in two variants; basic and
pro which differ in RAM and eMMC size:

- 2GB (basic) or 4GB (pro) LPDDR4 RAM
- 16GB (basic) or 32GB (pro) eMMC 5.1 storage
- 16MB SPI flash
- 10/100/1000 Base-T Ethernet
- AP6398S Wireless (802.11 a/b/g/n/ac, BT5.0)
- HDMI 2.1 video
- 1x USB 2.0 + 1x USB 3.0 ports
- 1x USB-C (power) with USB 2.0 OTG
- 3x LED's (1x red, 1x blue, 1x white)
- 3x buttons (power, function, reset)
- IR receiver
- M2 socket with PCIe, USB, ADC & I2C
- 40pin GPIO Header
- 1x micro SD card slot

Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 Documentation/devicetree/bindings/arm/amlogic.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index efa032d12402..04a2b0ef34c6 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -137,6 +137,8 @@ properties:
 
       - description: Boards with the Amlogic Meson G12B A311D SoC
         items:
+          - enum:
+              - khadas,vim3
           - const: amlogic,a311d
           - const: amlogic,g12b
 
@@ -144,6 +146,7 @@ properties:
         items:
           - enum:
               - hardkernel,odroid-n2
+              - khadas,vim3
           - const: amlogic,s922x
           - const: amlogic,g12b
 
-- 
2.22.0

^ permalink raw reply related

* Re: [PATCH v2 08/20] ARM: dts: imx7-colibri: Add touch controllers
From: Fabio Estevam @ 2019-07-31 12:42 UTC (permalink / raw)
  To: Philippe Schenker
  Cc: Marcel Ziswiler, Max Krummenacher, stefan@agner.ch,
	devicetree@vger.kernel.org, Rob Herring, Shawn Guo, Mark Rutland,
	Michal Vokáč, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Pengutronix Kernel Team,
	NXP Linux Team, Sascha Hauer
In-Reply-To: <20190731123750.25670-9-philippe.schenker@toradex.com>

On Wed, Jul 31, 2019 at 9:38 AM Philippe Schenker
<philippe.schenker@toradex.com> wrote:
>
> Add atmel mxt multitouch controller and TouchRevolution multitouch

You missed to updated the commit log ;-)

^ permalink raw reply

* Re: [PATCH 1/6] dt-bindings: thermal: Add DT bindings documentation for Amlogic Thermal
From: Neil Armstrong @ 2019-07-31 12:44 UTC (permalink / raw)
  To: Guillaume La Roque, daniel.lezcano, khilman
  Cc: devicetree, linux-amlogic, linux-kernel, linux-arm-kernel,
	linux-pm
In-Reply-To: <20190731121409.17285-2-glaroque@baylibre.com>

On 31/07/2019 14:14, Guillaume La Roque wrote:
> Adding the devicetree binding documentation for the Amlogic temperature
> sensor found in the Amlogic Meson G12 SoCs.
> the G12A  and G12B SoCs are supported.
> 
> Signed-off-by: Guillaume La Roque <glaroque@baylibre.com>
> ---
>  .../bindings/thermal/amlogic,thermal.yaml     | 58 +++++++++++++++++++
>  1 file changed, 58 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
> 
> diff --git a/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
> new file mode 100644
> index 000000000000..1e2fe84da13d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
> @@ -0,0 +1,58 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/thermal/amlogic,thermal.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Amlogic Thermal Driver
> +
> +maintainers:
> +  - Guillaume La Roque <glaroque@baylibre.com>
> +
> +description: Amlogic Thermal driver
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - items:
> +          - enum:
> +              - amlogic,g12-cpu-thermal
> +              - amlogic,g12-ddr-thermal
> +          - enum:
> +              - amlogic,g12-thermal

Shouldn't be :
    compatible:
	items:
          - enum:
              - amlogic,g12-cpu-thermal
	      - amlogic,g12-ddr-thermal
          - const:
              - amlogic,g12-thermal

instead ?

> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  amlogic,ao-secure:
> +    description: phandle to the ao-secure syscon
> +    allOf:
> +     - $ref: /schemas/types.yaml#/definitions/uint32
> +
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - clocks
> +  - amlogic,ao-secure
> +
> +examples:
> +  - |
> +        cpu_temp: temperature-sensor@ff634800 {
> +                compatible = "amlogic,g12-cpu-thermal",
> +                             "amlogic,g12-thermal";
> +                reg = <0x0 0xff634800 0x0 0x50>;
> +                interrupts = <0x0 0x24 0x0>;
> +                clocks = <&clk 164>;
> +                status = "okay";
> +                #thermal-sensor-cells = <1>;
> +                amlogic,ao-secure = <&sec_AO>;
> +        };
> +...
> \ No newline at end of file
> 

^ permalink raw reply

* Re: [PATCH 2/6] thermal: amlogic: Add thermal driver to support G12 SoCs
From: Neil Armstrong @ 2019-07-31 12:45 UTC (permalink / raw)
  To: Guillaume La Roque, daniel.lezcano, khilman
  Cc: devicetree, linux-amlogic, linux-kernel, linux-arm-kernel,
	linux-pm
In-Reply-To: <20190731121409.17285-3-glaroque@baylibre.com>

On 31/07/2019 14:14, Guillaume La Roque wrote:
> Signed-off-by: Guillaume La Roque <glaroque@baylibre.com>
> ---
>  drivers/thermal/Kconfig           |  12 +-
>  drivers/thermal/Makefile          |   1 +
>  drivers/thermal/amlogic_thermal.c | 335 ++++++++++++++++++++++++++++++
>  3 files changed, 347 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/thermal/amlogic_thermal.c
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 9966364a6deb..2332ef1bfafc 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -1,4 +1,3 @@
> -# SPDX-License-Identifier: GPL-2.0-only

|\ typo ?

>  #
>  # Generic thermal sysfs drivers configuration
>  #
> @@ -348,6 +347,17 @@ config MTK_THERMAL
>  	  Enable this option if you want to have support for thermal management
>  	  controller present in Mediatek SoCs
>  
> +config AMLOGIC_THERMAL
> +	tristate "Amlogic Thermal Support"
> +	default ARCH_MESON
> +	depends on OF && ARCH_MESON
> +	help
> +	  If you say yes here you get support for Amlogic Thermal
> +	  for G12 SoC Family.
> +
> +	  This driver can also be built as a module. If so, the module will
> +	  be called amlogic_thermal.
> +
>  menu "Intel thermal drivers"
>  depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
>  source "drivers/thermal/intel/Kconfig"

[...]

^ permalink raw reply

* Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
From: Greg KH @ 2019-07-31 12:48 UTC (permalink / raw)
  To: Dragan Cvetic
  Cc: arnd@arndb.de, Michal Simek, linux-arm-kernel@lists.infradead.org,
	robh+dt@kernel.org, mark.rutland@arm.com,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Derek Kiernan
In-Reply-To: <CH2PR02MB6359A32E03E920AE5EEB7324CBE60@CH2PR02MB6359.namprd02.prod.outlook.com>

On Sat, Jun 22, 2019 at 05:54:04PM +0000, Dragan Cvetic wrote:
> 
> 
> > -----Original Message-----
> > From: Greg KH [mailto:gregkh@linuxfoundation.org]
> > Sent: Saturday 22 June 2019 07:02
> > To: Dragan Cvetic <draganc@xilinx.com>
> > Cc: arnd@arndb.de; Michal Simek <michals@xilinx.com>; linux-arm-kernel@lists.infradead.org; robh+dt@kernel.org;
> > mark.rutland@arm.com; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Derek Kiernan <dkiernan@xilinx.com>
> > Subject: Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
> > 
> > On Fri, Jun 21, 2019 at 05:49:45PM +0000, Dragan Cvetic wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Greg KH [mailto:gregkh@linuxfoundation.org]
> > > > Sent: Friday 21 June 2019 15:16
> > > > To: Dragan Cvetic <draganc@xilinx.com>
> > > > Cc: arnd@arndb.de; Michal Simek <michals@xilinx.com>; linux-arm-kernel@lists.infradead.org; robh+dt@kernel.org;
> > > > mark.rutland@arm.com; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Derek Kiernan <dkiernan@xilinx.com>
> > > > Subject: Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
> > > >
> > > > On Tue, Jun 11, 2019 at 06:29:34PM +0100, Dragan Cvetic wrote:
> > > > > This patchset is adding the full Soft Decision Forward Error
> > > > > Correction (SD-FEC) driver implementation, driver DT binding and
> > > > > driver documentation.
> > > > >
> > > > > Forward Error Correction (FEC) codes such as Low Density Parity
> > > > > Check (LDPC) and turbo codes provide a means to control errors in
> > > > > data transmissions over unreliable or noisy communication
> > > > > channels. The SD-FEC Integrated Block is an optimized block for
> > > > > soft-decision decoding of these codes. Fixed turbo codes are
> > > > > supported directly, whereas custom and standardized LDPC codes
> > > > > are supported through the ability to specify the parity check
> > > > > matrix through an AXI4-Lite bus or using the optional programmable
> > > > > (PL)-based support logic. For the further information see
> > > > > https://www.xilinx.com/support/documentation/ip_documentation/
> > > > > sd_fec/v1_1/pg256-sdfec-integrated-block.pdf
> > > > >
> > > > > This driver is a platform device driver which supports SDFEC16
> > > > > (16nm) IP. SD-FEC driver supports LDPC decoding and encoding and
> > > > > Turbo code decoding. LDPC codes can be specified on
> > > > > a codeword-by-codeword basis, also a custom LDPC code can be used.
> > > > >
> > > > > The SD-FEC driver exposes a char device interface and supports
> > > > > file operations: open(), close(), poll() and ioctl(). The driver
> > > > > allows only one usage of the device, open() limits the number of
> > > > > driver instances. The driver also utilize Common Clock Framework
> > > > > (CCF).
> > > > >
> > > > > The control and monitoring is supported over ioctl system call.
> > > > > The features supported by ioctl():
> > > > > - enable or disable data pipes to/from device
> > > > > - configure the FEC algorithm parameters
> > > > > - set the order of data
> > > > > - provide a control of a SDFEC bypass option
> > > > > - activates/deactivates SD-FEC
> > > > > - collect and provide statistical data
> > > > > - enable/disable interrupt mode
> > > >
> > > > Is there any userspace tool that talks to this device using these custom
> > > > ioctls yet?
> > > >
> > > Tools no, but could be the customer who is using the driver.
> > 
> > I don't understand this.  Who has written code to talk to these
> > special ioctls from userspace?  Is there a pointer to that code
> > anywhere?
> > 
> 
> The code which use this driver are written by the driver maintainers
> they are examples APP and test code which are not public.

So, no open code is talking to this one specific driver?  And you have
run this past your lawyers?  Please go talk to them about this and see
what they say (hint, creating a custom ioctl that only you use is a
"fun" legal area...)

> > > > Doing a one-off ioctl api is always a risky thing, you are pretty much
> > > > just creating brand new system calls for one piece of hardware.
> > > >
> > >
> > > Why is that wrong and what is the risk?
> > 
> > You now have custom syscalls for one specfic piece of hardware that you
> > now have to maintain working properly for the next 40+ years.  You have
> > to make sure those calls are correct and that this is the correct api to
> > talk to this hardware.
> 
> This is very specific HW, it's high speed Forward Error Correction HW.

I have no idea what that actually means.

What is "Forward Error Correction"?  What does it do?  Is this a network
device?  Video device?  Random black box that sends radio waves?

Is there no other in-kernel driver that does much the same type of
thing?  What "class" of driver would this be?

> > > What would you propose?
> > > Definitely, I have to read about this.
> > 
> > What is this hardware and what is it used for?  Who will be talking to
> 
> The Soft-Decision Forward Error Correction (SD-FEC) integrated block
> supports Low Density Parity Check (LDPC) decoding and encoding and
> Turbo code decoding.

I still don't understand what this means.

> SD-FEC use case is in high data rate applications such as 4G, 5G and
> DOCSIS3.1 Cable Access.  A high performance SD-FEC (i.e. >1Gbps), is a
> block used to enable these systems to function under non-ideal
> environments.

Nor do I understand what this is either.  Do you have a pointer to this
hardware somewhere online that might describe it better?  Given that I
have no clue, odds are others do not know what it is either.

> > it from userspace?  What userspace workload uses it?  What tools need to
> 
> There will be APP which configures the HW for the use cases listed above.

What exactly are these use cases?

Where is the application?  Who runs it?  Is it already in a distro
somewhere?  Who is going to distribute it?  Who is going to support it?
Is it only for sale?  What is the license of it?

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 4/6] arm64: dts: meson: sei510: Add minimal thermal zone
From: Neil Armstrong @ 2019-07-31 12:51 UTC (permalink / raw)
  To: Guillaume La Roque, daniel.lezcano, khilman
  Cc: devicetree, linux-amlogic, linux-kernel, linux-arm-kernel,
	linux-pm
In-Reply-To: <20190731121409.17285-5-glaroque@baylibre.com>

On 31/07/2019 14:14, Guillaume La Roque wrote:
> Add minimal thermal zone for DDR and CPU sensor
> 
> Signed-off-by: Guillaume La Roque <glaroque@baylibre.com>
> ---
>  arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
> index c7a87368850b..79ae514e238d 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
> +++ b/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
> @@ -33,6 +33,19 @@
>  		ethernet0 = &ethmac;
>  	};
>  
> +	thermal-zones {
> +		soc_thermal {
> +			polling-delay = <1000>;
> +			polling-delay-ptripsassive = <100>;
> +			thermal-sensors = <&cpu_temp 0>;


Seems the trips & cooling-maps are required as described in thermal.txt

For the soc_thermal zone it's esy to add a cooling map with the CPU
and cooling devices, but for the ddr_thermal, no idea if we can use the
CPUs within 2 cooling maps.

> +		};

I would add a blank line between the zones, same for other files.


> +		ddr_thermal {
> +			polling-delay = <1000>;
> +			polling-delay-passive = <100>;
> +			thermal-sensors = <&ddr_temp 1>;
> +		};
> +	};
> +
>  	mono_dac: audio-codec-0 {
>  		compatible = "maxim,max98357a";
>  		#sound-dai-cells = <0>;
> 

^ permalink raw reply

* Re: [PATCH 6/6] MAINTAINERS: add entry for Amlogic Thermal driver
From: Neil Armstrong @ 2019-07-31 12:52 UTC (permalink / raw)
  To: Guillaume La Roque, daniel.lezcano, khilman
  Cc: devicetree, linux-amlogic, linux-kernel, linux-arm-kernel,
	linux-pm
In-Reply-To: <20190731121409.17285-7-glaroque@baylibre.com>

On 31/07/2019 14:14, Guillaume La Roque wrote:
> Add myself as maintainer for Amlogic Thermal driver.
> 
> Signed-off-by: Guillaume La Roque <glaroque@baylibre.com>
> ---
>  MAINTAINERS | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fb2b12f75c37..299f27d11058 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15910,6 +15910,15 @@ F:	Documentation/driver-api/thermal/cpu-cooling-api.rst
>  F:	drivers/thermal/cpu_cooling.c
>  F:	include/linux/cpu_cooling.h
>  
> +THERMAL DRIVER FOR AMLOGIC SOCS
> +M:	Guillaume La Roque <glaroque@baylibre.com>
> +L:	linux-pm@vger.kernel.org
> +L:	linux-amlogic@lists.infradead.org
> +W:	http://linux-meson.com/
> +S:	Supported
> +F:	drivers/thermal/amlogic_thermal.c
> +F:	Documentation/devicetree/bindings/thermal/amlogic,thermal.yaml
> +
>  THINKPAD ACPI EXTRAS DRIVER
>  M:	Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
>  L:	ibm-acpi-devel@lists.sourceforge.net
> 

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>

^ permalink raw reply

* Re: [PATCH v2 07/20] ARM: dts: imx7-colibri: fix 1.8V/UHS support
From: Fabio Estevam @ 2019-07-31 12:56 UTC (permalink / raw)
  To: Philippe Schenker
  Cc: Marcel Ziswiler, Max Krummenacher, stefan@agner.ch,
	devicetree@vger.kernel.org, Rob Herring, Shawn Guo, Mark Rutland,
	Michal Vokáč, Stefan Agner,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Pengutronix Kernel Team,
	NXP Linux Team, Sascha Hauer
In-Reply-To: <20190731123750.25670-8-philippe.schenker@toradex.com>

On Wed, Jul 31, 2019 at 9:38 AM Philippe Schenker
<philippe.schenker@toradex.com> wrote:
>
> From: Stefan Agner <stefan.agner@toradex.com>
>
> Add pinmuxing and do not specify voltage restrictions in the
> module level device tree.

It would be nice to explain the reason for doing this.

> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
> Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
> ---
>
> Changes in v2: None
>
>  arch/arm/boot/dts/imx7-colibri.dtsi | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
> index 16d1a1ed1aff..67f5e0c87fdc 100644
> --- a/arch/arm/boot/dts/imx7-colibri.dtsi
> +++ b/arch/arm/boot/dts/imx7-colibri.dtsi
> @@ -326,7 +326,6 @@
>  &usdhc1 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_cd_usdhc1>;
> -       no-1-8-v;
>         cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
>         disable-wp;
>         vqmmc-supply = <&reg_LDO2>;
> @@ -671,6 +670,28 @@
>                 >;
>         };
>
> +       pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
> +               fsl,pins = <
> +                       MX7D_PAD_SD1_CMD__SD1_CMD       0x5a
> +                       MX7D_PAD_SD1_CLK__SD1_CLK       0x1a
> +                       MX7D_PAD_SD1_DATA0__SD1_DATA0   0x5a
> +                       MX7D_PAD_SD1_DATA1__SD1_DATA1   0x5a
> +                       MX7D_PAD_SD1_DATA2__SD1_DATA2   0x5a
> +                       MX7D_PAD_SD1_DATA3__SD1_DATA3   0x5a
> +               >;
> +       };
> +
> +       pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
> +               fsl,pins = <
> +                       MX7D_PAD_SD1_CMD__SD1_CMD       0x5b
> +                       MX7D_PAD_SD1_CLK__SD1_CLK       0x1b
> +                       MX7D_PAD_SD1_DATA0__SD1_DATA0   0x5b
> +                       MX7D_PAD_SD1_DATA1__SD1_DATA1   0x5b
> +                       MX7D_PAD_SD1_DATA2__SD1_DATA2   0x5b
> +                       MX7D_PAD_SD1_DATA3__SD1_DATA3   0x5b
> +               >;
> +       };

You add the entries for 100MHz and 200MHz, but I don't see them being
referenced anywhere.

^ permalink raw reply

* Re: [RFC PATCH 01/11] devfreq: exynos-bus: Extract exynos_bus_profile_init()
From: Artur Świgoń @ 2019-07-31 13:00 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel, cw00.choi, myungjoo.ham, inki.dae,
	sw0312.kim, georgi.djakov, m.szyprowski,
	Bartłomiej Żołnierkiewicz
In-Reply-To: <20190724190741.GD14346@kozik-lap>

Hi,

On Wed, 2019-07-24 at 21:07 +0200, Krzysztof Kozlowski wrote:
> On Tue, Jul 23, 2019 at 02:20:06PM +0200, Artur Świgoń wrote:
> > This patch adds a new static function, exynos_bus_profile_init(), extracted
> > from exynos_bus_probe().
> > 
> > Signed-off-by: Artur Świgoń <a.swigon@partner.samsung.com>
> > ---
> >  drivers/devfreq/exynos-bus.c | 106 ++++++++++++++++++++---------------
> >  1 file changed, 60 insertions(+), 46 deletions(-)
> > 
> > diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c
> > index d9f377912c10..d8f1efaf2d49 100644
> > --- a/drivers/devfreq/exynos-bus.c
> > +++ b/drivers/devfreq/exynos-bus.c
> > @@ -372,12 +372,69 @@ static int exynos_bus_parse_of(struct device_node *np,
> >  	return ret;
> >  }
> >  
> > +static int exynos_bus_profile_init(struct exynos_bus *bus,
> > +				   struct devfreq_dev_profile *profile)
> > +{
> > +	struct device *dev = bus->dev;
> > +	struct devfreq_simple_ondemand_data *ondemand_data;
> > +	int ret;
> > +
> > +	/* Initialize the struct profile and governor data for parent device */
> > +	profile->polling_ms = 50;
> > +	profile->target = exynos_bus_target;
> > +	profile->get_dev_status = exynos_bus_get_dev_status;
> > +	profile->exit = exynos_bus_exit;
> > +
> > +	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
> > +	if (!ondemand_data) {
> > +		ret = -ENOMEM;
> > +		goto err;
> 
> Just return proper error code. Less lines, obvious code since you do not
> have any cleanup in error path.

I was advised to avoid modifying code being moved (in one patch). I do make
changes in these places in patch 04/11, i.e. change the original label 'err' to
'out'. What's your opinion on making the proposed changes to patches 01 and 02
(s/goto err/return ret/) in patch 04 instead?

> > +
> > +	/* Register opp_notifier to catch the change of OPP  */
> > +	ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
> > +	if (ret < 0) {
> > +		dev_err(dev, "failed to register opp notifier\n");
> > +		goto err;
> 
> The same - return err.
> 
> Best regards,
> Krzysztof

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics

^ permalink raw reply

* Re: [RFC PATCH 08/11] arm: dts: exynos: Add parents and #interconnect-cells to Exynos4412
From: Artur Świgoń @ 2019-07-31 13:00 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel, cw00.choi, myungjoo.ham, inki.dae,
	sw0312.kim, georgi.djakov, m.szyprowski,
	Bartłomiej Żołnierkiewicz
In-Reply-To: <20190724192426.GJ14346@kozik-lap>

On Wed, 2019-07-24 at 21:24 +0200, Krzysztof Kozlowski wrote:
> On Tue, Jul 23, 2019 at 02:20:13PM +0200, Artur Świgoń wrote:
> > This patch adds two fields tp the Exynos4412 DTS:
> 
> tp->to

Fixed. Thanks for catching the typo :)

> >   - parent: to declare connections between nodes that are not in a
> >     parent-child relation in devfreq;
> 
> Is it a standard property?
> The explanation needs some improvement... why are you adding parent to a
> devices which are not child-parent?

This is not a standard property. I actually wanted to call it 'neighbor' at first. If you take a look at [1] and search for 'Exynos4x12', you will see that there are two power lines, and each has exactly one parent block (the rest are modelled in devfreq as its children). In [2], the parent of each child is indicated using the 'devfreq' property, e.g.,

&bus_display {
	devfreq = <&bus_leftbus>;
	status = "okay";
};

The single piece missing to make this topology a connected graph (for
interconnect QoS purposes) is the 'parent' property I proposed in this patch.
bus_leftbus is dependent on bus_dmc, therefore using the term 'parent' is
justified IMHO.

The explanation could be improved by adding what Chanwoo Choi <
cw00.choi@samsung.com> expressed in a parallel reply to this patch:
> - If 'devfreq' property is used between buses,
>   it indicates that there are requirement of sharing of power line.
> - If 'parent' property is used between buses,
>   it indicates that there are requirement of interconnect connection.

[1] Documentation/devicetree/bindings/devfreq/exynos-bus.txt
[2] arch/arm/boot/dts/exynos4412-odroid-common.dtsi (subject of this patch)

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics

^ permalink raw reply

* Re: [RFC PATCH 09/11] devfreq: exynos-bus: Add interconnect functionality to exynos-bus
From: Artur Świgoń @ 2019-07-31 13:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: devicetree, linux-arm-kernel, linux-samsung-soc, linux-kernel,
	linux-pm, dri-devel, cw00.choi, myungjoo.ham, inki.dae,
	sw0312.kim, georgi.djakov, m.szyprowski,
	Bartłomiej Żołnierkiewicz
In-Reply-To: <20190724183639.GA14346@kozik-lap>

On Wed, 2019-07-24 at 20:36 +0200, Krzysztof Kozlowski wrote:
> On Tue, Jul 23, 2019 at 02:20:14PM +0200, Artur Świgoń wrote:
> > This patch adds interconnect functionality to the exynos-bus devfreq
> > driver.
> > 
> > The SoC topology is a graph (or, more specifically, a tree) and most of its
> > edges are taken from the devfreq parent-child hierarchy (cf.
> > Documentation/devicetree/bindings/devfreq/exynos-bus.txt). The previous
> > patch adds missing edges to the DT (under the name 'parent'). Due to
> 
> Do not refer to DT patches. They will come through different tree so
> "previous" will not be correct anymore. You mentioned dependencies in
> cover letter so it is sufficient.

OK.
 
> >  /*
> > @@ -61,6 +69,13 @@ exynos_bus_ops_edev(enable_edev);
> >  exynos_bus_ops_edev(disable_edev);
> >  exynos_bus_ops_edev(set_event);
> >  
> > +static int exynos_bus_next_id(void)
> > +{
> > +	static int exynos_bus_node_id;
> > +
> > +	return exynos_bus_node_id++;
> 
> This does not look robust. Use IDR for IDs. 

OK.

> > +static int exynos_bus_icc_connect(struct exynos_bus *bus)
> > +{
> > +	struct device_node *np = bus->dev->of_node;
> > +	struct devfreq *parent_devfreq;
> > +	struct icc_node *parent_node = NULL;
> > +	struct of_phandle_args args;
> > +	int ret = 0;
> > +
> > +	parent_devfreq = devfreq_get_devfreq_by_phandle(bus->dev, 0);
> > +	if (!IS_ERR(parent_devfreq)) {
> > +		struct exynos_bus *parent_bus;
> 
> What if someone unbinds this parent devfreq? I guess everything in
> devfreq starts exploding... however it's not the problem of this patch.
> 
> Do you also need suspend/resume order (device links)? I guess the other
> side, e.g.  mixer, should resume before the bus?

Actually, I think that the bus (devfreq) should resume before mixer. However,
suspend/resume order is another issue that applies to this driver regardless of
using the interconnect framework, although device links could probably also be
implemented in the interconnect framework itself.

> > +		parent_bus = dev_get_drvdata(parent_devfreq->dev.parent);
> > +		parent_node = parent_bus->node;
> > +	} else {
> > +		/* Look for parent in DT */
> > +		int num = of_count_phandle_with_args(np, "parent",
> > +						     "#interconnect-cells");
> > +		if (num != 1)
> 
> You will return here 0 but isn't it an error?

It is definitely not an error when 'parent' does not exist in DT (for buses that
are parents themselves). I can extend the comment in the code to explicitly
state that.

Best regards,
-- 
Artur Świgoń
Samsung R&D Institute Poland
Samsung Electronics

^ permalink raw reply

* Re: [PATCH 2/2] ARM: dts: at91: add support for Arietta G25
From: Ludovic Desroches @ 2019-07-31 13:18 UTC (permalink / raw)
  To: Uwe Kleine-König, Rob Herring, Mark Rutland, Nicolas Ferre,
	Alexandre Belloni, linux-arm-kernel, devicetree, info
In-Reply-To: <20190731113648.kyktpnk3exly57fw@M43218.corp.atmel.com>

On Wed, Jul 31, 2019 at 01:36:49PM +0200, Ludovic Desroches wrote:
> On Sun, Jul 28, 2019 at 11:04:03PM +0200, Uwe Kleine-König wrote:
> > 
> > The Arietta G25 is a SBC powered by a AT91SAMG25 running at 400 MHz.
> > See https://www.acmesystems.it/arietta for more details.
> > 
> > Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
> Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>

I should have double checked before, I had in mind that we support this
board in our bootloader but it's also the case in the kernel:

arch/arm/boot/dts/at91-ariettag25.dts

Regards

Ludovic

> 
> > ---
> >  arch/arm/boot/dts/at91sam9g25-arietta.dts | 86 +++++++++++++++++++++++
> >  1 file changed, 86 insertions(+)
> >  create mode 100644 arch/arm/boot/dts/at91sam9g25-arietta.dts
> > 
> > diff --git a/arch/arm/boot/dts/at91sam9g25-arietta.dts b/arch/arm/boot/dts/at91sam9g25-arietta.dts
> > new file mode 100644
> > index 000000000000..6c20e02f0ea9
> > --- /dev/null
> > +++ b/arch/arm/boot/dts/at91sam9g25-arietta.dts
> > @@ -0,0 +1,86 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Arietta - System On Module
> > + * https://www.acmesystems.it/arietta
> > + */
> > +
> > +/dts-v1/;
> > +#include "at91sam9g25.dtsi"
> > +
> > +/ {
> > +	model = "Acme Systems Arietta G25";
> > +	compatible = "acme,ariettag25", "atmel,at91sam9x5", "atmel,at91sam9";
> > +
> > +	chosen {
> > +		stdout-path = "serial0:115200n8";
> > +	};
> > +
> > +	memory {
> > +		reg = <0x20000000 0x8000000>;
> > +	};
> > +
> > +	clocks {
> > +		slow_xtal {
> > +			clock-frequency = <32768>;
> > +		};
> > +
> > +		main_xtal {
> > +			clock-frequency = <12000000>;
> > +		};
> > +	};
> > +
> > +	ahb {
> > +		apb {
> > +			rtc@fffffeb0 {
> > +				status = "okay";
> > +			};
> > +		};
> > +	};
> > +
> > +	leds {
> > +		compatible = "gpio-leds";
> > +
> > +		arietta_led {
> > +			label = "arietta_led";
> > +			gpios = <&pioB 8 GPIO_ACTIVE_HIGH>;
> > +			linux,default-trigger = "heartbeat";
> > +		};
> > +	};
> > +};
> > +
> > +&dbgu {
> > +	status = "okay";
> > +};
> > +
> > +&mmc0 {
> > +	pinctrl-0 = <
> > +		&pinctrl_mmc0_slot0_clk_cmd_dat0
> > +		&pinctrl_mmc0_slot0_dat1_3>;
> > +	status = "okay";
> > +
> > +	slot@0 {
> > +		reg = <0>;
> > +		bus-width = <4>;
> > +	};
> > +};
> > +
> > +&usart0 {
> > +	status ="okay";
> > +};
> > +
> > +&usart1 {
> > +	status ="okay";
> > +};
> > +
> > +&usb0 {
> > +	status = "okay";
> > +	num-ports = <3>;
> > +};
> > +
> > +&usb1 {
> > +	status = "okay";
> > +};
> > +
> > +&usb2 {
> > +	status = "okay";
> > +};
> > -- 
> > 2.20.1
> > 

^ permalink raw reply

* [PATCH/RFC] ARM: dts: rza2mevb: Fix numbering of Ethernet aliases
From: Geert Uytterhoeven @ 2019-07-31 13:39 UTC (permalink / raw)
  To: Simon Horman, Magnus Damm, Marek Vasut
  Cc: Rob Herring, Mark Rutland, linux-renesas-soc, devicetree,
	Geert Uytterhoeven

The two Ethernet ports on the RZA2MEVB development board are labeled
"Ether1" and "Ether2".  Reflect this numbering in the ethernet aliases.

Fixes: eb8be0276d903a23 ("ARM: dts: rza2mevb: add ethernet aliases")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
Is this the right thing to do?
Can U-Boot live with the absence of ethernet0?

 arch/arm/boot/dts/r7s9210-rza2mevb.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/r7s9210-rza2mevb.dts b/arch/arm/boot/dts/r7s9210-rza2mevb.dts
index d062d02865e7dfbb..0686bac4bfd8e191 100644
--- a/arch/arm/boot/dts/r7s9210-rza2mevb.dts
+++ b/arch/arm/boot/dts/r7s9210-rza2mevb.dts
@@ -18,8 +18,8 @@
 
 	aliases {
 		serial0 = &scif4;
-		ethernet0 = &ether0;
-		ethernet1 = &ether1;
+		ethernet1 = &ether0;
+		ethernet2 = &ether1;
 	};
 
 	chosen {
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH v7 08/14] media: rkisp1: add capture device driver
From: Helen Koike @ 2019-07-31 13:49 UTC (permalink / raw)
  To: André Almeida, linux-rockchip
  Cc: devicetree, eddie.cai.linux, mchehab, heiko, jacob2.chen,
	jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
	laurent.pinchart, sakari.ailus, kernel, ezequiel, linux-media,
	linux-arm-kernel, zhengsq, Jacob Chen, Allon Huang
In-Reply-To: <6334c031-9d28-796c-5486-70a3c7861922@collabora.com>



On 7/4/19 2:27 PM, André Almeida wrote:
> Hello Helen,
> 
> On 7/3/19 4:09 PM, Helen Koike wrote:
>> From: Jacob Chen <jacob2.chen@rock-chips.com>
>>
>> This is the capture device interface driver that provides the v4l2
>> user interface. Frames can be received from ISP1.
>>
>> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
>> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
>> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
>> Signed-off-by: Jacob Chen <cc@rock-chips.com>
>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
>> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
>> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
>> [updated for upstream]
>> Signed-off-by: Helen Koike <helen.koike@collabora.com>
>>
>> ---
>> Hi,
>>
>> Hans, I removed your Acked-by tag since some things changed. Please let
>> me know if I can keep it.
>>
>> Thanks
>> Helen
>>
>> Changes in v7:
>> - s/strlcpy/strscpy
>> - Fix v4l2-compliance issues:
>>         * remove input ioctls
>> media api can be used to define the topology, this input api is not
>> required. Besides it, if an input is enumerated, v4l2-compliance is not
>> happy with G_FMT returning the default colorspace instead of something
>> more specific.
>>         * return the pixelformat to the userspace
>> G_/S_/TRY_ FORMAT should return a valid pixelformat to the user, even if
>> the user gave an invalid one
>>         * add missing default colorspace and ycbcr
>>         * fix wrong pixformat in mp_fmts[] table
>>         * add buf type check in s_/g_selection
>>         * queue_setup - check sizes
>>         * normalize bus_info name
>>         * fix field any v4l2-compliance -s complain - set field none
>>         when streaming
>> - Fix compiling error: s/vidioc_enum_fmt_vid_cap_mplane/vidioc_enum_fmt_vid_cap
>> - Replace stream state with a boolean
>> The rkisp1_state enum consists only of 3 entries, where 1 is completely
>> unused and the other two respectively mean not streaming or streaming.
>> Replace it with a boolean called "streaming".
>> - Simplify MI interrupt handling
>> Rather than adding unnecessary indirection, just use stream index to
>> handle MI interrupt enable/disable/clear, since the stream index matches
>> the order of bits now, thanks to previous patch. While at it, remove
>> some dead code.
>> - code styling and checkpatch fixes
>> - add link_validate: don't allow a link with bayer/non-bayer mismatch
>>
>>  .../media/platform/rockchip/isp1/capture.c    | 1754 +++++++++++++++++
>>  .../media/platform/rockchip/isp1/capture.h    |  164 ++
>>  drivers/media/platform/rockchip/isp1/regs.c   |  223 +++
>>  drivers/media/platform/rockchip/isp1/regs.h   | 1525 ++++++++++++++
>>  4 files changed, 3666 insertions(+)
>>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/capture.h
>>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.c
>>  create mode 100644 drivers/media/platform/rockchip/isp1/regs.h
>>
>> diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c
>> new file mode 100644
>> index 000000000000..86ceeb8443e7
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/capture.c
>> @@ -0,0 +1,1754 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/pm_runtime.h>
>> +#include <media/v4l2-common.h>
>> +#include <media/v4l2-event.h>
>> +#include <media/v4l2-fh.h>
>> +#include <media/v4l2-ioctl.h>
>> +#include <media/v4l2-subdev.h>
>> +#include <media/videobuf2-dma-contig.h>
>> +
>> +#include "dev.h"
>> +#include "regs.h"
>> +
>> +/*
>> + * NOTE:
>> + * 1. There are two capture video devices in rkisp1, selfpath and mainpath
>> + * 2. Two capture device have separated memory-interface/crop/scale units.
>> + * 3. Besides describing stream hardware, this file also contain entries
>> + *    for pipeline operations.
>> + * 4. The register read/write operations in this file are put into regs.c.
>> + */
>> +
>> +/*
>> + * differences between selfpatch 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 CIF_ISP_REQ_BUFS_MIN 1
>> +#define CIF_ISP_REQ_BUFS_MAX 8
>> +
>> +#define STREAM_PAD_SINK				0
>> +#define STREAM_PAD_SOURCE			1
>> +
>> +#define STREAM_MAX_MP_RSZ_OUTPUT_WIDTH		4416
>> +#define STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT		3312
>> +#define STREAM_MAX_SP_RSZ_OUTPUT_WIDTH		1920
>> +#define STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT		1920
>> +#define STREAM_MIN_RSZ_OUTPUT_WIDTH		32
>> +#define STREAM_MIN_RSZ_OUTPUT_HEIGHT		16
>> +
>> +#define STREAM_MAX_MP_SP_INPUT_WIDTH STREAM_MAX_MP_RSZ_OUTPUT_WIDTH
>> +#define STREAM_MAX_MP_SP_INPUT_HEIGHT STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT
>> +#define STREAM_MIN_MP_SP_INPUT_WIDTH		32
>> +#define STREAM_MIN_MP_SP_INPUT_HEIGHT		32
>> +
>> +/* Get xsubs and ysubs for fourcc formats
>> + *
>> + * @xsubs: horizontal color samples in a 4*4 matrix, for yuv
>> + * @ysubs: vertical color samples in a 4*4 matrix, for yuv
>> + */
>> +static int fcc_xysubs(u32 fcc, u32 *xsubs, u32 *ysubs)
>> +{
>> +	switch (fcc) {
>> +	case V4L2_PIX_FMT_GREY:
>> +	case V4L2_PIX_FMT_YUV444M:
>> +		*xsubs = 1;
>> +		*ysubs = 1;
>> +		break;
>> +	case V4L2_PIX_FMT_YUYV:
>> +	case V4L2_PIX_FMT_YVYU:
>> +	case V4L2_PIX_FMT_VYUY:
>> +	case V4L2_PIX_FMT_YUV422P:
>> +	case V4L2_PIX_FMT_NV16:
>> +	case V4L2_PIX_FMT_NV61:
>> +	case V4L2_PIX_FMT_YVU422M:
>> +		*xsubs = 2;
>> +		*ysubs = 1;
>> +		break;
>> +	case V4L2_PIX_FMT_NV21:
>> +	case V4L2_PIX_FMT_NV12:
>> +	case V4L2_PIX_FMT_NV21M:
>> +	case V4L2_PIX_FMT_NV12M:
>> +	case V4L2_PIX_FMT_YUV420:
>> +	case V4L2_PIX_FMT_YVU420:
>> +		*xsubs = 2;
>> +		*ysubs = 2;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int mbus_code_xysubs(u32 code, u32 *xsubs, u32 *ysubs)
>> +{
>> +	switch (code) {
>> +	case MEDIA_BUS_FMT_YUYV8_2X8:
>> +	case MEDIA_BUS_FMT_YUYV8_1X16:
>> +	case MEDIA_BUS_FMT_YVYU8_1X16:
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +	case MEDIA_BUS_FMT_VYUY8_1X16:
>> +		*xsubs = 2;
>> +		*ysubs = 1;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int mbus_code_sp_in_fmt(u32 code, u32 *format)
>> +{
>> +	switch (code) {
>> +	case MEDIA_BUS_FMT_YUYV8_2X8:
>> +		*format = MI_CTRL_SP_INPUT_YUV422;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct capture_fmt mp_fmts[] = {
>> +	/* yuv422 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_YUYV,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUVINT,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVYU,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUVINT,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_VYUY,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUVINT,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YUV422P,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV16,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV61,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVU422M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 3,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	},
>> +	/* yuv420 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_NV21,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV12,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV21M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 2,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV12M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 2,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_SPLA,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YUV420,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVU420,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	},
>> +	/* yuv444 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_YUV444M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 3,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	},
>> +	/* yuv400 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_GREY,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_MP_WRITE_YUVINT,
>> +	},
>> +	/* raw */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_SRGGB8,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 8 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGRBG8,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 8 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGBRG8,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 8 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SBGGR8,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 8 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SRGGB10,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 10 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGRBG10,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 10 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGBRG10,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 10 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SBGGR10,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 10 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SRGGB12,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 12 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGRBG12,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 12 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SGBRG12,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 12 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_SBGGR12,
>> +		.fmt_type = FMT_BAYER,
>> +		.bpp = { 12 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_MP_WRITE_RAW12,
>> +	},
>> +};
>> +
>> +static const struct capture_fmt sp_fmts[] = {
>> +	/* yuv422 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_YUYV,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_INT,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVYU,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_INT,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_VYUY,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 16 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_INT,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YUV422P,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV16,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV61,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVU422M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 3,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV422,
>> +	},
>> +	/* yuv420 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_NV21,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV12,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV21M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 2,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_NV12M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 16 },
>> +		.cplanes = 2,
>> +		.mplanes = 2,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_SPLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YUV420,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_YVU420,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 1,
>> +		.uv_swap = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV420,
>> +	},
>> +	/* yuv444 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_YUV444M,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8, 8, 8 },
>> +		.cplanes = 3,
>> +		.mplanes = 3,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV444,
>> +	},
>> +	/* yuv400 */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_GREY,
>> +		.fmt_type = FMT_YUV,
>> +		.bpp = { 8 },
>> +		.cplanes = 1,
>> +		.mplanes = 1,
>> +		.uv_swap = 0,
>> +		.write_format = MI_CTRL_SP_WRITE_INT,
>> +		.output_format = MI_CTRL_SP_OUTPUT_YUV400,
>> +	},
>> +	/* rgb */
>> +	{
>> +		.fourcc = V4L2_PIX_FMT_RGB24,
>> +		.fmt_type = FMT_RGB,
>> +		.bpp = { 24 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_RGB888,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_RGB565,
>> +		.fmt_type = FMT_RGB,
>> +		.bpp = { 16 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_RGB565,
>> +	}, {
>> +		.fourcc = V4L2_PIX_FMT_BGR666,
>> +		.fmt_type = FMT_RGB,
>> +		.bpp = { 18 },
>> +		.mplanes = 1,
>> +		.write_format = MI_CTRL_SP_WRITE_PLA,
>> +		.output_format = MI_CTRL_SP_OUTPUT_RGB666,
>> +	},
>> +};
>> +
>> +static struct stream_config rkisp1_mp_stream_config = {
>> +	.fmts = mp_fmts,
>> +	.fmt_size = ARRAY_SIZE(mp_fmts),
>> +	/* constraints */
>> +	.max_rsz_width = STREAM_MAX_MP_RSZ_OUTPUT_WIDTH,
>> +	.max_rsz_height = STREAM_MAX_MP_RSZ_OUTPUT_HEIGHT,
>> +	.min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH,
>> +	.min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT,
>> +	/* registers */
>> +	.rsz = {
>> +		.ctrl = CIF_MRSZ_CTRL,
>> +		.scale_hy = CIF_MRSZ_SCALE_HY,
>> +		.scale_hcr = CIF_MRSZ_SCALE_HCR,
>> +		.scale_hcb = CIF_MRSZ_SCALE_HCB,
>> +		.scale_vy = CIF_MRSZ_SCALE_VY,
>> +		.scale_vc = CIF_MRSZ_SCALE_VC,
>> +		.scale_lut = CIF_MRSZ_SCALE_LUT,
>> +		.scale_lut_addr = CIF_MRSZ_SCALE_LUT_ADDR,
>> +		.scale_hy_shd = CIF_MRSZ_SCALE_HY_SHD,
>> +		.scale_hcr_shd = CIF_MRSZ_SCALE_HCR_SHD,
>> +		.scale_hcb_shd = CIF_MRSZ_SCALE_HCB_SHD,
>> +		.scale_vy_shd = CIF_MRSZ_SCALE_VY_SHD,
>> +		.scale_vc_shd = CIF_MRSZ_SCALE_VC_SHD,
>> +		.phase_hy = CIF_MRSZ_PHASE_HY,
>> +		.phase_hc = CIF_MRSZ_PHASE_HC,
>> +		.phase_vy = CIF_MRSZ_PHASE_VY,
>> +		.phase_vc = CIF_MRSZ_PHASE_VC,
>> +		.ctrl_shd = CIF_MRSZ_CTRL_SHD,
>> +		.phase_hy_shd = CIF_MRSZ_PHASE_HY_SHD,
>> +		.phase_hc_shd = CIF_MRSZ_PHASE_HC_SHD,
>> +		.phase_vy_shd = CIF_MRSZ_PHASE_VY_SHD,
>> +		.phase_vc_shd = CIF_MRSZ_PHASE_VC_SHD,
>> +	},
>> +	.dual_crop = {
>> +		.ctrl = CIF_DUAL_CROP_CTRL,
>> +		.yuvmode_mask = CIF_DUAL_CROP_MP_MODE_YUV,
>> +		.rawmode_mask = CIF_DUAL_CROP_MP_MODE_RAW,
>> +		.h_offset = CIF_DUAL_CROP_M_H_OFFS,
>> +		.v_offset = CIF_DUAL_CROP_M_V_OFFS,
>> +		.h_size = CIF_DUAL_CROP_M_H_SIZE,
>> +		.v_size = CIF_DUAL_CROP_M_V_SIZE,
>> +	},
>> +	.mi = {
>> +		.y_size_init = CIF_MI_MP_Y_SIZE_INIT,
>> +		.cb_size_init = CIF_MI_MP_CB_SIZE_INIT,
>> +		.cr_size_init = CIF_MI_MP_CR_SIZE_INIT,
>> +		.y_base_ad_init = CIF_MI_MP_Y_BASE_AD_INIT,
>> +		.cb_base_ad_init = CIF_MI_MP_CB_BASE_AD_INIT,
>> +		.cr_base_ad_init = CIF_MI_MP_CR_BASE_AD_INIT,
>> +		.y_offs_cnt_init = CIF_MI_MP_Y_OFFS_CNT_INIT,
>> +		.cb_offs_cnt_init = CIF_MI_MP_CB_OFFS_CNT_INIT,
>> +		.cr_offs_cnt_init = CIF_MI_MP_CR_OFFS_CNT_INIT,
>> +	},
>> +};
>> +
>> +static struct stream_config rkisp1_sp_stream_config = {
>> +	.fmts = sp_fmts,
>> +	.fmt_size = ARRAY_SIZE(sp_fmts),
>> +	/* constraints */
>> +	.max_rsz_width = STREAM_MAX_SP_RSZ_OUTPUT_WIDTH,
>> +	.max_rsz_height = STREAM_MAX_SP_RSZ_OUTPUT_HEIGHT,
>> +	.min_rsz_width = STREAM_MIN_RSZ_OUTPUT_WIDTH,
>> +	.min_rsz_height = STREAM_MIN_RSZ_OUTPUT_HEIGHT,
>> +	/* registers */
>> +	.rsz = {
>> +		.ctrl = CIF_SRSZ_CTRL,
>> +		.scale_hy = CIF_SRSZ_SCALE_HY,
>> +		.scale_hcr = CIF_SRSZ_SCALE_HCR,
>> +		.scale_hcb = CIF_SRSZ_SCALE_HCB,
>> +		.scale_vy = CIF_SRSZ_SCALE_VY,
>> +		.scale_vc = CIF_SRSZ_SCALE_VC,
>> +		.scale_lut = CIF_SRSZ_SCALE_LUT,
>> +		.scale_lut_addr = CIF_SRSZ_SCALE_LUT_ADDR,
>> +		.scale_hy_shd = CIF_SRSZ_SCALE_HY_SHD,
>> +		.scale_hcr_shd = CIF_SRSZ_SCALE_HCR_SHD,
>> +		.scale_hcb_shd = CIF_SRSZ_SCALE_HCB_SHD,
>> +		.scale_vy_shd = CIF_SRSZ_SCALE_VY_SHD,
>> +		.scale_vc_shd = CIF_SRSZ_SCALE_VC_SHD,
>> +		.phase_hy = CIF_SRSZ_PHASE_HY,
>> +		.phase_hc = CIF_SRSZ_PHASE_HC,
>> +		.phase_vy = CIF_SRSZ_PHASE_VY,
>> +		.phase_vc = CIF_SRSZ_PHASE_VC,
>> +		.ctrl_shd = CIF_SRSZ_CTRL_SHD,
>> +		.phase_hy_shd = CIF_SRSZ_PHASE_HY_SHD,
>> +		.phase_hc_shd = CIF_SRSZ_PHASE_HC_SHD,
>> +		.phase_vy_shd = CIF_SRSZ_PHASE_VY_SHD,
>> +		.phase_vc_shd = CIF_SRSZ_PHASE_VC_SHD,
>> +	},
>> +	.dual_crop = {
>> +		.ctrl = CIF_DUAL_CROP_CTRL,
>> +		.yuvmode_mask = CIF_DUAL_CROP_SP_MODE_YUV,
>> +		.rawmode_mask = CIF_DUAL_CROP_SP_MODE_RAW,
>> +		.h_offset = CIF_DUAL_CROP_S_H_OFFS,
>> +		.v_offset = CIF_DUAL_CROP_S_V_OFFS,
>> +		.h_size = CIF_DUAL_CROP_S_H_SIZE,
>> +		.v_size = CIF_DUAL_CROP_S_V_SIZE,
>> +	},
>> +	.mi = {
>> +		.y_size_init = CIF_MI_SP_Y_SIZE_INIT,
>> +		.cb_size_init = CIF_MI_SP_CB_SIZE_INIT,
>> +		.cr_size_init = CIF_MI_SP_CR_SIZE_INIT,
>> +		.y_base_ad_init = CIF_MI_SP_Y_BASE_AD_INIT,
>> +		.cb_base_ad_init = CIF_MI_SP_CB_BASE_AD_INIT,
>> +		.cr_base_ad_init = CIF_MI_SP_CR_BASE_AD_INIT,
>> +		.y_offs_cnt_init = CIF_MI_SP_Y_OFFS_CNT_INIT,
>> +		.cb_offs_cnt_init = CIF_MI_SP_CB_OFFS_CNT_INIT,
>> +		.cr_offs_cnt_init = CIF_MI_SP_CR_OFFS_CNT_INIT,
>> +	},
>> +};
>> +
>> +static const
>> +struct capture_fmt *find_fmt(struct rkisp1_stream *stream, const u32 pixelfmt)
>> +{
>> +	const struct capture_fmt *fmt;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < stream->config->fmt_size; i++) {
>> +		fmt = &stream->config->fmts[i];
>> +		if (fmt->fourcc == pixelfmt)
>> +			return fmt;
>> +	}
>> +	return NULL;
>> +}
>> +
>> +/* configure dual-crop unit */
>> +static int rkisp1_config_dcrop(struct rkisp1_stream *stream, bool async)
>> +{
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_rect *dcrop = &stream->dcrop;
>> +	struct v4l2_rect *input_win;
>> +
>> +	/* dual-crop unit get data from isp */
>> +	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
>> +
>> +	if (dcrop->width == input_win->width &&
>> +	    dcrop->height == input_win->height &&
>> +	    dcrop->left == 0 && dcrop->top == 0) {
>> +		disable_dcrop(stream, async);
>> +		v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +			 "stream %d crop disabled\n", stream->id);
>> +		return 0;
>> +	}
>> +
>> +	config_dcrop(stream, dcrop, async);
>> +
>> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +		 "stream %d crop: %dx%d -> %dx%d\n", stream->id,
>> +		 input_win->width, input_win->height,
>> +		 dcrop->width, dcrop->height);
>> +
>> +	return 0;
>> +}
>> +
>> +/* configure scale unit */
>> +static int rkisp1_config_rsz(struct rkisp1_stream *stream, bool async)
>> +{
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_pix_format_mplane output_fmt = stream->out_fmt;
>> +	struct capture_fmt *output_isp_fmt = &stream->out_isp_fmt;
>> +	struct ispsd_out_fmt *input_isp_fmt =
>> +			rkisp1_get_ispsd_out_fmt(&dev->isp_sdev);
>> +	struct v4l2_rect in_y, in_c, out_y, out_c;
>> +	u32 xsubs_in, ysubs_in, xsubs_out, ysubs_out;
>> +
>> +	if (input_isp_fmt->fmt_type == FMT_BAYER)
>> +		goto disable;
>> +
>> +	/* set input and output sizes for scale calculation */
>> +	in_y.width = stream->dcrop.width;
>> +	in_y.height = stream->dcrop.height;
>> +	out_y.width = output_fmt.width;
>> +	out_y.height = output_fmt.height;
>> +
>> +	/* The size of Cb,Cr are related to the format */
>> +	if (mbus_code_xysubs(input_isp_fmt->mbus_code, &xsubs_in, &ysubs_in)) {
>> +		v4l2_err(&dev->v4l2_dev, "Not xsubs/ysubs found\n");
>> +		return -EINVAL;
>> +	}
>> +	in_c.width = in_y.width / xsubs_in;
>> +	in_c.height = in_y.height / ysubs_in;
>> +
>> +	if (output_isp_fmt->fmt_type == FMT_YUV) {
>> +		fcc_xysubs(output_isp_fmt->fourcc, &xsubs_out, &ysubs_out);
>> +		out_c.width = out_y.width / xsubs_out;
>> +		out_c.height = out_y.height / ysubs_out;
>> +	} else {
>> +		out_c.width = out_y.width / xsubs_in;
>> +		out_c.height = out_y.height / ysubs_in;
>> +	}
>> +
>> +	if (in_c.width == out_c.width && in_c.height == out_c.height)
>> +		goto disable;
>> +
>> +	/* set RSZ input and output */
>> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +		 "stream %d rsz/scale: %dx%d -> %dx%d\n",
>> +		 stream->id, stream->dcrop.width, stream->dcrop.height,
>> +		 output_fmt.width, output_fmt.height);
>> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +		 "chroma scaling %dx%d -> %dx%d\n",
>> +		 in_c.width, in_c.height, out_c.width, out_c.height);
>> +
>> +	/* calculate and set scale */
>> +	config_rsz(stream, &in_y, &in_c, &out_y, &out_c, async);
>> +
>> +	if (rkisp1_debug)
>> +		dump_rsz_regs(stream);
>> +
>> +	return 0;
>> +
>> +disable:
>> +	disable_rsz(stream, async);
>> +
>> +	return 0;
>> +}
>> +
>> +/***************************** stream operations*******************************/
>> +
>> +/*
>> + * configure memory interface for mainpath
>> + * This should only be called when stream-on
>> + */
>> +static int mp_config_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +       /*
>> +	* NOTE: plane_fmt[0].sizeimage is total size of all planes for single
>> +	* memory plane formats, so calculate the size explicitly.
>> +	*/
>> +	mi_set_y_size(stream, stream->out_fmt.plane_fmt[0].bytesperline *
>> +			 stream->out_fmt.height);
>> +	mi_set_cb_size(stream, stream->out_fmt.plane_fmt[1].sizeimage);
>> +	mi_set_cr_size(stream, stream->out_fmt.plane_fmt[2].sizeimage);
>> +
>> +	mi_frame_end_int_enable(stream);
>> +	if (stream->out_isp_fmt.uv_swap)
>> +		mp_set_uv_swap(base);
>> +
>> +	config_mi_ctrl(stream);
>> +	mp_mi_ctrl_set_format(base, stream->out_isp_fmt.write_format);
>> +	mp_mi_ctrl_autoupdate_en(base);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * configure memory interface for selfpath
>> + * This should only be called when stream-on
>> + */
>> +static int sp_config_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct capture_fmt *output_isp_fmt = &stream->out_isp_fmt;
>> +	struct ispsd_out_fmt *input_isp_fmt =
>> +			rkisp1_get_ispsd_out_fmt(&dev->isp_sdev);
>> +	u32 sp_in_fmt;
>> +
>> +	if (mbus_code_sp_in_fmt(input_isp_fmt->mbus_code, &sp_in_fmt)) {
>> +		v4l2_err(&dev->v4l2_dev, "Can't find the input format\n");
>> +		return -EINVAL;
>> +	}
>> +       /*
>> +	* NOTE: plane_fmt[0].sizeimage is total size of all planes for single
>> +	* memory plane formats, so calculate the size explicitly.
>> +	*/
>> +	mi_set_y_size(stream, stream->out_fmt.plane_fmt[0].bytesperline *
>> +		      stream->out_fmt.height);
>> +	mi_set_cb_size(stream, stream->out_fmt.plane_fmt[1].sizeimage);
>> +	mi_set_cr_size(stream, stream->out_fmt.plane_fmt[2].sizeimage);
>> +
>> +	sp_set_y_width(base, stream->out_fmt.width);
>> +	sp_set_y_height(base, stream->out_fmt.height);
>> +	sp_set_y_line_length(base, stream->u.sp.y_stride);
>> +
>> +	mi_frame_end_int_enable(stream);
>> +	if (output_isp_fmt->uv_swap)
>> +		sp_set_uv_swap(base);
>> +
>> +	config_mi_ctrl(stream);
>> +	sp_mi_ctrl_set_format(base, stream->out_isp_fmt.write_format |
>> +			      sp_in_fmt | output_isp_fmt->output_format);
>> +
>> +	sp_mi_ctrl_autoupdate_en(base);
>> +
>> +	return 0;
>> +}
>> +
>> +static void mp_enable_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
>> +
>> +	mi_ctrl_mp_disable(base);
>> +	if (isp_fmt->fmt_type == FMT_BAYER)
>> +		mi_ctrl_mpraw_enable(base);
>> +	else if (isp_fmt->fmt_type == FMT_YUV)
>> +		mi_ctrl_mpyuv_enable(base);
>> +}
>> +
>> +static void sp_enable_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	mi_ctrl_spyuv_enable(base);
>> +}
>> +
>> +static void mp_disable_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	mi_ctrl_mp_disable(base);
>> +}
>> +
>> +static void sp_disable_mi(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	mi_ctrl_spyuv_disable(base);
>> +}
>> +
>> +/* Update buffer info to memory interface, it's called in interrupt */
>> +static void update_mi(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
>> +
>> +	/* The dummy space allocated by dma_alloc_coherent is used, we can
>> +	 * throw data to it if there is no available buffer.
>> +	 */
>> +	if (stream->next_buf) {
>> +		mi_set_y_addr(stream,
>> +			stream->next_buf->buff_addr[RKISP1_PLANE_Y]);
>> +		mi_set_cb_addr(stream,
>> +			stream->next_buf->buff_addr[RKISP1_PLANE_CB]);
>> +		mi_set_cr_addr(stream,
>> +			stream->next_buf->buff_addr[RKISP1_PLANE_CR]);
>> +	} else {
>> +		v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
>> +			 "stream %d: to dummy buf\n", stream->id);
>> +		mi_set_y_addr(stream, dummy_buf->dma_addr);
>> +		mi_set_cb_addr(stream, dummy_buf->dma_addr);
>> +		mi_set_cr_addr(stream, dummy_buf->dma_addr);
>> +	}
>> +
>> +	mi_set_y_offset(stream, 0);
>> +	mi_set_cb_offset(stream, 0);
>> +	mi_set_cr_offset(stream, 0);
>> +}
>> +
>> +static void mp_stop_mi(struct rkisp1_stream *stream)
>> +{
>> +	if (!stream->streaming)
>> +		return;
>> +	mi_frame_end_int_clear(stream);
>> +	stream->ops->disable_mi(stream);
>> +}
>> +
>> +static void sp_stop_mi(struct rkisp1_stream *stream)
>> +{
>> +	if (!stream->streaming)
>> +		return;
>> +	mi_frame_end_int_clear(stream);
>> +	stream->ops->disable_mi(stream);
>> +}
>> +
>> +static struct streams_ops rkisp1_mp_streams_ops = {
>> +	.config_mi = mp_config_mi,
>> +	.enable_mi = mp_enable_mi,
>> +	.disable_mi = mp_disable_mi,
>> +	.stop_mi = mp_stop_mi,
>> +	.set_data_path = mp_set_data_path,
>> +	.is_stream_stopped = mp_is_stream_stopped,
>> +};
>> +
>> +static struct streams_ops rkisp1_sp_streams_ops = {
>> +	.config_mi = sp_config_mi,
>> +	.enable_mi = sp_enable_mi,
>> +	.disable_mi = sp_disable_mi,
>> +	.stop_mi = sp_stop_mi,
>> +	.set_data_path = sp_set_data_path,
>> +	.is_stream_stopped = sp_is_stream_stopped,
>> +};
>> +
>> +/*
>> + * This function is called when a frame end come. The next frame
>> + * is processing and we should set up buffer for next-next frame,
>> + * otherwise it will overflow.
>> + */
>> +static int mi_frame_end(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_device *isp_dev = stream->ispdev;
>> +	struct rkisp1_isp_subdev *isp_sd = &isp_dev->isp_sdev;
>> +	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
>> +	unsigned long lock_flags = 0;
>> +	int i = 0;
>> +
>> +	if (stream->curr_buf) {
>> +		/* Dequeue a filled buffer */
>> +		for (i = 0; i < isp_fmt->mplanes; i++) {
>> +			u32 payload_size =
>> +				stream->out_fmt.plane_fmt[i].sizeimage;
>> +			vb2_set_plane_payload(
>> +				&stream->curr_buf->vb.vb2_buf, i,
>> +				payload_size);
>> +		}
>> +		stream->curr_buf->vb.sequence =
>> +				atomic_read(&isp_sd->frm_sync_seq) - 1;
>> +		stream->curr_buf->vb.vb2_buf.timestamp = ktime_get_ns();
>> +		stream->curr_buf->vb.field = V4L2_FIELD_NONE;
>> +		vb2_buffer_done(&stream->curr_buf->vb.vb2_buf,
>> +				VB2_BUF_STATE_DONE);
>> +	}
>> +
>> +	/* Next frame is writing to it */
>> +	stream->curr_buf = stream->next_buf;
>> +	stream->next_buf = NULL;
>> +
>> +	/* Set up an empty buffer for the next-next frame */
>> +	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
>> +	if (!list_empty(&stream->buf_queue)) {
>> +		stream->next_buf = list_first_entry(&stream->buf_queue,
>> +					struct rkisp1_buffer, queue);
>> +		list_del(&stream->next_buf->queue);
>> +	}
>> +
>> +	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
>> +
>> +	update_mi(stream);
>> +
>> +	return 0;
>> +}
>> +
>> +/***************************** vb2 operations*******************************/
>> +
>> +/*
>> + * Set flags and wait, it should stop in interrupt.
>> + * If it didn't, stop it by force.
>> + */
>> +static void rkisp1_stream_stop(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +	int ret;
>> +
>> +	stream->stopping = true;
>> +	ret = wait_event_timeout(stream->done,
>> +				 !stream->streaming,
>> +				 msecs_to_jiffies(1000));
>> +	if (!ret) {
>> +		v4l2_warn(v4l2_dev, "waiting on event return error %d\n", ret);
>> +		stream->ops->stop_mi(stream);
>> +		stream->stopping = false;
>> +		stream->streaming = false;
>> +	}
>> +	disable_dcrop(stream, true);
>> +	disable_rsz(stream, true);
>> +}
>> +
>> +/*
>> + * Most of registers inside rockchip isp1 have shadow register since
>> + * they must be not changed during processing a frame.
>> + * Usually, each sub-module updates its shadow register after
>> + * processing the last pixel of a frame.
>> + */
>> +static int rkisp1_start(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct rkisp1_stream *other = &dev->stream[stream->id ^ 1];
>> +	int ret;
>> +
>> +	stream->ops->set_data_path(base);
>> +	ret = stream->ops->config_mi(stream);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* Set up an buffer for the next frame */
>> +	mi_frame_end(stream);
>> +	stream->ops->enable_mi(stream);
>> +	/* It's safe to config ACTIVE and SHADOW regs for the
>> +	 * first stream. While when the second is starting, do NOT
>> +	 * force_cfg_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 sencond FE maybe corrupt especially
>> +	 * when run at 120fps.
>> +	 */
>> +	if (!other->streaming) {
>> +		force_cfg_update(base);
>> +		mi_frame_end(stream);
>> +	}
>> +	stream->streaming = true;
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_queue_setup(struct vb2_queue *queue,
>> +			      unsigned int *num_buffers,
>> +			      unsigned int *num_planes,
>> +			      unsigned int sizes[],
>> +			      struct device *alloc_devs[])
>> +{
>> +	struct rkisp1_stream *stream = queue->drv_priv;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	const struct v4l2_pix_format_mplane *pixm = &stream->out_fmt;
>> +	const struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
>> +	unsigned int i;
>> +
>> +	*num_planes = isp_fmt->mplanes;
>> +
>> +	for (i = 0; i < isp_fmt->mplanes; i++) {
>> +		const struct v4l2_plane_pix_format *plane_fmt;
>> +
>> +		plane_fmt = &pixm->plane_fmt[i];
>> +		if (sizes[i] && sizes[i] < plane_fmt->sizeimage)
>> +			return -EINVAL;
>> +		sizes[i] = plane_fmt->sizeimage;
>> +	}
>> +
>> +	v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev, "%s count %d, size %d\n",
>> +		 v4l2_type_names[queue->type], *num_buffers, sizes[0]);
>> +
>> +	return 0;
>> +}
> 
> I believe this `queue_setup` function is incomplete. You can see the
> expected behavior at [1].
> 
> In summary, `num_planes` is both an input and a output argument.
> 
> - If `*num_planes != 0`, that means it is a input arg. The driver needs
> to check if the userspace had assigned the correct number of buffers,
> comparing with `isp_fmt->mplanes`. If it the driver should return an
> `-EINVAL`. Also, it will need to check if the `sizes[]` are correctly
> assigned correctly (like you did at `if (sizes[i] && sizes[i] <
> plane_fmt->sizeimage)`)
> 
> - If `*num_planes == 0`, it's an output arg. Now, the driver must set
> `*num_planes` and `sizes[]` according to the format.
> 
> It's looks like you have mixed the two behaviors. You also may want to
> have a look at `jpu_queue_setup()` from `drivers/media/platform/rcar_jpu.c`.
> 
> Thanks!
>     André

Hi André,

Sorry, I missed this review and also some others for some reason, thanks for
the friendly reminder you sent me. I'll properly update in the next version.

Thanks
Helen

> 
> [1]
> https://www.kernel.org/doc/html/latest/media/kapi/v4l2-videobuf2.html#c.vb2_ops
> 
>> +
>> +/*
>> + * The vb2_buffer are stored in rkisp1_buffer, in order to unify
>> + * mplane buffer and none-mplane buffer.
>> + */
>> +static void rkisp1_buf_queue(struct vb2_buffer *vb)
>> +{
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	struct rkisp1_buffer *ispbuf = to_rkisp1_buffer(vbuf);
>> +	struct vb2_queue *queue = vb->vb2_queue;
>> +	struct rkisp1_stream *stream = queue->drv_priv;
>> +	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
>> +	unsigned long lock_flags = 0;
>> +	unsigned int i;
>> +
>> +	memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
>> +	for (i = 0; i < isp_fmt->mplanes; i++)
>> +		ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
>> +
>> +	/* Convert to non-MPLANE */
>> +	if (isp_fmt->mplanes == 1) {
>> +		ispbuf->buff_addr[RKISP1_PLANE_CB] =
>> +			ispbuf->buff_addr[RKISP1_PLANE_Y] +
>> +			stream->out_fmt.plane_fmt[RKISP1_PLANE_Y].bytesperline *
>> +			stream->out_fmt.height;
>> +		ispbuf->buff_addr[RKISP1_PLANE_CR] =
>> +			ispbuf->buff_addr[RKISP1_PLANE_CB] +
>> +			stream->out_fmt.plane_fmt[RKISP1_PLANE_CB].sizeimage;
>> +	}
>> +	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
>> +
>> +	/* XXX: replace dummy to speed up  */
>> +	if (stream->streaming &&
>> +	    stream->next_buf == NULL &&
>> +	    atomic_read(&stream->ispdev->isp_sdev.frm_sync_seq) == 0) {
>> +		stream->next_buf = ispbuf;
>> +		update_mi(stream);
>> +	} else {
>> +		list_add_tail(&ispbuf->queue, &stream->buf_queue);
>> +	}
>> +	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
>> +}
>> +
>> +static int rkisp1_buf_prepare(struct vb2_buffer *vb)
>> +{
>> +	struct vb2_queue *queue = vb->vb2_queue;
>> +	struct rkisp1_stream *stream = queue->drv_priv;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct capture_fmt *isp_fmt = &stream->out_isp_fmt;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < isp_fmt->mplanes; i++) {
>> +		unsigned long size = stream->out_fmt.plane_fmt[i].sizeimage;
>> +
>> +		if (isp_fmt->mplanes > 1 && i == 0)
>> +			size = stream->out_fmt.plane_fmt[RKISP1_PLANE_Y].bytesperline *
>> +				stream->out_fmt.height;
>> +
>> +		if (vb2_plane_size(vb, i) < size) {
>> +			v4l2_err(&dev->v4l2_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 int rkisp1_create_dummy_buf(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +
>> +	/* get a maximum size */
>> +	dummy_buf->size = max3(stream->out_fmt.plane_fmt[0].bytesperline *
>> +		stream->out_fmt.height,
>> +		stream->out_fmt.plane_fmt[1].sizeimage,
>> +		stream->out_fmt.plane_fmt[2].sizeimage);
>> +
>> +	dummy_buf->vaddr = dma_alloc_coherent(dev->dev, dummy_buf->size,
>> +					      &dummy_buf->dma_addr,
>> +					      GFP_KERNEL);
>> +	if (!dummy_buf->vaddr) {
>> +		v4l2_err(&dev->v4l2_dev,
>> +			 "Failed to allocate the memory for dummy buffer\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void rkisp1_destroy_dummy_buf(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +
>> +	dma_free_coherent(dev->dev, dummy_buf->size,
>> +			  dummy_buf->vaddr, dummy_buf->dma_addr);
>> +}
>> +
>> +static void rkisp1_return_all_buffers(struct rkisp1_stream *stream,
>> +					enum vb2_buffer_state state)
>> +{
>> +	unsigned long lock_flags = 0;
>> +	struct rkisp1_buffer *buf;
>> +
>> +	spin_lock_irqsave(&stream->vbq_lock, lock_flags);
>> +	if (stream->curr_buf) {
>> +		list_add_tail(&stream->curr_buf->queue, &stream->buf_queue);
>> +		stream->curr_buf = NULL;
>> +	}
>> +	if (stream->next_buf) {
>> +		list_add_tail(&stream->next_buf->queue, &stream->buf_queue);
>> +		stream->next_buf = NULL;
>> +	}
>> +	while (!list_empty(&stream->buf_queue)) {
>> +		buf = list_first_entry(&stream->buf_queue,
>> +				       struct rkisp1_buffer, queue);
>> +		list_del(&buf->queue);
>> +		vb2_buffer_done(&buf->vb.vb2_buf, state);
>> +	}
>> +	spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
>> +}
>> +
>> +static void rkisp1_stop_streaming(struct vb2_queue *queue)
>> +{
>> +	struct rkisp1_stream *stream = queue->drv_priv;
>> +	struct rkisp1_vdev_node *node = &stream->vnode;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +	int ret;
>> +
>> +	rkisp1_stream_stop(stream);
>> +	/* call to the other devices */
>> +	media_pipeline_stop(&node->vdev.entity);
>> +	ret = dev->pipe.set_stream(&dev->pipe, false);
>> +	if (ret < 0)
>> +		v4l2_err(v4l2_dev, "pipeline stream-off failed error:%d\n",
>> +			 ret);
>> +
>> +	/* release buffers */
>> +	rkisp1_return_all_buffers(stream, VB2_BUF_STATE_ERROR);
>> +
>> +	ret = dev->pipe.close(&dev->pipe);
>> +	if (ret < 0)
>> +		v4l2_err(v4l2_dev, "pipeline close failed error:%d\n", ret);
>> +
>> +	rkisp1_destroy_dummy_buf(stream);
>> +}
>> +
>> +static int rkisp1_stream_start(struct rkisp1_stream *stream)
>> +{
>> +	struct v4l2_device *v4l2_dev = &stream->ispdev->v4l2_dev;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct rkisp1_stream *other = &dev->stream[stream->id ^ 1];
>> +	bool async = false;
>> +	int ret;
>> +
>> +	if (other->streaming)
>> +		async = true;
>> +
>> +	ret = rkisp1_config_rsz(stream, async);
>> +	if (ret < 0) {
>> +		v4l2_err(v4l2_dev, "config rsz failed with error %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	/*
>> +	 * can't be async now, otherwise the latter started stream fails to
>> +	 * produce mi interrupt.
>> +	 */
>> +	ret = rkisp1_config_dcrop(stream, false);
>> +	if (ret < 0) {
>> +		v4l2_err(v4l2_dev, "config dcrop failed with error %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	return rkisp1_start(stream);
>> +}
>> +
>> +static int
>> +rkisp1_start_streaming(struct vb2_queue *queue, unsigned int count)
>> +{
>> +	struct rkisp1_stream *stream = queue->drv_priv;
>> +	struct rkisp1_vdev_node *node = &stream->vnode;
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +	int ret = -EINVAL;
>> +
>> +	if (WARN_ON(stream->streaming))
>> +		goto return_queued_buf;
>> +
>> +	ret = rkisp1_create_dummy_buf(stream);
>> +	if (ret < 0)
>> +		goto return_queued_buf;
>> +
>> +	/* enable clocks/power-domains */
>> +	ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
>> +	if (ret < 0) {
>> +		v4l2_err(v4l2_dev, "open cif pipeline failed %d\n", ret);
>> +		goto destroy_dummy_buf;
>> +	}
>> +
>> +	/* configure stream hardware to start */
>> +	ret = rkisp1_stream_start(stream);
>> +	if (ret < 0) {
>> +		v4l2_err(v4l2_dev, "start streaming failed\n");
>> +		goto close_pipe;
>> +	}
>> +
>> +	/* start sub-devices */
>> +	ret = dev->pipe.set_stream(&dev->pipe, true);
>> +	if (ret < 0)
>> +		goto stop_stream;
>> +
>> +	ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
>> +	if (ret < 0) {
>> +		v4l2_err(&dev->v4l2_dev, "start pipeline failed %d\n", ret);
>> +		goto pipe_stream_off;
>> +	}
>> +
>> +	return 0;
>> +
>> +pipe_stream_off:
>> +	dev->pipe.set_stream(&dev->pipe, false);
>> +stop_stream:
>> +	rkisp1_stream_stop(stream);
>> +close_pipe:
>> +	dev->pipe.close(&dev->pipe);
>> +destroy_dummy_buf:
>> +	rkisp1_destroy_dummy_buf(stream);
>> +return_queued_buf:
>> +	rkisp1_return_all_buffers(stream, VB2_BUF_STATE_QUEUED);
>> +
>> +	return ret;
>> +}
>> +
>> +static struct vb2_ops rkisp1_vb2_ops = {
>> +	.queue_setup = rkisp1_queue_setup,
>> +	.buf_queue = rkisp1_buf_queue,
>> +	.buf_prepare = rkisp1_buf_prepare,
>> +	.wait_prepare = vb2_ops_wait_prepare,
>> +	.wait_finish = vb2_ops_wait_finish,
>> +	.stop_streaming = rkisp1_stop_streaming,
>> +	.start_streaming = rkisp1_start_streaming,
>> +};
>> +
>> +static int rkisp_init_vb2_queue(struct vb2_queue *q,
>> +				struct rkisp1_stream *stream,
>> +				enum v4l2_buf_type buf_type)
>> +{
>> +	struct rkisp1_vdev_node *node;
>> +
>> +	node = queue_to_node(q);
>> +
>> +	q->type = buf_type;
>> +	q->io_modes = VB2_MMAP | VB2_DMABUF;
>> +	q->drv_priv = stream;
>> +	q->ops = &rkisp1_vb2_ops;
>> +	q->mem_ops = &vb2_dma_contig_memops;
>> +	q->buf_struct_size = sizeof(struct rkisp1_buffer);
>> +	q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN;
>> +	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
>> +	q->lock = &node->vlock;
>> +	q->dev = stream->ispdev->dev;
>> +
>> +	return vb2_queue_init(q);
>> +}
>> +
>> +static void rkisp1_set_fmt(struct rkisp1_stream *stream,
>> +			   struct v4l2_pix_format_mplane *pixm,
>> +			   bool try)
>> +{
>> +	const struct capture_fmt *fmt;
>> +	const struct stream_config *config = stream->config;
>> +	struct rkisp1_stream *other_stream =
>> +			&stream->ispdev->stream[!stream->id];
>> +	unsigned int imagsize = 0;
>> +	unsigned int planes;
>> +	u32 xsubs = 1, ysubs = 1;
>> +	unsigned int i;
>> +
>> +	fmt = find_fmt(stream, pixm->pixelformat);
>> +	if (!fmt) {
>> +		fmt = config->fmts;
>> +		pixm->pixelformat = fmt->fourcc;
>> +	}
>> +
>> +	/* do checks on resolution */
>> +	pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width,
>> +			      config->max_rsz_width);
>> +	pixm->height = clamp_t(u32, pixm->height, config->min_rsz_height,
>> +			      config->max_rsz_height);
>> +	pixm->num_planes = fmt->mplanes;
>> +	pixm->field = V4L2_FIELD_NONE;
>> +	pixm->colorspace = V4L2_COLORSPACE_DEFAULT;
>> +	pixm->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> +	/* get quantization from ispsd */
>> +	pixm->quantization = stream->ispdev->isp_sdev.quantization;
>> +
>> +	/* output full range by default, take effect in isp_params */
>> +	if (!pixm->quantization)
>> +		pixm->quantization = V4L2_QUANTIZATION_FULL_RANGE;
>> +	/* can not change quantization when stream-on */
>> +	if (other_stream->streaming)
>> +		pixm->quantization = other_stream->out_fmt.quantization;
>> +
>> +	/* calculate size */
>> +	fcc_xysubs(fmt->fourcc, &xsubs, &ysubs);
>> +	planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
>> +	for (i = 0; i < planes; i++) {
>> +		struct v4l2_plane_pix_format *plane_fmt;
>> +		int width, height, bytesperline;
>> +
>> +		plane_fmt = pixm->plane_fmt + i;
>> +		width = pixm->width / (i ? xsubs : 1);
>> +		height = pixm->height / (i ? ysubs : 1);
>> +
>> +		bytesperline = width * DIV_ROUND_UP(fmt->bpp[i], 8);
>> +		/* stride is only available for sp stream and y plane */
>> +		if (stream->id != RKISP1_STREAM_SP || i != 0 ||
>> +		    plane_fmt->bytesperline < bytesperline)
>> +			plane_fmt->bytesperline = bytesperline;
>> +
>> +		plane_fmt->sizeimage = plane_fmt->bytesperline * height;
>> +
>> +		imagsize += plane_fmt->sizeimage;
>> +	}
>> +
>> +	/* convert to non-MPLANE format.
>> +	 * it's important since we want to unify none-MPLANE
>> +	 * and MPLANE.
>> +	 */
>> +	if (fmt->mplanes == 1)
>> +		pixm->plane_fmt[0].sizeimage = imagsize;
>> +
>> +	if (!try) {
>> +		stream->out_isp_fmt = *fmt;
>> +		stream->out_fmt = *pixm;
>> +
>> +		if (stream->id == RKISP1_STREAM_SP) {
>> +			stream->u.sp.y_stride =
>> +				pixm->plane_fmt[0].bytesperline /
>> +				DIV_ROUND_UP(fmt->bpp[0], 8);
>> +		} else {
>> +			stream->u.mp.raw_enable = (fmt->fmt_type == FMT_BAYER);
>> +		}
>> +		v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
>> +			 "%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
>> +			 stream->id, pixm->width, pixm->height,
>> +			 stream->out_fmt.width, stream->out_fmt.height);
>> +	}
>> +}
>> +
>> +/************************* v4l2_file_operations***************************/
>> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
>> +{
>> +	struct rkisp1_stream *stream = &dev->stream[id];
>> +	struct v4l2_pix_format_mplane pixm;
>> +
>> +	memset(stream, 0, sizeof(*stream));
>> +	stream->id = id;
>> +	stream->ispdev = dev;
>> +
>> +	INIT_LIST_HEAD(&stream->buf_queue);
>> +	init_waitqueue_head(&stream->done);
>> +	spin_lock_init(&stream->vbq_lock);
>> +	if (stream->id == RKISP1_STREAM_SP) {
>> +		stream->ops = &rkisp1_sp_streams_ops;
>> +		stream->config = &rkisp1_sp_stream_config;
>> +	} else {
>> +		stream->ops = &rkisp1_mp_streams_ops;
>> +		stream->config = &rkisp1_mp_stream_config;
>> +	}
>> +
>> +	stream->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(stream, &pixm, false);
>> +
>> +	stream->dcrop.left = 0;
>> +	stream->dcrop.top = 0;
>> +	stream->dcrop.width = RKISP1_DEFAULT_WIDTH;
>> +	stream->dcrop.height = RKISP1_DEFAULT_HEIGHT;
>> +}
>> +
>> +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,
>> +};
>> +
>> +/*
>> + * mp and sp v4l2_ioctl_ops
>> + */
>> +
>> +static int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh,
>> +					 struct v4l2_format *f)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +
>> +	rkisp1_set_fmt(stream, &f->fmt.pix_mp, true);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv,
>> +					  struct v4l2_fmtdesc *f)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +	const struct capture_fmt *fmt = NULL;
>> +
>> +	if (f->index >= stream->config->fmt_size)
>> +		return -EINVAL;
>> +
>> +	fmt = &stream->config->fmts[f->index];
>> +	f->pixelformat = fmt->fourcc;
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_s_fmt_vid_cap_mplane(struct file *file,
>> +				       void *priv, struct v4l2_format *f)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +	struct video_device *vdev = &stream->vnode.vdev;
>> +	struct rkisp1_vdev_node *node = vdev_to_node(vdev);
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +
>> +	if (vb2_is_busy(&node->buf_queue)) {
>> +		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
>> +		return -EBUSY;
>> +	}
>> +
>> +	rkisp1_set_fmt(stream, &f->fmt.pix_mp, false);
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh,
>> +				       struct v4l2_format *f)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +
>> +	f->fmt.pix_mp = stream->out_fmt;
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_g_selection(struct file *file, void *prv,
>> +			      struct v4l2_selection *sel)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_rect *dcrop = &stream->dcrop;
>> +	struct v4l2_rect *input_win;
>> +
>> +	if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
>> +		return -EINVAL;
>> +
>> +	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
>> +
>> +	switch (sel->target) {
>> +	case V4L2_SEL_TGT_CROP_BOUNDS:
>> +		sel->r.width = input_win->width;
>> +		sel->r.height = input_win->height;
>> +		sel->r.left = 0;
>> +		sel->r.top = 0;
>> +		break;
>> +	case V4L2_SEL_TGT_CROP:
>> +		sel->r = *dcrop;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static struct v4l2_rect *rkisp1_update_crop(struct rkisp1_stream *stream,
>> +					    struct v4l2_rect *sel,
>> +					    const struct v4l2_rect *in)
>> +{
>> +	/* Not crop for MP bayer raw data */
>> +	if (stream->id == RKISP1_STREAM_MP &&
>> +	    stream->out_isp_fmt.fmt_type == FMT_BAYER) {
>> +		sel->left = 0;
>> +		sel->top = 0;
>> +		sel->width = in->width;
>> +		sel->height = in->height;
>> +		return sel;
>> +	}
>> +
>> +	sel->left = ALIGN(sel->left, 2);
>> +	sel->width = ALIGN(sel->width, 2);
>> +	sel->left = clamp_t(u32, sel->left, 0,
>> +			    in->width - STREAM_MIN_MP_SP_INPUT_WIDTH);
>> +	sel->top = clamp_t(u32, sel->top, 0,
>> +			   in->height - STREAM_MIN_MP_SP_INPUT_HEIGHT);
>> +	sel->width = clamp_t(u32, sel->width, STREAM_MIN_MP_SP_INPUT_WIDTH,
>> +			     in->width - sel->left);
>> +	sel->height = clamp_t(u32, sel->height, STREAM_MIN_MP_SP_INPUT_HEIGHT,
>> +			      in->height - sel->top);
>> +	return sel;
>> +}
>> +
>> +static int rkisp1_s_selection(struct file *file, void *prv,
>> +			      struct v4l2_selection *sel)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +	struct video_device *vdev = &stream->vnode.vdev;
>> +	struct rkisp1_vdev_node *node = vdev_to_node(vdev);
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_rect *dcrop = &stream->dcrop;
>> +	const struct v4l2_rect *input_win;
>> +
>> +	if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
>> +		return -EINVAL;
>> +
>> +	if (vb2_is_busy(&node->buf_queue)) {
>> +		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
>> +		return -EBUSY;
>> +	}
>> +
>> +	input_win = rkisp1_get_isp_sd_win(&dev->isp_sdev);
>> +
>> +	if (sel->target != V4L2_SEL_TGT_CROP)
>> +		return -EINVAL;
>> +
>> +	if (sel->flags != 0)
>> +		return -EINVAL;
>> +
>> +	if (sel->target == V4L2_SEL_TGT_CROP) {
>> +		*dcrop = *rkisp1_update_crop(stream, &sel->r, input_win);
>> +		v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
>> +			 "stream %d crop(%d,%d)/%dx%d\n", stream->id,
>> +			 dcrop->left, dcrop->top, dcrop->width, dcrop->height);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_querycap(struct file *file, void *priv,
>> +			   struct v4l2_capability *cap)
>> +{
>> +	struct rkisp1_stream *stream = video_drvdata(file);
>> +	struct device *dev = stream->ispdev->dev;
>> +
>> +	strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
>> +	strscpy(cap->card, dev->driver->name, sizeof(cap->card));
>> +	strscpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
>> +
>> +	return 0;
>> +}
>> +
>> +static int rkisp1_vdev_link_validate(struct media_link *link)
>> +{
>> +	struct v4l2_subdev *sd =
>> +		media_entity_to_v4l2_subdev(link->source->entity);
>> +	struct rkisp1_isp_subdev *isp_sd = sd_to_isp_sd(sd);
>> +	struct video_device *vdev =
>> +		media_entity_to_video_device(link->sink->entity);
>> +	struct rkisp1_stream *stream = video_get_drvdata(vdev);
>> +
>> +	if (stream->out_isp_fmt.fmt_type != isp_sd->out_fmt.fmt_type) {
>> +		v4l2_err(vdev->v4l2_dev,
>> +			 "format type mismatch in link '%s:%d->%s:%d'\n",
>> +			 link->source->entity->name, link->source->index,
>> +			 link->sink->entity->name, link->sink->index);
>> +		return -EPIPE;
>> +	}
>> +	return 0;
>> +}
>> +
>> +static const struct media_entity_operations rkisp1_isp_vdev_media_ops = {
>> +	.link_validate = rkisp1_vdev_link_validate,
>> +};
>> +
>> +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_s_selection = rkisp1_s_selection,
>> +	.vidioc_g_selection = rkisp1_g_selection,
>> +	.vidioc_querycap = rkisp1_querycap,
>> +	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
>> +	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
>> +};
>> +
>> +static void rkisp1_unregister_stream_vdev(struct rkisp1_stream *stream)
>> +{
>> +	media_entity_cleanup(&stream->vnode.vdev.entity);
>> +	video_unregister_device(&stream->vnode.vdev);
>> +}
>> +
>> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev)
>> +{
>> +	struct rkisp1_stream *mp_stream = &dev->stream[RKISP1_STREAM_MP];
>> +	struct rkisp1_stream *sp_stream = &dev->stream[RKISP1_STREAM_SP];
>> +
>> +	rkisp1_unregister_stream_vdev(mp_stream);
>> +	rkisp1_unregister_stream_vdev(sp_stream);
>> +}
>> +
>> +static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
>> +{
>> +	struct rkisp1_device *dev = stream->ispdev;
>> +	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
>> +	struct video_device *vdev = &stream->vnode.vdev;
>> +	struct rkisp1_vdev_node *node;
>> +	int ret;
>> +
>> +	strscpy(vdev->name,
>> +		stream->id == RKISP1_STREAM_SP ? SP_VDEV_NAME : MP_VDEV_NAME,
>> +		sizeof(vdev->name));
>> +	node = 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;
>> +	vdev->entity.ops = &rkisp1_isp_vdev_media_ops;
>> +	video_set_drvdata(vdev, stream);
>> +	vdev->vfl_dir = VFL_DIR_RX;
>> +	node->pad.flags = MEDIA_PAD_FL_SINK;
>> +
>> +	rkisp_init_vb2_queue(&node->buf_queue, stream,
>> +			     V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
>> +	vdev->queue = &node->buf_queue;
>> +
>> +	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
>> +	if (ret < 0) {
>> +		v4l2_err(v4l2_dev,
>> +			 "video_register_device failed with error %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
>> +	if (ret < 0)
>> +		goto unreg;
>> +
>> +	return 0;
>> +unreg:
>> +	video_unregister_device(vdev);
>> +	return ret;
>> +}
>> +
>> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev)
>> +{
>> +	struct rkisp1_stream *stream;
>> +	unsigned int i, j;
>> +	int ret;
>> +
>> +	for (i = 0; i < RKISP1_MAX_STREAM; i++) {
>> +		stream = &dev->stream[i];
>> +		stream->ispdev = dev;
>> +		ret = rkisp1_register_stream_vdev(stream);
>> +		if (ret < 0)
>> +			goto err;
>> +	}
>> +
>> +	return 0;
>> +err:
>> +	for (j = 0; j < i; j++) {
>> +		stream = &dev->stream[j];
>> +		rkisp1_unregister_stream_vdev(stream);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +/****************  Interrupter Handler ****************/
>> +
>> +void rkisp1_mi_isr(u32 mis_val, struct rkisp1_device *dev)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(dev->stream); ++i) {
>> +		struct rkisp1_stream *stream = &dev->stream[i];
>> +
>> +		if (!(mis_val & CIF_MI_FRAME(stream)))
>> +			continue;
>> +
>> +		mi_frame_end_int_clear(stream);
>> +
>> +		if (stream->stopping) {
>> +			/*
>> +			 * 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_mi() takes effect at the next
>> +			 * frame end that sync the configurations to shadow
>> +			 * regs.
>> +			 */
>> +			if (stream->ops->is_stream_stopped(dev->base_addr)) {
>> +				stream->stopping = false;
>> +				stream->streaming = false;
>> +				wake_up(&stream->done);
>> +			} else {
>> +				stream->ops->stop_mi(stream);
>> +			}
>> +		} else {
>> +			mi_frame_end(stream);
>> +		}
>> +	}
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/capture.h b/drivers/media/platform/rockchip/isp1/capture.h
>> new file mode 100644
>> index 000000000000..aa2dcce407be
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/capture.h
>> @@ -0,0 +1,164 @@
>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#ifndef _RKISP1_PATH_VIDEO_H
>> +#define _RKISP1_PATH_VIDEO_H
>> +
>> +#include "common.h"
>> +
>> +struct rkisp1_stream;
>> +
>> +/*
>> + * @fourcc: pixel format
>> + * @mbus_code: pixel format over bus
>> + * @fmt_type: helper filed for pixel format
>> + * @bpp: bits per pixel
>> + * @bayer_pat: bayer patten type
>> + * @cplanes: number of colour planes
>> + * @mplanes: number of stored memory planes
>> + * @uv_swap: if cb cr swaped, for yuv
>> + * @write_format: defines how YCbCr self picture data is written to memory
>> + * @input_format: defines sp input format
>> + * @output_format: defines sp output format
>> + */
>> +struct capture_fmt {
>> +	u32 fourcc;
>> +	u32 mbus_code;
>> +	u8 fmt_type;
>> +	u8 cplanes;
>> +	u8 mplanes;
>> +	u8 uv_swap;
>> +	u32 write_format;
>> +	u32 output_format;
>> +	u8 bpp[VIDEO_MAX_PLANES];
>> +};
>> +
>> +enum rkisp1_sp_inp {
>> +	RKISP1_SP_INP_ISP,
>> +	RKISP1_SP_INP_DMA_SP,
>> +	RKISP1_SP_INP_MAX
>> +};
>> +
>> +struct rkisp1_stream_sp {
>> +	int y_stride;
>> +	enum rkisp1_sp_inp input_sel;
>> +};
>> +
>> +struct rkisp1_stream_mp {
>> +	bool raw_enable;
>> +};
>> +
>> +/* Different config between selfpath and mainpath */
>> +struct stream_config {
>> +	const struct capture_fmt *fmts;
>> +	int fmt_size;
>> +	/* 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;
>> +	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;
>> +};
>> +
>> +/* Different reg ops between selfpath and mainpath */
>> +struct streams_ops {
>> +	int (*config_mi)(struct rkisp1_stream *stream);
>> +	void (*stop_mi)(struct rkisp1_stream *stream);
>> +	void (*enable_mi)(struct rkisp1_stream *stream);
>> +	void (*disable_mi)(struct rkisp1_stream *stream);
>> +	void (*set_data_path)(void __iomem *base);
>> +	bool (*is_stream_stopped)(void __iomem *base);
>> +};
>> +
>> +/*
>> + * struct rkisp1_stream - ISP capture video device
>> + *
>> + * @out_isp_fmt: output isp format
>> + * @out_fmt: output buffer size
>> + * @dcrop: coordinates of dual-crop
>> + *
>> + * @vbq_lock: lock to protect buf_queue
>> + * @buf_queue: queued buffer list
>> + * @dummy_buf: dummy space to store dropped data
>> + *
>> + * rkisp1 use shadowsock registers, so it need two buffer at a time
>> + * @curr_buf: the buffer used for current frame
>> + * @next_buf: the buffer used for next frame
>> + */
>> +struct rkisp1_stream {
>> +	unsigned id:1;
>> +	struct rkisp1_device *ispdev;
>> +	struct rkisp1_vdev_node vnode;
>> +	struct capture_fmt out_isp_fmt;
>> +	struct v4l2_pix_format_mplane out_fmt;
>> +	struct v4l2_rect dcrop;
>> +	struct streams_ops *ops;
>> +	struct stream_config *config;
>> +	spinlock_t vbq_lock;
>> +	struct list_head buf_queue;
>> +	struct rkisp1_dummy_buffer dummy_buf;
>> +	struct rkisp1_buffer *curr_buf;
>> +	struct rkisp1_buffer *next_buf;
>> +	bool streaming;
>> +	bool stopping;
>> +	wait_queue_head_t done;
>> +	union {
>> +		struct rkisp1_stream_sp sp;
>> +		struct rkisp1_stream_mp mp;
>> +	} u;
>> +};
>> +
>> +void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev);
>> +int rkisp1_register_stream_vdevs(struct rkisp1_device *dev);
>> +void rkisp1_mi_isr(u32 mis_val, struct rkisp1_device *dev);
>> +void rkisp1_stream_init(struct rkisp1_device *dev, u32 id);
>> +
>> +#endif /* _RKISP1_PATH_VIDEO_H */
>> diff --git a/drivers/media/platform/rockchip/isp1/regs.c b/drivers/media/platform/rockchip/isp1/regs.c
>> new file mode 100644
>> index 000000000000..7d1d0c8aed81
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/regs.c
>> @@ -0,0 +1,223 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#include <media/v4l2-common.h>
>> +
>> +#include "regs.h"
>> +
>> +void disable_dcrop(struct rkisp1_stream *stream, bool async)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
>> +	u32 dc_ctrl = readl(dc_ctrl_addr);
>> +	u32 mask = ~(stream->config->dual_crop.yuvmode_mask |
>> +			stream->config->dual_crop.rawmode_mask);
>> +	u32 val = dc_ctrl & mask;
>> +
>> +	if (async)
>> +		val |= CIF_DUAL_CROP_GEN_CFG_UPD;
>> +	else
>> +		val |= CIF_DUAL_CROP_CFG_UPD;
>> +	writel(val, dc_ctrl_addr);
>> +}
>> +
>> +void
>> +config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect, bool async)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
>> +	u32 dc_ctrl = readl(dc_ctrl_addr);
>> +
>> +	writel(rect->left, base + stream->config->dual_crop.h_offset);
>> +	writel(rect->top, base + stream->config->dual_crop.v_offset);
>> +	writel(rect->width, base + stream->config->dual_crop.h_size);
>> +	writel(rect->height, base + stream->config->dual_crop.v_size);
>> +	dc_ctrl |= stream->config->dual_crop.yuvmode_mask;
>> +	if (async)
>> +		dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
>> +	else
>> +		dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
>> +	writel(dc_ctrl, dc_ctrl_addr);
>> +}
>> +
>> +void dump_rsz_regs(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	pr_info("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",
>> +		readl(base + stream->config->rsz.ctrl),
>> +		readl(base + stream->config->rsz.ctrl_shd),
>> +		readl(base + stream->config->rsz.scale_hy),
>> +		readl(base + stream->config->rsz.scale_hy_shd),
>> +		readl(base + stream->config->rsz.scale_hcb),
>> +		readl(base + stream->config->rsz.scale_hcb_shd),
>> +		readl(base + stream->config->rsz.scale_hcr),
>> +		readl(base + stream->config->rsz.scale_hcr_shd),
>> +		readl(base + stream->config->rsz.scale_vy),
>> +		readl(base + stream->config->rsz.scale_vy_shd),
>> +		readl(base + stream->config->rsz.scale_vc),
>> +		readl(base + stream->config->rsz.scale_vc_shd),
>> +		readl(base + stream->config->rsz.phase_hy),
>> +		readl(base + stream->config->rsz.phase_hy_shd),
>> +		readl(base + stream->config->rsz.phase_hc),
>> +		readl(base + stream->config->rsz.phase_hc_shd),
>> +		readl(base + stream->config->rsz.phase_vy),
>> +		readl(base + stream->config->rsz.phase_vy_shd),
>> +		readl(base + stream->config->rsz.phase_vc),
>> +		readl(base + stream->config->rsz.phase_vc_shd));
>> +}
>> +
>> +static void update_rsz_shadow(struct rkisp1_stream *stream, bool async)
>> +{
>> +	void __iomem *addr =
>> +		stream->ispdev->base_addr + stream->config->rsz.ctrl;
>> +	u32 ctrl_cfg = readl(addr);
>> +
>> +	if (async)
>> +		writel(CIF_RSZ_CTRL_CFG_UPD_AUTO | ctrl_cfg, addr);
>> +	else
>> +		writel(CIF_RSZ_CTRL_CFG_UPD | ctrl_cfg, addr);
>> +}
>> +
>> +static void set_scale(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +		      struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +		      struct v4l2_rect *out_c)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *scale_hy_addr = base + stream->config->rsz.scale_hy;
>> +	void __iomem *scale_hcr_addr = base + stream->config->rsz.scale_hcr;
>> +	void __iomem *scale_hcb_addr = base + stream->config->rsz.scale_hcb;
>> +	void __iomem *scale_vy_addr = base + stream->config->rsz.scale_vy;
>> +	void __iomem *scale_vc_addr = base + stream->config->rsz.scale_vc;
>> +	void __iomem *rsz_ctrl_addr = base + stream->config->rsz.ctrl;
>> +	u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0;
>> +
>> +	if (in_y->width < out_y->width) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
>> +				CIF_RSZ_CTRL_SCALE_HY_UP;
>> +		scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(out_y->width - 1);
>> +		writel(scale_hy, scale_hy_addr);
>> +	} else if (in_y->width > out_y->width) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
>> +		scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(in_y->width - 1) + 1;
>> +		writel(scale_hy, scale_hy_addr);
>> +	}
>> +	if (in_c->width < out_c->width) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
>> +				CIF_RSZ_CTRL_SCALE_HC_UP;
>> +		scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(out_c->width - 1);
>> +		writel(scale_hc, scale_hcb_addr);
>> +		writel(scale_hc, scale_hcr_addr);
>> +	} else if (in_c->width > out_c->width) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
>> +		scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(in_c->width - 1) + 1;
>> +		writel(scale_hc, scale_hcb_addr);
>> +		writel(scale_hc, scale_hcr_addr);
>> +	}
>> +
>> +	if (in_y->height < out_y->height) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
>> +				CIF_RSZ_CTRL_SCALE_VY_UP;
>> +		scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(out_y->height - 1);
>> +		writel(scale_vy, scale_vy_addr);
>> +	} else if (in_y->height > out_y->height) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
>> +		scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(in_y->height - 1) + 1;
>> +		writel(scale_vy, scale_vy_addr);
>> +	}
>> +
>> +	if (in_c->height < out_c->height) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
>> +				CIF_RSZ_CTRL_SCALE_VC_UP;
>> +		scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(out_c->height - 1);
>> +		writel(scale_vc, scale_vc_addr);
>> +	} else if (in_c->height > out_c->height) {
>> +		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
>> +		scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
>> +				(in_c->height - 1) + 1;
>> +		writel(scale_vc, scale_vc_addr);
>> +	}
>> +
>> +	writel(rsz_ctrl, rsz_ctrl_addr);
>> +}
>> +
>> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +		struct v4l2_rect *out_c, bool async)
>> +{
>> +	void __iomem *base_addr = stream->ispdev->base_addr;
>> +	unsigned int i;
>> +
>> +	/* No phase offset */
>> +	writel(0, base_addr + stream->config->rsz.phase_hy);
>> +	writel(0, base_addr + stream->config->rsz.phase_hc);
>> +	writel(0, base_addr + stream->config->rsz.phase_vy);
>> +	writel(0, base_addr + stream->config->rsz.phase_vc);
>> +
>> +	/* Linear interpolation */
>> +	for (i = 0; i < 64; i++) {
>> +		writel(i, base_addr + stream->config->rsz.scale_lut_addr);
>> +		writel(i, base_addr + stream->config->rsz.scale_lut);
>> +	}
>> +
>> +	set_scale(stream, in_y, in_c, out_y, out_c);
>> +
>> +	update_rsz_shadow(stream, async);
>> +}
>> +
>> +void disable_rsz(struct rkisp1_stream *stream, bool async)
>> +{
>> +	writel(0, stream->ispdev->base_addr + stream->config->rsz.ctrl);
>> +
>> +	if (!async)
>> +		update_rsz_shadow(stream, async);
>> +}
>> +
>> +void config_mi_ctrl(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +	u32 reg;
>> +
>> +	reg = readl(addr) & ~GENMASK(17, 16);
>> +	writel(reg | CIF_MI_CTRL_BURST_LEN_LUM_64, addr);
>> +	reg = readl(addr) & ~GENMASK(19, 18);
>> +	writel(reg | CIF_MI_CTRL_BURST_LEN_CHROM_64, addr);
>> +	reg = readl(addr);
>> +	writel(reg | CIF_MI_CTRL_INIT_BASE_EN, addr);
>> +	reg = readl(addr);
>> +	writel(reg | CIF_MI_CTRL_INIT_OFFSET_EN, addr);
>> +}
>> +
>> +bool mp_is_stream_stopped(void __iomem *base)
>> +{
>> +	int en;
>> +
>> +	en = CIF_MI_CTRL_SHD_MP_IN_ENABLED | CIF_MI_CTRL_SHD_RAW_OUT_ENABLED;
>> +	return !(readl(base + CIF_MI_CTRL_SHD) & en);
>> +}
>> +
>> +bool sp_is_stream_stopped(void __iomem *base)
>> +{
>> +	return !(readl(base + CIF_MI_CTRL_SHD) & CIF_MI_CTRL_SHD_SP_IN_ENABLED);
>> +}
>> diff --git a/drivers/media/platform/rockchip/isp1/regs.h b/drivers/media/platform/rockchip/isp1/regs.h
>> new file mode 100644
>> index 000000000000..df93336bf772
>> --- /dev/null
>> +++ b/drivers/media/platform/rockchip/isp1/regs.h
>> @@ -0,0 +1,1525 @@
>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>> +/*
>> + * Rockchip isp1 driver
>> + *
>> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
>> + */
>> +
>> +#ifndef _RKISP1_REGS_H
>> +#define _RKISP1_REGS_H
>> +#include "dev.h"
>> +
>> +/* ISP_CTRL */
>> +#define CIF_ISP_CTRL_ISP_ENABLE			BIT(0)
>> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT		(0 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_ITU656		(1 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_ITU601		(2 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601	(3 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_DATA_MODE		(4 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656	(5 << 1)
>> +#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656	(6 << 1)
>> +#define CIF_ISP_CTRL_ISP_INFORM_ENABLE		BIT(4)
>> +#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA		BIT(6)
>> +#define CIF_ISP_CTRL_ISP_AWB_ENA		BIT(7)
>> +#define CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT	BIT(8)
>> +#define CIF_ISP_CTRL_ISP_CFG_UPD		BIT(9)
>> +#define CIF_ISP_CTRL_ISP_GEN_CFG_UPD		BIT(10)
>> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA		BIT(11)
>> +#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA		BIT(12)
>> +#define CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA		BIT(13)
>> +#define CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA		BIT(14)
>> +
>> +/* ISP_ACQ_PROP */
>> +#define CIF_ISP_ACQ_PROP_POS_EDGE		BIT(0)
>> +#define CIF_ISP_ACQ_PROP_HSYNC_LOW		BIT(1)
>> +#define CIF_ISP_ACQ_PROP_VSYNC_LOW		BIT(2)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB		(0 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG		(1 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG		(2 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR		(3 << 3)
>> +#define CIF_ISP_ACQ_PROP_BAYER_PAT(pat)		((pat) << 3)
>> +#define CIF_ISP_ACQ_PROP_YCBYCR			(0 << 7)
>> +#define CIF_ISP_ACQ_PROP_YCRYCB			(1 << 7)
>> +#define CIF_ISP_ACQ_PROP_CBYCRY			(2 << 7)
>> +#define CIF_ISP_ACQ_PROP_CRYCBY			(3 << 7)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ALL		(0 << 9)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN		(1 << 9)
>> +#define CIF_ISP_ACQ_PROP_FIELD_SEL_ODD		(2 << 9)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_12B		(0 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO	(1 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB		(2 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO		(3 << 12)
>> +#define CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB		(4 << 12)
>> +
>> +/* VI_DPCL */
>> +#define CIF_VI_DPCL_DMA_JPEG			(0 << 0)
>> +#define CIF_VI_DPCL_MP_MUX_MRSZ_MI		(1 << 0)
>> +#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG		(2 << 0)
>> +#define CIF_VI_DPCL_CHAN_MODE_MP		(1 << 2)
>> +#define CIF_VI_DPCL_CHAN_MODE_SP		(2 << 2)
>> +#define CIF_VI_DPCL_CHAN_MODE_MPSP		(3 << 2)
>> +#define CIF_VI_DPCL_DMA_SW_SPMUX		(0 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_SI			(1 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_IE			(2 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_JPEG			(3 << 4)
>> +#define CIF_VI_DPCL_DMA_SW_ISP			(4 << 4)
>> +#define CIF_VI_DPCL_IF_SEL_PARALLEL		(0 << 8)
>> +#define CIF_VI_DPCL_IF_SEL_SMIA			(1 << 8)
>> +#define CIF_VI_DPCL_IF_SEL_MIPI			(2 << 8)
>> +#define CIF_VI_DPCL_DMA_IE_MUX_DMA		BIT(10)
>> +#define CIF_VI_DPCL_DMA_SP_MUX_DMA		BIT(11)
>> +
>> +/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */
>> +#define CIF_ISP_OFF				BIT(0)
>> +#define CIF_ISP_FRAME				BIT(1)
>> +#define CIF_ISP_DATA_LOSS			BIT(2)
>> +#define CIF_ISP_PIC_SIZE_ERROR			BIT(3)
>> +#define CIF_ISP_AWB_DONE			BIT(4)
>> +#define CIF_ISP_FRAME_IN			BIT(5)
>> +#define CIF_ISP_V_START				BIT(6)
>> +#define CIF_ISP_H_START				BIT(7)
>> +#define CIF_ISP_FLASH_ON			BIT(8)
>> +#define CIF_ISP_FLASH_OFF			BIT(9)
>> +#define CIF_ISP_SHUTTER_ON			BIT(10)
>> +#define CIF_ISP_SHUTTER_OFF			BIT(11)
>> +#define CIF_ISP_AFM_SUM_OF			BIT(12)
>> +#define CIF_ISP_AFM_LUM_OF			BIT(13)
>> +#define CIF_ISP_AFM_FIN				BIT(14)
>> +#define CIF_ISP_HIST_MEASURE_RDY		BIT(15)
>> +#define CIF_ISP_FLASH_CAP			BIT(17)
>> +#define CIF_ISP_EXP_END				BIT(18)
>> +#define CIF_ISP_VSM_END				BIT(19)
>> +
>> +/* ISP_ERR */
>> +#define CIF_ISP_ERR_INFORM_SIZE			BIT(0)
>> +#define CIF_ISP_ERR_IS_SIZE			BIT(1)
>> +#define CIF_ISP_ERR_OUTFORM_SIZE		BIT(2)
>> +
>> +/* MI_CTRL */
>> +#define CIF_MI_CTRL_MP_ENABLE			(1 << 0)
>> +#define CIF_MI_CTRL_SP_ENABLE			(2 << 0)
>> +#define CIF_MI_CTRL_JPEG_ENABLE			(4 << 0)
>> +#define CIF_MI_CTRL_RAW_ENABLE			(8 << 0)
>> +#define CIF_MI_CTRL_HFLIP			BIT(4)
>> +#define CIF_MI_CTRL_VFLIP			BIT(5)
>> +#define CIF_MI_CTRL_ROT				BIT(6)
>> +#define CIF_MI_BYTE_SWAP			BIT(7)
>> +#define CIF_MI_SP_Y_FULL_YUV2RGB		BIT(8)
>> +#define CIF_MI_SP_CBCR_FULL_YUV2RGB		BIT(9)
>> +#define CIF_MI_SP_422NONCOSITEED		BIT(10)
>> +#define CIF_MI_MP_PINGPONG_ENABEL		BIT(11)
>> +#define CIF_MI_SP_PINGPONG_ENABEL		BIT(12)
>> +#define CIF_MI_MP_AUTOUPDATE_ENABLE		BIT(13)
>> +#define CIF_MI_SP_AUTOUPDATE_ENABLE		BIT(14)
>> +#define CIF_MI_LAST_PIXEL_SIG_ENABLE		BIT(15)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_16		(0 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_32		(1 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_LUM_64		(2 << 16)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_16		(0 << 18)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_32		(1 << 18)
>> +#define CIF_MI_CTRL_BURST_LEN_CHROM_64		(2 << 18)
>> +#define CIF_MI_CTRL_INIT_BASE_EN		BIT(20)
>> +#define CIF_MI_CTRL_INIT_OFFSET_EN		BIT(21)
>> +#define MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8	(0 << 22)
>> +#define MI_CTRL_MP_WRITE_YUV_SPLA		(1 << 22)
>> +#define MI_CTRL_MP_WRITE_YUVINT			(2 << 22)
>> +#define MI_CTRL_MP_WRITE_RAW12			(2 << 22)
>> +#define MI_CTRL_SP_WRITE_PLA			(0 << 24)
>> +#define MI_CTRL_SP_WRITE_SPLA			(1 << 24)
>> +#define MI_CTRL_SP_WRITE_INT			(2 << 24)
>> +#define MI_CTRL_SP_INPUT_YUV400			(0 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV420			(1 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV422			(2 << 26)
>> +#define MI_CTRL_SP_INPUT_YUV444			(3 << 26)
>> +#define MI_CTRL_SP_OUTPUT_YUV400		(0 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV420		(1 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV422		(2 << 28)
>> +#define MI_CTRL_SP_OUTPUT_YUV444		(3 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB565		(4 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB666		(5 << 28)
>> +#define MI_CTRL_SP_OUTPUT_RGB888		(6 << 28)
>> +
>> +#define MI_CTRL_MP_FMT_MASK			GENMASK(23, 22)
>> +#define MI_CTRL_SP_FMT_MASK			GENMASK(30, 24)
>> +
>> +/* MI_INIT */
>> +#define CIF_MI_INIT_SKIP			BIT(2)
>> +#define CIF_MI_INIT_SOFT_UPD			BIT(4)
>> +
>> +/* MI_CTRL_SHD */
>> +#define CIF_MI_CTRL_SHD_MP_IN_ENABLED		BIT(0)
>> +#define CIF_MI_CTRL_SHD_SP_IN_ENABLED		BIT(1)
>> +#define CIF_MI_CTRL_SHD_JPEG_IN_ENABLED		BIT(2)
>> +#define CIF_MI_CTRL_SHD_RAW_IN_ENABLED		BIT(3)
>> +#define CIF_MI_CTRL_SHD_MP_OUT_ENABLED		BIT(16)
>> +#define CIF_MI_CTRL_SHD_SP_OUT_ENABLED		BIT(17)
>> +#define CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED	BIT(18)
>> +#define CIF_MI_CTRL_SHD_RAW_OUT_ENABLED		BIT(19)
>> +
>> +/* RSZ_CTRL */
>> +#define CIF_RSZ_CTRL_SCALE_HY_ENABLE		BIT(0)
>> +#define CIF_RSZ_CTRL_SCALE_HC_ENABLE		BIT(1)
>> +#define CIF_RSZ_CTRL_SCALE_VY_ENABLE		BIT(2)
>> +#define CIF_RSZ_CTRL_SCALE_VC_ENABLE		BIT(3)
>> +#define CIF_RSZ_CTRL_SCALE_HY_UP		BIT(4)
>> +#define CIF_RSZ_CTRL_SCALE_HC_UP		BIT(5)
>> +#define CIF_RSZ_CTRL_SCALE_VY_UP		BIT(6)
>> +#define CIF_RSZ_CTRL_SCALE_VC_UP		BIT(7)
>> +#define CIF_RSZ_CTRL_CFG_UPD			BIT(8)
>> +#define CIF_RSZ_CTRL_CFG_UPD_AUTO		BIT(9)
>> +#define CIF_RSZ_SCALER_FACTOR			BIT(16)
>> +
>> +/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
>> +#define CIF_MI_FRAME(stream)			BIT((stream)->id)
>> +#define CIF_MI_MBLK_LINE			BIT(2)
>> +#define CIF_MI_FILL_MP_Y			BIT(3)
>> +#define CIF_MI_WRAP_MP_Y			BIT(4)
>> +#define CIF_MI_WRAP_MP_CB			BIT(5)
>> +#define CIF_MI_WRAP_MP_CR			BIT(6)
>> +#define CIF_MI_WRAP_SP_Y			BIT(7)
>> +#define CIF_MI_WRAP_SP_CB			BIT(8)
>> +#define CIF_MI_WRAP_SP_CR			BIT(9)
>> +#define CIF_MI_DMA_READY			BIT(11)
>> +
>> +/* MI_STATUS */
>> +#define CIF_MI_STATUS_MP_Y_FIFO_FULL		BIT(0)
>> +#define CIF_MI_STATUS_SP_Y_FIFO_FULL		BIT(4)
>> +
>> +/* MI_DMA_CTRL */
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_16	(0 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_32	(1 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_64	(2 << 0)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16	(0 << 2)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32	(1 << 2)
>> +#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64	(2 << 2)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR		(0 << 4)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR	(1 << 4)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV400		(0 << 6)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV420		(1 << 6)
>> +#define CIF_MI_DMA_CTRL_READ_FMT_PACKED		(2 << 4)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV422		(2 << 6)
>> +#define CIF_MI_DMA_CTRL_FMT_YUV444		(3 << 6)
>> +#define CIF_MI_DMA_CTRL_BYTE_SWAP		BIT(8)
>> +#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA		BIT(9)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_NO		(0 << 12)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT		(1 << 12)
>> +#define CIF_MI_DMA_CTRL_RGB_BAYER_16BIT		(2 << 12)
>> +/* MI_DMA_START */
>> +#define CIF_MI_DMA_START_ENABLE			BIT(0)
>> +/* MI_XTD_FORMAT_CTRL  */
>> +#define CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP	BIT(0)
>> +#define CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP	BIT(1)
>> +#define CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP	BIT(2)
>> +
>> +/* CCL */
>> +#define CIF_CCL_CIF_CLK_DIS			BIT(2)
>> +/* ICCL */
>> +#define CIF_ICCL_ISP_CLK			BIT(0)
>> +#define CIF_ICCL_CP_CLK				BIT(1)
>> +#define CIF_ICCL_RES_2				BIT(2)
>> +#define CIF_ICCL_MRSZ_CLK			BIT(3)
>> +#define CIF_ICCL_SRSZ_CLK			BIT(4)
>> +#define CIF_ICCL_JPEG_CLK			BIT(5)
>> +#define CIF_ICCL_MI_CLK				BIT(6)
>> +#define CIF_ICCL_RES_7				BIT(7)
>> +#define CIF_ICCL_IE_CLK				BIT(8)
>> +#define CIF_ICCL_SIMP_CLK			BIT(9)
>> +#define CIF_ICCL_SMIA_CLK			BIT(10)
>> +#define CIF_ICCL_MIPI_CLK			BIT(11)
>> +#define CIF_ICCL_DCROP_CLK			BIT(12)
>> +/* IRCL */
>> +#define CIF_IRCL_ISP_SW_RST			BIT(0)
>> +#define CIF_IRCL_CP_SW_RST			BIT(1)
>> +#define CIF_IRCL_YCS_SW_RST			BIT(2)
>> +#define CIF_IRCL_MRSZ_SW_RST			BIT(3)
>> +#define CIF_IRCL_SRSZ_SW_RST			BIT(4)
>> +#define CIF_IRCL_JPEG_SW_RST			BIT(5)
>> +#define CIF_IRCL_MI_SW_RST			BIT(6)
>> +#define CIF_IRCL_CIF_SW_RST			BIT(7)
>> +#define CIF_IRCL_IE_SW_RST			BIT(8)
>> +#define CIF_IRCL_SI_SW_RST			BIT(9)
>> +#define CIF_IRCL_MIPI_SW_RST			BIT(11)
>> +
>> +/* C_PROC_CTR */
>> +#define CIF_C_PROC_CTR_ENABLE			BIT(0)
>> +#define CIF_C_PROC_YOUT_FULL			BIT(1)
>> +#define CIF_C_PROC_YIN_FULL			BIT(2)
>> +#define CIF_C_PROC_COUT_FULL			BIT(3)
>> +#define CIF_C_PROC_CTRL_RESERVED		0xFFFFFFFE
>> +#define CIF_C_PROC_CONTRAST_RESERVED		0xFFFFFF00
>> +#define CIF_C_PROC_BRIGHTNESS_RESERVED		0xFFFFFF00
>> +#define CIF_C_PROC_HUE_RESERVED			0xFFFFFF00
>> +#define CIF_C_PROC_SATURATION_RESERVED		0xFFFFFF00
>> +#define CIF_C_PROC_MACC_RESERVED		0xE000E000
>> +#define CIF_C_PROC_TONE_RESERVED		0xF000
>> +/* DUAL_CROP_CTRL */
>> +#define CIF_DUAL_CROP_MP_MODE_BYPASS		(0 << 0)
>> +#define CIF_DUAL_CROP_MP_MODE_YUV		(1 << 0)
>> +#define CIF_DUAL_CROP_MP_MODE_RAW		(2 << 0)
>> +#define CIF_DUAL_CROP_SP_MODE_BYPASS		(0 << 2)
>> +#define CIF_DUAL_CROP_SP_MODE_YUV		(1 << 2)
>> +#define CIF_DUAL_CROP_SP_MODE_RAW		(2 << 2)
>> +#define CIF_DUAL_CROP_CFG_UPD_PERMANENT		BIT(4)
>> +#define CIF_DUAL_CROP_CFG_UPD			BIT(5)
>> +#define CIF_DUAL_CROP_GEN_CFG_UPD		BIT(6)
>> +
>> +/* IMG_EFF_CTRL */
>> +#define CIF_IMG_EFF_CTRL_ENABLE			BIT(0)
>> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE	(0 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE		(1 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA		(2 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL		(3 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS		(4 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH		(5 << 1)
>> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN		(6 << 1)
>> +#define CIF_IMG_EFF_CTRL_CFG_UPD		BIT(4)
>> +#define CIF_IMG_EFF_CTRL_YCBCR_FULL		BIT(5)
>> +
>> +#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT	0
>> +#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT	1
>> +#define CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT	2
>> +#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT	3
>> +#define CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT	4
>> +#define CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT	5
>> +#define CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT	6
>> +#define CIF_IMG_EFF_CTRL_MODE_MASK		0xE
>> +
>> +/* IMG_EFF_COLOR_SEL */
>> +#define CIF_IMG_EFF_COLOR_RGB			0
>> +#define CIF_IMG_EFF_COLOR_B			(1 << 0)
>> +#define CIF_IMG_EFF_COLOR_G			(2 << 0)
>> +#define CIF_IMG_EFF_COLOR_GB			(3 << 0)
>> +#define CIF_IMG_EFF_COLOR_R			(4 << 0)
>> +#define CIF_IMG_EFF_COLOR_RB			(5 << 0)
>> +#define CIF_IMG_EFF_COLOR_RG			(6 << 0)
>> +#define CIF_IMG_EFF_COLOR_RGB2			(7 << 0)
>> +
>> +/* MIPI_CTRL */
>> +#define CIF_MIPI_CTRL_OUTPUT_ENA		BIT(0)
>> +#define CIF_MIPI_CTRL_SHUTDOWNLANES(a)		(((a) & 0xF) << 8)
>> +#define CIF_MIPI_CTRL_NUM_LANES(a)		(((a) & 0x3) << 12)
>> +#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP		BIT(16)
>> +#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP	BIT(17)
>> +#define CIF_MIPI_CTRL_CLOCKLANE_ENA		BIT(18)
>> +
>> +/* MIPI_DATA_SEL */
>> +#define CIF_MIPI_DATA_SEL_VC(a)			(((a) & 0x3) << 6)
>> +#define CIF_MIPI_DATA_SEL_DT(a)			(((a) & 0x3F) << 0)
>> +/* MIPI DATA_TYPE */
>> +#define CIF_CSI2_DT_YUV420_8b			0x18
>> +#define CIF_CSI2_DT_YUV420_10b			0x19
>> +#define CIF_CSI2_DT_YUV422_8b			0x1E
>> +#define CIF_CSI2_DT_YUV422_10b			0x1F
>> +#define CIF_CSI2_DT_RGB565			0x22
>> +#define CIF_CSI2_DT_RGB666			0x23
>> +#define CIF_CSI2_DT_RGB888			0x24
>> +#define CIF_CSI2_DT_RAW8			0x2A
>> +#define CIF_CSI2_DT_RAW10			0x2B
>> +#define CIF_CSI2_DT_RAW12			0x2C
>> +
>> +/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
>> +#define CIF_MIPI_SYNC_FIFO_OVFLW(a)		(((a) & 0xF) << 0)
>> +#define CIF_MIPI_ERR_SOT(a)			(((a) & 0xF) << 4)
>> +#define CIF_MIPI_ERR_SOT_SYNC(a)		(((a) & 0xF) << 8)
>> +#define CIF_MIPI_ERR_EOT_SYNC(a)		(((a) & 0xF) << 12)
>> +#define CIF_MIPI_ERR_CTRL(a)			(((a) & 0xF) << 16)
>> +#define CIF_MIPI_ERR_PROTOCOL			BIT(20)
>> +#define CIF_MIPI_ERR_ECC1			BIT(21)
>> +#define CIF_MIPI_ERR_ECC2			BIT(22)
>> +#define CIF_MIPI_ERR_CS				BIT(23)
>> +#define CIF_MIPI_FRAME_END			BIT(24)
>> +#define CIF_MIPI_ADD_DATA_OVFLW			BIT(25)
>> +#define CIF_MIPI_ADD_DATA_WATER_MARK		BIT(26)
>> +
>> +#define CIF_MIPI_ERR_CSI  (CIF_MIPI_ERR_PROTOCOL | \
>> +	CIF_MIPI_ERR_ECC1 | \
>> +	CIF_MIPI_ERR_ECC2 | \
>> +	CIF_MIPI_ERR_CS)
>> +
>> +#define CIF_MIPI_ERR_DPHY  (CIF_MIPI_ERR_SOT(3) | \
>> +	CIF_MIPI_ERR_SOT_SYNC(3) | \
>> +	CIF_MIPI_ERR_EOT_SYNC(3) | \
>> +	CIF_MIPI_ERR_CTRL(3))
>> +
>> +/* SUPER_IMPOSE */
>> +#define CIF_SUPER_IMP_CTRL_NORMAL_MODE		BIT(0)
>> +#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM		BIT(1)
>> +#define CIF_SUPER_IMP_CTRL_TRANSP_DIS		BIT(2)
>> +
>> +/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
>> +#define CIF_ISP_HIST_PROP_MODE_DIS		(0 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_RGB		(1 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_RED		(2 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_GREEN		(3 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_BLUE		(4 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_LUM		(5 << 0)
>> +#define CIF_ISP_HIST_PROP_MODE_MASK		0x7
>> +#define CIF_ISP_HIST_PREDIV_SET(x)		(((x) & 0x7F) << 3)
>> +#define CIF_ISP_HIST_WEIGHT_SET(v0, v1, v2, v3)	\
>> +				     (((v0) & 0x1F) | (((v1) & 0x1F) << 8)  |\
>> +				     (((v2) & 0x1F) << 16) | \
>> +				     (((v3) & 0x1F) << 24))
>> +
>> +#define CIF_ISP_HIST_WINDOW_OFFSET_RESERVED	0xFFFFF000
>> +#define CIF_ISP_HIST_WINDOW_SIZE_RESERVED	0xFFFFF800
>> +#define CIF_ISP_HIST_WEIGHT_RESERVED		0xE0E0E0E0
>> +#define CIF_ISP_MAX_HIST_PREDIVIDER		0x0000007F
>> +#define CIF_ISP_HIST_ROW_NUM			5
>> +#define CIF_ISP_HIST_COLUMN_NUM			5
>> +
>> +/* AUTO FOCUS MEASUREMENT:  ISP_AFM_CTRL */
>> +#define ISP_AFM_CTRL_ENABLE			BIT(0)
>> +
>> +/* SHUTTER CONTROL */
>> +#define CIF_ISP_SH_CTRL_SH_ENA			BIT(0)
>> +#define CIF_ISP_SH_CTRL_REP_EN			BIT(1)
>> +#define CIF_ISP_SH_CTRL_SRC_SH_TRIG		BIT(2)
>> +#define CIF_ISP_SH_CTRL_EDGE_POS		BIT(3)
>> +#define CIF_ISP_SH_CTRL_POL_LOW			BIT(4)
>> +
>> +/* FLASH MODULE */
>> +/* ISP_FLASH_CMD */
>> +#define CIF_FLASH_CMD_PRELIGHT_ON		BIT(0)
>> +#define CIF_FLASH_CMD_FLASH_ON			BIT(1)
>> +#define CIF_FLASH_CMD_PRE_FLASH_ON		BIT(2)
>> +/* ISP_FLASH_CONFIG */
>> +#define CIF_FLASH_CONFIG_PRELIGHT_END		BIT(0)
>> +#define CIF_FLASH_CONFIG_VSYNC_POS		BIT(1)
>> +#define CIF_FLASH_CONFIG_PRELIGHT_LOW		BIT(2)
>> +#define CIF_FLASH_CONFIG_SRC_FL_TRIG		BIT(3)
>> +#define CIF_FLASH_CONFIG_DELAY(a)		(((a) & 0xF) << 4)
>> +
>> +/* Demosaic:  ISP_DEMOSAIC */
>> +#define CIF_ISP_DEMOSAIC_BYPASS			BIT(10)
>> +#define CIF_ISP_DEMOSAIC_TH(x)			((x) & 0xFF)
>> +
>> +/* AWB */
>> +/* ISP_AWB_PROP */
>> +#define CIF_ISP_AWB_YMAX_CMP_EN			BIT(2)
>> +#define CIFISP_AWB_YMAX_READ(x)			(((x) >> 2) & 1)
>> +#define CIF_ISP_AWB_MODE_RGB_EN			((1 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_YCBCR_EN		((0 << 31) | (0x2 << 0))
>> +#define CIF_ISP_AWB_MODE_MASK_NONE		0xFFFFFFFC
>> +#define CIF_ISP_AWB_MODE_READ(x)		((x) & 3)
>> +/* ISP_AWB_GAIN_RB, ISP_AWB_GAIN_G  */
>> +#define CIF_ISP_AWB_GAIN_R_SET(x)		(((x) & 0x3FF) << 16)
>> +#define CIF_ISP_AWB_GAIN_R_READ(x)		(((x) >> 16) & 0x3FF)
>> +#define CIF_ISP_AWB_GAIN_B_SET(x)		((x) & 0x3FFF)
>> +#define CIF_ISP_AWB_GAIN_B_READ(x)		((x) & 0x3FFF)
>> +/* ISP_AWB_REF */
>> +#define CIF_ISP_AWB_REF_CR_SET(x)		(((x) & 0xFF) << 8)
>> +#define CIF_ISP_AWB_REF_CR_READ(x)		(((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_REF_CB_READ(x)		((x) & 0xFF)
>> +/* ISP_AWB_THRESH */
>> +#define CIF_ISP_AWB_MAX_CS_SET(x)		(((x) & 0xFF) << 8)
>> +#define CIF_ISP_AWB_MAX_CS_READ(x)		(((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_MIN_C_READ(x)		((x) & 0xFF)
>> +#define CIF_ISP_AWB_MIN_Y_SET(x)		(((x) & 0xFF) << 16)
>> +#define CIF_ISP_AWB_MIN_Y_READ(x)		(((x) >> 16) & 0xFF)
>> +#define CIF_ISP_AWB_MAX_Y_SET(x)		(((x) & 0xFF) << 24)
>> +#define CIF_ISP_AWB_MAX_Y_READ(x)		(((x) >> 24) & 0xFF)
>> +/* ISP_AWB_MEAN */
>> +#define CIF_ISP_AWB_GET_MEAN_CR_R(x)		((x) & 0xFF)
>> +#define CIF_ISP_AWB_GET_MEAN_CB_B(x)		(((x) >> 8) & 0xFF)
>> +#define CIF_ISP_AWB_GET_MEAN_Y_G(x)		(((x) >> 16) & 0xFF)
>> +/* ISP_AWB_WHITE_CNT */
>> +#define CIF_ISP_AWB_GET_PIXEL_CNT(x)		((x) & 0x3FFFFFF)
>> +
>> +#define CIF_ISP_AWB_GAINS_MAX_VAL		0x000003FF
>> +#define CIF_ISP_AWB_WINDOW_OFFSET_MAX		0x00000FFF
>> +#define CIF_ISP_AWB_WINDOW_MAX_SIZE		0x00001FFF
>> +#define CIF_ISP_AWB_CBCR_MAX_REF		0x000000FF
>> +#define CIF_ISP_AWB_THRES_MAX_YC		0x000000FF
>> +
>> +/* AE */
>> +/* ISP_EXP_CTRL */
>> +#define CIF_ISP_EXP_ENA				BIT(0)
>> +#define 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 CIF_ISP_EXP_CTRL_MEASMODE_1		BIT(31)
>> +
>> +/* ISP_EXP_H_SIZE */
>> +#define CIF_ISP_EXP_H_SIZE_SET(x)		((x) & 0x7FF)
>> +#define CIF_ISP_EXP_HEIGHT_MASK			0x000007FF
>> +/* ISP_EXP_V_SIZE : vertical size must be a multiple of 2). */
>> +#define CIF_ISP_EXP_V_SIZE_SET(x)		((x) & 0x7FE)
>> +
>> +/* ISP_EXP_H_OFFSET */
>> +#define CIF_ISP_EXP_H_OFFSET_SET(x)		((x) & 0x1FFF)
>> +#define CIF_ISP_EXP_MAX_HOFFS			2424
>> +/* ISP_EXP_V_OFFSET */
>> +#define CIF_ISP_EXP_V_OFFSET_SET(x)		((x) & 0x1FFF)
>> +#define CIF_ISP_EXP_MAX_VOFFS			1806
>> +
>> +#define CIF_ISP_EXP_ROW_NUM			5
>> +#define CIF_ISP_EXP_COLUMN_NUM			5
>> +#define CIF_ISP_EXP_NUM_LUMA_REGS \
>> +	(CIF_ISP_EXP_ROW_NUM * CIF_ISP_EXP_COLUMN_NUM)
>> +#define CIF_ISP_EXP_BLOCK_MAX_HSIZE		516
>> +#define CIF_ISP_EXP_BLOCK_MIN_HSIZE		35
>> +#define CIF_ISP_EXP_BLOCK_MAX_VSIZE		390
>> +#define CIF_ISP_EXP_BLOCK_MIN_VSIZE		28
>> +#define CIF_ISP_EXP_MAX_HSIZE	\
>> +	(CIF_ISP_EXP_BLOCK_MAX_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
>> +#define CIF_ISP_EXP_MIN_HSIZE	\
>> +	(CIF_ISP_EXP_BLOCK_MIN_HSIZE * CIF_ISP_EXP_COLUMN_NUM + 1)
>> +#define CIF_ISP_EXP_MAX_VSIZE	\
>> +	(CIF_ISP_EXP_BLOCK_MAX_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
>> +#define CIF_ISP_EXP_MIN_VSIZE	\
>> +	(CIF_ISP_EXP_BLOCK_MIN_VSIZE * CIF_ISP_EXP_ROW_NUM + 1)
>> +
>> +/* LSC: ISP_LSC_CTRL */
>> +#define CIF_ISP_LSC_CTRL_ENA			BIT(0)
>> +#define CIF_ISP_LSC_SECT_SIZE_RESERVED		0xFC00FC00
>> +#define CIF_ISP_LSC_GRAD_RESERVED		0xF000F000
>> +#define CIF_ISP_LSC_SAMPLE_RESERVED		0xF000F000
>> +#define CIF_ISP_LSC_SECTORS_MAX			17
>> +#define CIF_ISP_LSC_TABLE_DATA(v0, v1)     \
>> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 12))
>> +#define CIF_ISP_LSC_SECT_SIZE(v0, v1)      \
>> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
>> +#define CIF_ISP_LSC_GRAD_SIZE(v0, v1)      \
>> +	(((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
>> +
>> +/* LSC: ISP_LSC_TABLE_SEL */
>> +#define CIF_ISP_LSC_TABLE_0			0
>> +#define CIF_ISP_LSC_TABLE_1			1
>> +
>> +/* LSC: ISP_LSC_STATUS */
>> +#define CIF_ISP_LSC_ACTIVE_TABLE		BIT(1)
>> +#define CIF_ISP_LSC_TABLE_ADDRESS_0		0
>> +#define CIF_ISP_LSC_TABLE_ADDRESS_153		153
>> +
>> +/* FLT */
>> +/* ISP_FILT_MODE */
>> +#define CIF_ISP_FLT_ENA				BIT(0)
>> +
>> +/*
>> + * 0: green filter static mode (active filter factor = FILT_FAC_MID)
>> + * 1: dynamic noise reduction/sharpen Default
>> + */
>> +#define CIF_ISP_FLT_MODE_DNR			BIT(1)
>> +#define CIF_ISP_FLT_MODE_MAX			1
>> +#define CIF_ISP_FLT_CHROMA_V_MODE(x)		(((x) & 0x3) << 4)
>> +#define CIF_ISP_FLT_CHROMA_H_MODE(x)		(((x) & 0x3) << 6)
>> +#define CIF_ISP_FLT_CHROMA_MODE_MAX		3
>> +#define CIF_ISP_FLT_GREEN_STAGE1(x)		(((x) & 0xF) << 8)
>> +#define CIF_ISP_FLT_GREEN_STAGE1_MAX		8
>> +#define CIF_ISP_FLT_THREAD_RESERVED		0xFFFFFC00
>> +#define CIF_ISP_FLT_FAC_RESERVED		0xFFFFFFC0
>> +#define CIF_ISP_FLT_LUM_WEIGHT_RESERVED		0xFFF80000
>> +
>> +#define CIF_ISP_CTK_COEFF_RESERVED		0xFFFFF800
>> +#define CIF_ISP_XTALK_OFFSET_RESERVED		0xFFFFF000
>> +
>> +/* GOC */
>> +#define CIF_ISP_GAMMA_OUT_MODE_EQU		BIT(0)
>> +#define CIF_ISP_GOC_MODE_MAX			1
>> +#define CIF_ISP_GOC_RESERVED			0xFFFFF800
>> +/* ISP_CTRL BIT 11*/
>> +#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(x)	(((x) >> 11) & 1)
>> +
>> +/* DPCC */
>> +/* ISP_DPCC_MODE */
>> +#define CIF_ISP_DPCC_ENA			BIT(0)
>> +#define CIF_ISP_DPCC_MODE_MAX			0x07
>> +#define CIF_ISP_DPCC_OUTPUTMODE_MAX		0x0F
>> +#define CIF_ISP_DPCC_SETUSE_MAX			0x0F
>> +#define CIF_ISP_DPCC_METHODS_SET_RESERVED	0xFFFFE000
>> +#define CIF_ISP_DPCC_LINE_THRESH_RESERVED	0xFFFF0000
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_RESERVED	0xFFFFC0C0
>> +#define CIF_ISP_DPCC_PG_FAC_RESERVED		0xFFFFC0C0
>> +#define CIF_ISP_DPCC_RND_THRESH_RESERVED	0xFFFF0000
>> +#define CIF_ISP_DPCC_RG_FAC_RESERVED		0xFFFFC0C0
>> +#define CIF_ISP_DPCC_RO_LIMIT_RESERVED		0xFFFFF000
>> +#define CIF_ISP_DPCC_RND_OFFS_RESERVED		0xFFFFF000
>> +
>> +/* BLS */
>> +/* ISP_BLS_CTRL */
>> +#define CIF_ISP_BLS_ENA				BIT(0)
>> +#define CIF_ISP_BLS_MODE_MEASURED		BIT(1)
>> +#define CIF_ISP_BLS_MODE_FIXED			0
>> +#define CIF_ISP_BLS_WINDOW_1			(1 << 2)
>> +#define CIF_ISP_BLS_WINDOW_2			(2 << 2)
>> +
>> +/* GAMMA-IN */
>> +#define CIFISP_DEGAMMA_X_RESERVED	\
>> +	((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\
>> +	(1 << 15) | (1 << 11) | (1 << 7) | (1 << 3))
>> +#define CIFISP_DEGAMMA_Y_RESERVED               0xFFFFF000
>> +
>> +/* AFM */
>> +#define CIF_ISP_AFM_ENA				BIT(0)
>> +#define CIF_ISP_AFM_THRES_RESERVED		0xFFFF0000
>> +#define CIF_ISP_AFM_VAR_SHIFT_RESERVED		0xFFF8FFF8
>> +#define CIF_ISP_AFM_WINDOW_X_RESERVED		0xE000
>> +#define CIF_ISP_AFM_WINDOW_Y_RESERVED		0xF000
>> +#define CIF_ISP_AFM_WINDOW_X_MIN		0x5
>> +#define CIF_ISP_AFM_WINDOW_Y_MIN		0x2
>> +#define CIF_ISP_AFM_WINDOW_X(x)			(((x) & 0x1FFF) << 16)
>> +#define CIF_ISP_AFM_WINDOW_Y(x)			((x) & 0x1FFF)
>> +
>> +/* DPF */
>> +#define CIF_ISP_DPF_MODE_EN			BIT(0)
>> +#define CIF_ISP_DPF_MODE_B_FLT_DIS		BIT(1)
>> +#define CIF_ISP_DPF_MODE_GB_FLT_DIS		BIT(2)
>> +#define CIF_ISP_DPF_MODE_GR_FLT_DIS		BIT(3)
>> +#define CIF_ISP_DPF_MODE_R_FLT_DIS		BIT(4)
>> +#define CIF_ISP_DPF_MODE_RB_FLTSIZE_9x9		BIT(5)
>> +#define CIF_ISP_DPF_MODE_NLL_SEGMENTATION	BIT(6)
>> +#define CIF_ISP_DPF_MODE_AWB_GAIN_COMP		BIT(7)
>> +#define CIF_ISP_DPF_MODE_LSC_GAIN_COMP		BIT(8)
>> +#define CIF_ISP_DPF_MODE_USE_NF_GAIN		BIT(9)
>> +#define CIF_ISP_DPF_NF_GAIN_RESERVED		0xFFFFF000
>> +#define CIF_ISP_DPF_SPATIAL_COEFF_MAX		0x1F
>> +#define CIF_ISP_DPF_NLL_COEFF_N_MAX		0x3FF
>> +
>> +/* =================================================================== */
>> +/*                            CIF Registers                            */
>> +/* =================================================================== */
>> +#define CIF_CTRL_BASE			0x00000000
>> +#define CIF_CCL				(CIF_CTRL_BASE + 0x00000000)
>> +#define CIF_VI_ID			(CIF_CTRL_BASE + 0x00000008)
>> +#define CIF_ICCL			(CIF_CTRL_BASE + 0x00000010)
>> +#define CIF_IRCL			(CIF_CTRL_BASE + 0x00000014)
>> +#define CIF_VI_DPCL			(CIF_CTRL_BASE + 0x00000018)
>> +
>> +#define CIF_IMG_EFF_BASE		0x00000200
>> +#define CIF_IMG_EFF_CTRL		(CIF_IMG_EFF_BASE + 0x00000000)
>> +#define CIF_IMG_EFF_COLOR_SEL		(CIF_IMG_EFF_BASE + 0x00000004)
>> +#define CIF_IMG_EFF_MAT_1		(CIF_IMG_EFF_BASE + 0x00000008)
>> +#define CIF_IMG_EFF_MAT_2		(CIF_IMG_EFF_BASE + 0x0000000C)
>> +#define CIF_IMG_EFF_MAT_3		(CIF_IMG_EFF_BASE + 0x00000010)
>> +#define CIF_IMG_EFF_MAT_4		(CIF_IMG_EFF_BASE + 0x00000014)
>> +#define CIF_IMG_EFF_MAT_5		(CIF_IMG_EFF_BASE + 0x00000018)
>> +#define CIF_IMG_EFF_TINT		(CIF_IMG_EFF_BASE + 0x0000001C)
>> +#define CIF_IMG_EFF_CTRL_SHD		(CIF_IMG_EFF_BASE + 0x00000020)
>> +#define CIF_IMG_EFF_SHARPEN		(CIF_IMG_EFF_BASE + 0x00000024)
>> +
>> +#define CIF_SUPER_IMP_BASE		0x00000300
>> +#define CIF_SUPER_IMP_CTRL		(CIF_SUPER_IMP_BASE + 0x00000000)
>> +#define CIF_SUPER_IMP_OFFSET_X		(CIF_SUPER_IMP_BASE + 0x00000004)
>> +#define CIF_SUPER_IMP_OFFSET_Y		(CIF_SUPER_IMP_BASE + 0x00000008)
>> +#define CIF_SUPER_IMP_COLOR_Y		(CIF_SUPER_IMP_BASE + 0x0000000C)
>> +#define CIF_SUPER_IMP_COLOR_CB		(CIF_SUPER_IMP_BASE + 0x00000010)
>> +#define CIF_SUPER_IMP_COLOR_CR		(CIF_SUPER_IMP_BASE + 0x00000014)
>> +
>> +#define CIF_ISP_BASE			0x00000400
>> +#define CIF_ISP_CTRL			(CIF_ISP_BASE + 0x00000000)
>> +#define CIF_ISP_ACQ_PROP		(CIF_ISP_BASE + 0x00000004)
>> +#define CIF_ISP_ACQ_H_OFFS		(CIF_ISP_BASE + 0x00000008)
>> +#define CIF_ISP_ACQ_V_OFFS		(CIF_ISP_BASE + 0x0000000C)
>> +#define CIF_ISP_ACQ_H_SIZE		(CIF_ISP_BASE + 0x00000010)
>> +#define CIF_ISP_ACQ_V_SIZE		(CIF_ISP_BASE + 0x00000014)
>> +#define CIF_ISP_ACQ_NR_FRAMES		(CIF_ISP_BASE + 0x00000018)
>> +#define CIF_ISP_GAMMA_DX_LO		(CIF_ISP_BASE + 0x0000001C)
>> +#define CIF_ISP_GAMMA_DX_HI		(CIF_ISP_BASE + 0x00000020)
>> +#define CIF_ISP_GAMMA_R_Y0		(CIF_ISP_BASE + 0x00000024)
>> +#define CIF_ISP_GAMMA_R_Y1		(CIF_ISP_BASE + 0x00000028)
>> +#define CIF_ISP_GAMMA_R_Y2		(CIF_ISP_BASE + 0x0000002C)
>> +#define CIF_ISP_GAMMA_R_Y3		(CIF_ISP_BASE + 0x00000030)
>> +#define CIF_ISP_GAMMA_R_Y4		(CIF_ISP_BASE + 0x00000034)
>> +#define CIF_ISP_GAMMA_R_Y5		(CIF_ISP_BASE + 0x00000038)
>> +#define CIF_ISP_GAMMA_R_Y6		(CIF_ISP_BASE + 0x0000003C)
>> +#define CIF_ISP_GAMMA_R_Y7		(CIF_ISP_BASE + 0x00000040)
>> +#define CIF_ISP_GAMMA_R_Y8		(CIF_ISP_BASE + 0x00000044)
>> +#define CIF_ISP_GAMMA_R_Y9		(CIF_ISP_BASE + 0x00000048)
>> +#define CIF_ISP_GAMMA_R_Y10		(CIF_ISP_BASE + 0x0000004C)
>> +#define CIF_ISP_GAMMA_R_Y11		(CIF_ISP_BASE + 0x00000050)
>> +#define CIF_ISP_GAMMA_R_Y12		(CIF_ISP_BASE + 0x00000054)
>> +#define CIF_ISP_GAMMA_R_Y13		(CIF_ISP_BASE + 0x00000058)
>> +#define CIF_ISP_GAMMA_R_Y14		(CIF_ISP_BASE + 0x0000005C)
>> +#define CIF_ISP_GAMMA_R_Y15		(CIF_ISP_BASE + 0x00000060)
>> +#define CIF_ISP_GAMMA_R_Y16		(CIF_ISP_BASE + 0x00000064)
>> +#define CIF_ISP_GAMMA_G_Y0		(CIF_ISP_BASE + 0x00000068)
>> +#define CIF_ISP_GAMMA_G_Y1		(CIF_ISP_BASE + 0x0000006C)
>> +#define CIF_ISP_GAMMA_G_Y2		(CIF_ISP_BASE + 0x00000070)
>> +#define CIF_ISP_GAMMA_G_Y3		(CIF_ISP_BASE + 0x00000074)
>> +#define CIF_ISP_GAMMA_G_Y4		(CIF_ISP_BASE + 0x00000078)
>> +#define CIF_ISP_GAMMA_G_Y5		(CIF_ISP_BASE + 0x0000007C)
>> +#define CIF_ISP_GAMMA_G_Y6		(CIF_ISP_BASE + 0x00000080)
>> +#define CIF_ISP_GAMMA_G_Y7		(CIF_ISP_BASE + 0x00000084)
>> +#define CIF_ISP_GAMMA_G_Y8		(CIF_ISP_BASE + 0x00000088)
>> +#define CIF_ISP_GAMMA_G_Y9		(CIF_ISP_BASE + 0x0000008C)
>> +#define CIF_ISP_GAMMA_G_Y10		(CIF_ISP_BASE + 0x00000090)
>> +#define CIF_ISP_GAMMA_G_Y11		(CIF_ISP_BASE + 0x00000094)
>> +#define CIF_ISP_GAMMA_G_Y12		(CIF_ISP_BASE + 0x00000098)
>> +#define CIF_ISP_GAMMA_G_Y13		(CIF_ISP_BASE + 0x0000009C)
>> +#define CIF_ISP_GAMMA_G_Y14		(CIF_ISP_BASE + 0x000000A0)
>> +#define CIF_ISP_GAMMA_G_Y15		(CIF_ISP_BASE + 0x000000A4)
>> +#define CIF_ISP_GAMMA_G_Y16		(CIF_ISP_BASE + 0x000000A8)
>> +#define CIF_ISP_GAMMA_B_Y0		(CIF_ISP_BASE + 0x000000AC)
>> +#define CIF_ISP_GAMMA_B_Y1		(CIF_ISP_BASE + 0x000000B0)
>> +#define CIF_ISP_GAMMA_B_Y2		(CIF_ISP_BASE + 0x000000B4)
>> +#define CIF_ISP_GAMMA_B_Y3		(CIF_ISP_BASE + 0x000000B8)
>> +#define CIF_ISP_GAMMA_B_Y4		(CIF_ISP_BASE + 0x000000BC)
>> +#define CIF_ISP_GAMMA_B_Y5		(CIF_ISP_BASE + 0x000000C0)
>> +#define CIF_ISP_GAMMA_B_Y6		(CIF_ISP_BASE + 0x000000C4)
>> +#define CIF_ISP_GAMMA_B_Y7		(CIF_ISP_BASE + 0x000000C8)
>> +#define CIF_ISP_GAMMA_B_Y8		(CIF_ISP_BASE + 0x000000CC)
>> +#define CIF_ISP_GAMMA_B_Y9		(CIF_ISP_BASE + 0x000000D0)
>> +#define CIF_ISP_GAMMA_B_Y10		(CIF_ISP_BASE + 0x000000D4)
>> +#define CIF_ISP_GAMMA_B_Y11		(CIF_ISP_BASE + 0x000000D8)
>> +#define CIF_ISP_GAMMA_B_Y12		(CIF_ISP_BASE + 0x000000DC)
>> +#define CIF_ISP_GAMMA_B_Y13		(CIF_ISP_BASE + 0x000000E0)
>> +#define CIF_ISP_GAMMA_B_Y14		(CIF_ISP_BASE + 0x000000E4)
>> +#define CIF_ISP_GAMMA_B_Y15		(CIF_ISP_BASE + 0x000000E8)
>> +#define CIF_ISP_GAMMA_B_Y16		(CIF_ISP_BASE + 0x000000EC)
>> +#define CIF_ISP_AWB_PROP		(CIF_ISP_BASE + 0x00000110)
>> +#define CIF_ISP_AWB_WND_H_OFFS		(CIF_ISP_BASE + 0x00000114)
>> +#define CIF_ISP_AWB_WND_V_OFFS		(CIF_ISP_BASE + 0x00000118)
>> +#define CIF_ISP_AWB_WND_H_SIZE		(CIF_ISP_BASE + 0x0000011C)
>> +#define CIF_ISP_AWB_WND_V_SIZE		(CIF_ISP_BASE + 0x00000120)
>> +#define CIF_ISP_AWB_FRAMES		(CIF_ISP_BASE + 0x00000124)
>> +#define CIF_ISP_AWB_REF			(CIF_ISP_BASE + 0x00000128)
>> +#define CIF_ISP_AWB_THRESH		(CIF_ISP_BASE + 0x0000012C)
>> +#define CIF_ISP_AWB_GAIN_G		(CIF_ISP_BASE + 0x00000138)
>> +#define CIF_ISP_AWB_GAIN_RB		(CIF_ISP_BASE + 0x0000013C)
>> +#define CIF_ISP_AWB_WHITE_CNT		(CIF_ISP_BASE + 0x00000140)
>> +#define CIF_ISP_AWB_MEAN		(CIF_ISP_BASE + 0x00000144)
>> +#define CIF_ISP_CC_COEFF_0		(CIF_ISP_BASE + 0x00000170)
>> +#define CIF_ISP_CC_COEFF_1		(CIF_ISP_BASE + 0x00000174)
>> +#define CIF_ISP_CC_COEFF_2		(CIF_ISP_BASE + 0x00000178)
>> +#define CIF_ISP_CC_COEFF_3		(CIF_ISP_BASE + 0x0000017C)
>> +#define CIF_ISP_CC_COEFF_4		(CIF_ISP_BASE + 0x00000180)
>> +#define CIF_ISP_CC_COEFF_5		(CIF_ISP_BASE + 0x00000184)
>> +#define CIF_ISP_CC_COEFF_6		(CIF_ISP_BASE + 0x00000188)
>> +#define CIF_ISP_CC_COEFF_7		(CIF_ISP_BASE + 0x0000018C)
>> +#define CIF_ISP_CC_COEFF_8		(CIF_ISP_BASE + 0x00000190)
>> +#define CIF_ISP_OUT_H_OFFS		(CIF_ISP_BASE + 0x00000194)
>> +#define CIF_ISP_OUT_V_OFFS		(CIF_ISP_BASE + 0x00000198)
>> +#define CIF_ISP_OUT_H_SIZE		(CIF_ISP_BASE + 0x0000019C)
>> +#define CIF_ISP_OUT_V_SIZE		(CIF_ISP_BASE + 0x000001A0)
>> +#define CIF_ISP_DEMOSAIC		(CIF_ISP_BASE + 0x000001A4)
>> +#define CIF_ISP_FLAGS_SHD		(CIF_ISP_BASE + 0x000001A8)
>> +#define CIF_ISP_OUT_H_OFFS_SHD		(CIF_ISP_BASE + 0x000001AC)
>> +#define CIF_ISP_OUT_V_OFFS_SHD		(CIF_ISP_BASE + 0x000001B0)
>> +#define CIF_ISP_OUT_H_SIZE_SHD		(CIF_ISP_BASE + 0x000001B4)
>> +#define CIF_ISP_OUT_V_SIZE_SHD		(CIF_ISP_BASE + 0x000001B8)
>> +#define CIF_ISP_IMSC			(CIF_ISP_BASE + 0x000001BC)
>> +#define CIF_ISP_RIS			(CIF_ISP_BASE + 0x000001C0)
>> +#define CIF_ISP_MIS			(CIF_ISP_BASE + 0x000001C4)
>> +#define CIF_ISP_ICR			(CIF_ISP_BASE + 0x000001C8)
>> +#define CIF_ISP_ISR			(CIF_ISP_BASE + 0x000001CC)
>> +#define CIF_ISP_CT_COEFF_0		(CIF_ISP_BASE + 0x000001D0)
>> +#define CIF_ISP_CT_COEFF_1		(CIF_ISP_BASE + 0x000001D4)
>> +#define CIF_ISP_CT_COEFF_2		(CIF_ISP_BASE + 0x000001D8)
>> +#define CIF_ISP_CT_COEFF_3		(CIF_ISP_BASE + 0x000001DC)
>> +#define CIF_ISP_CT_COEFF_4		(CIF_ISP_BASE + 0x000001E0)
>> +#define CIF_ISP_CT_COEFF_5		(CIF_ISP_BASE + 0x000001E4)
>> +#define CIF_ISP_CT_COEFF_6		(CIF_ISP_BASE + 0x000001E8)
>> +#define CIF_ISP_CT_COEFF_7		(CIF_ISP_BASE + 0x000001EC)
>> +#define CIF_ISP_CT_COEFF_8		(CIF_ISP_BASE + 0x000001F0)
>> +#define CIF_ISP_GAMMA_OUT_MODE		(CIF_ISP_BASE + 0x000001F4)
>> +#define CIF_ISP_GAMMA_OUT_Y_0		(CIF_ISP_BASE + 0x000001F8)
>> +#define CIF_ISP_GAMMA_OUT_Y_1		(CIF_ISP_BASE + 0x000001FC)
>> +#define CIF_ISP_GAMMA_OUT_Y_2		(CIF_ISP_BASE + 0x00000200)
>> +#define CIF_ISP_GAMMA_OUT_Y_3		(CIF_ISP_BASE + 0x00000204)
>> +#define CIF_ISP_GAMMA_OUT_Y_4		(CIF_ISP_BASE + 0x00000208)
>> +#define CIF_ISP_GAMMA_OUT_Y_5		(CIF_ISP_BASE + 0x0000020C)
>> +#define CIF_ISP_GAMMA_OUT_Y_6		(CIF_ISP_BASE + 0x00000210)
>> +#define CIF_ISP_GAMMA_OUT_Y_7		(CIF_ISP_BASE + 0x00000214)
>> +#define CIF_ISP_GAMMA_OUT_Y_8		(CIF_ISP_BASE + 0x00000218)
>> +#define CIF_ISP_GAMMA_OUT_Y_9		(CIF_ISP_BASE + 0x0000021C)
>> +#define CIF_ISP_GAMMA_OUT_Y_10		(CIF_ISP_BASE + 0x00000220)
>> +#define CIF_ISP_GAMMA_OUT_Y_11		(CIF_ISP_BASE + 0x00000224)
>> +#define CIF_ISP_GAMMA_OUT_Y_12		(CIF_ISP_BASE + 0x00000228)
>> +#define CIF_ISP_GAMMA_OUT_Y_13		(CIF_ISP_BASE + 0x0000022C)
>> +#define CIF_ISP_GAMMA_OUT_Y_14		(CIF_ISP_BASE + 0x00000230)
>> +#define CIF_ISP_GAMMA_OUT_Y_15		(CIF_ISP_BASE + 0x00000234)
>> +#define CIF_ISP_GAMMA_OUT_Y_16		(CIF_ISP_BASE + 0x00000238)
>> +#define CIF_ISP_ERR			(CIF_ISP_BASE + 0x0000023C)
>> +#define CIF_ISP_ERR_CLR			(CIF_ISP_BASE + 0x00000240)
>> +#define CIF_ISP_FRAME_COUNT		(CIF_ISP_BASE + 0x00000244)
>> +#define CIF_ISP_CT_OFFSET_R		(CIF_ISP_BASE + 0x00000248)
>> +#define CIF_ISP_CT_OFFSET_G		(CIF_ISP_BASE + 0x0000024C)
>> +#define CIF_ISP_CT_OFFSET_B		(CIF_ISP_BASE + 0x00000250)
>> +
>> +#define CIF_ISP_FLASH_BASE		0x00000660
>> +#define CIF_ISP_FLASH_CMD		(CIF_ISP_FLASH_BASE + 0x00000000)
>> +#define CIF_ISP_FLASH_CONFIG		(CIF_ISP_FLASH_BASE + 0x00000004)
>> +#define CIF_ISP_FLASH_PREDIV		(CIF_ISP_FLASH_BASE + 0x00000008)
>> +#define CIF_ISP_FLASH_DELAY		(CIF_ISP_FLASH_BASE + 0x0000000C)
>> +#define CIF_ISP_FLASH_TIME		(CIF_ISP_FLASH_BASE + 0x00000010)
>> +#define CIF_ISP_FLASH_MAXP		(CIF_ISP_FLASH_BASE + 0x00000014)
>> +
>> +#define CIF_ISP_SH_BASE			0x00000680
>> +#define CIF_ISP_SH_CTRL			(CIF_ISP_SH_BASE + 0x00000000)
>> +#define CIF_ISP_SH_PREDIV		(CIF_ISP_SH_BASE + 0x00000004)
>> +#define CIF_ISP_SH_DELAY		(CIF_ISP_SH_BASE + 0x00000008)
>> +#define CIF_ISP_SH_TIME			(CIF_ISP_SH_BASE + 0x0000000C)
>> +
>> +#define CIF_C_PROC_BASE			0x00000800
>> +#define CIF_C_PROC_CTRL			(CIF_C_PROC_BASE + 0x00000000)
>> +#define CIF_C_PROC_CONTRAST		(CIF_C_PROC_BASE + 0x00000004)
>> +#define CIF_C_PROC_BRIGHTNESS		(CIF_C_PROC_BASE + 0x00000008)
>> +#define CIF_C_PROC_SATURATION		(CIF_C_PROC_BASE + 0x0000000C)
>> +#define CIF_C_PROC_HUE			(CIF_C_PROC_BASE + 0x00000010)
>> +
>> +#define CIF_DUAL_CROP_BASE		0x00000880
>> +#define CIF_DUAL_CROP_CTRL		(CIF_DUAL_CROP_BASE + 0x00000000)
>> +#define CIF_DUAL_CROP_M_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000004)
>> +#define CIF_DUAL_CROP_M_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000008)
>> +#define CIF_DUAL_CROP_M_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000000C)
>> +#define CIF_DUAL_CROP_M_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000010)
>> +#define CIF_DUAL_CROP_S_H_OFFS		(CIF_DUAL_CROP_BASE + 0x00000014)
>> +#define CIF_DUAL_CROP_S_V_OFFS		(CIF_DUAL_CROP_BASE + 0x00000018)
>> +#define CIF_DUAL_CROP_S_H_SIZE		(CIF_DUAL_CROP_BASE + 0x0000001C)
>> +#define CIF_DUAL_CROP_S_V_SIZE		(CIF_DUAL_CROP_BASE + 0x00000020)
>> +#define CIF_DUAL_CROP_M_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000024)
>> +#define CIF_DUAL_CROP_M_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000028)
>> +#define CIF_DUAL_CROP_M_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000002C)
>> +#define CIF_DUAL_CROP_M_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000030)
>> +#define CIF_DUAL_CROP_S_H_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000034)
>> +#define CIF_DUAL_CROP_S_V_OFFS_SHD	(CIF_DUAL_CROP_BASE + 0x00000038)
>> +#define CIF_DUAL_CROP_S_H_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x0000003C)
>> +#define CIF_DUAL_CROP_S_V_SIZE_SHD	(CIF_DUAL_CROP_BASE + 0x00000040)
>> +
>> +#define CIF_MRSZ_BASE			0x00000C00
>> +#define CIF_MRSZ_CTRL			(CIF_MRSZ_BASE + 0x00000000)
>> +#define CIF_MRSZ_SCALE_HY		(CIF_MRSZ_BASE + 0x00000004)
>> +#define CIF_MRSZ_SCALE_HCB		(CIF_MRSZ_BASE + 0x00000008)
>> +#define CIF_MRSZ_SCALE_HCR		(CIF_MRSZ_BASE + 0x0000000C)
>> +#define CIF_MRSZ_SCALE_VY		(CIF_MRSZ_BASE + 0x00000010)
>> +#define CIF_MRSZ_SCALE_VC		(CIF_MRSZ_BASE + 0x00000014)
>> +#define CIF_MRSZ_PHASE_HY		(CIF_MRSZ_BASE + 0x00000018)
>> +#define CIF_MRSZ_PHASE_HC		(CIF_MRSZ_BASE + 0x0000001C)
>> +#define CIF_MRSZ_PHASE_VY		(CIF_MRSZ_BASE + 0x00000020)
>> +#define CIF_MRSZ_PHASE_VC		(CIF_MRSZ_BASE + 0x00000024)
>> +#define CIF_MRSZ_SCALE_LUT_ADDR		(CIF_MRSZ_BASE + 0x00000028)
>> +#define CIF_MRSZ_SCALE_LUT		(CIF_MRSZ_BASE + 0x0000002C)
>> +#define CIF_MRSZ_CTRL_SHD		(CIF_MRSZ_BASE + 0x00000030)
>> +#define CIF_MRSZ_SCALE_HY_SHD		(CIF_MRSZ_BASE + 0x00000034)
>> +#define CIF_MRSZ_SCALE_HCB_SHD		(CIF_MRSZ_BASE + 0x00000038)
>> +#define CIF_MRSZ_SCALE_HCR_SHD		(CIF_MRSZ_BASE + 0x0000003C)
>> +#define CIF_MRSZ_SCALE_VY_SHD		(CIF_MRSZ_BASE + 0x00000040)
>> +#define CIF_MRSZ_SCALE_VC_SHD		(CIF_MRSZ_BASE + 0x00000044)
>> +#define CIF_MRSZ_PHASE_HY_SHD		(CIF_MRSZ_BASE + 0x00000048)
>> +#define CIF_MRSZ_PHASE_HC_SHD		(CIF_MRSZ_BASE + 0x0000004C)
>> +#define CIF_MRSZ_PHASE_VY_SHD		(CIF_MRSZ_BASE + 0x00000050)
>> +#define CIF_MRSZ_PHASE_VC_SHD		(CIF_MRSZ_BASE + 0x00000054)
>> +
>> +#define CIF_SRSZ_BASE			0x00001000
>> +#define CIF_SRSZ_CTRL			(CIF_SRSZ_BASE + 0x00000000)
>> +#define CIF_SRSZ_SCALE_HY		(CIF_SRSZ_BASE + 0x00000004)
>> +#define CIF_SRSZ_SCALE_HCB		(CIF_SRSZ_BASE + 0x00000008)
>> +#define CIF_SRSZ_SCALE_HCR		(CIF_SRSZ_BASE + 0x0000000C)
>> +#define CIF_SRSZ_SCALE_VY		(CIF_SRSZ_BASE + 0x00000010)
>> +#define CIF_SRSZ_SCALE_VC		(CIF_SRSZ_BASE + 0x00000014)
>> +#define CIF_SRSZ_PHASE_HY		(CIF_SRSZ_BASE + 0x00000018)
>> +#define CIF_SRSZ_PHASE_HC		(CIF_SRSZ_BASE + 0x0000001C)
>> +#define CIF_SRSZ_PHASE_VY		(CIF_SRSZ_BASE + 0x00000020)
>> +#define CIF_SRSZ_PHASE_VC		(CIF_SRSZ_BASE + 0x00000024)
>> +#define CIF_SRSZ_SCALE_LUT_ADDR		(CIF_SRSZ_BASE + 0x00000028)
>> +#define CIF_SRSZ_SCALE_LUT		(CIF_SRSZ_BASE + 0x0000002C)
>> +#define CIF_SRSZ_CTRL_SHD		(CIF_SRSZ_BASE + 0x00000030)
>> +#define CIF_SRSZ_SCALE_HY_SHD		(CIF_SRSZ_BASE + 0x00000034)
>> +#define CIF_SRSZ_SCALE_HCB_SHD		(CIF_SRSZ_BASE + 0x00000038)
>> +#define CIF_SRSZ_SCALE_HCR_SHD		(CIF_SRSZ_BASE + 0x0000003C)
>> +#define CIF_SRSZ_SCALE_VY_SHD		(CIF_SRSZ_BASE + 0x00000040)
>> +#define CIF_SRSZ_SCALE_VC_SHD		(CIF_SRSZ_BASE + 0x00000044)
>> +#define CIF_SRSZ_PHASE_HY_SHD		(CIF_SRSZ_BASE + 0x00000048)
>> +#define CIF_SRSZ_PHASE_HC_SHD		(CIF_SRSZ_BASE + 0x0000004C)
>> +#define CIF_SRSZ_PHASE_VY_SHD		(CIF_SRSZ_BASE + 0x00000050)
>> +#define CIF_SRSZ_PHASE_VC_SHD		(CIF_SRSZ_BASE + 0x00000054)
>> +
>> +#define CIF_MI_BASE			0x00001400
>> +#define CIF_MI_CTRL			(CIF_MI_BASE + 0x00000000)
>> +#define CIF_MI_INIT			(CIF_MI_BASE + 0x00000004)
>> +#define CIF_MI_MP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x00000008)
>> +#define CIF_MI_MP_Y_SIZE_INIT		(CIF_MI_BASE + 0x0000000C)
>> +#define CIF_MI_MP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000010)
>> +#define CIF_MI_MP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000014)
>> +#define CIF_MI_MP_Y_IRQ_OFFS_INIT	(CIF_MI_BASE + 0x00000018)
>> +#define CIF_MI_MP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x0000001C)
>> +#define CIF_MI_MP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000020)
>> +#define CIF_MI_MP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000024)
>> +#define CIF_MI_MP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x00000028)
>> +#define CIF_MI_MP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x0000002C)
>> +#define CIF_MI_MP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000030)
>> +#define CIF_MI_MP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000034)
>> +#define CIF_MI_MP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x00000038)
>> +#define CIF_MI_SP_Y_BASE_AD_INIT	(CIF_MI_BASE + 0x0000003C)
>> +#define CIF_MI_SP_Y_SIZE_INIT		(CIF_MI_BASE + 0x00000040)
>> +#define CIF_MI_SP_Y_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000044)
>> +#define CIF_MI_SP_Y_OFFS_CNT_START	(CIF_MI_BASE + 0x00000048)
>> +#define CIF_MI_SP_Y_LLENGTH		(CIF_MI_BASE + 0x0000004C)
>> +#define CIF_MI_SP_CB_BASE_AD_INIT	(CIF_MI_BASE + 0x00000050)
>> +#define CIF_MI_SP_CB_SIZE_INIT		(CIF_MI_BASE + 0x00000054)
>> +#define CIF_MI_SP_CB_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000058)
>> +#define CIF_MI_SP_CB_OFFS_CNT_START	(CIF_MI_BASE + 0x0000005C)
>> +#define CIF_MI_SP_CR_BASE_AD_INIT	(CIF_MI_BASE + 0x00000060)
>> +#define CIF_MI_SP_CR_SIZE_INIT		(CIF_MI_BASE + 0x00000064)
>> +#define CIF_MI_SP_CR_OFFS_CNT_INIT	(CIF_MI_BASE + 0x00000068)
>> +#define CIF_MI_SP_CR_OFFS_CNT_START	(CIF_MI_BASE + 0x0000006C)
>> +#define CIF_MI_BYTE_CNT			(CIF_MI_BASE + 0x00000070)
>> +#define CIF_MI_CTRL_SHD			(CIF_MI_BASE + 0x00000074)
>> +#define CIF_MI_MP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x00000078)
>> +#define CIF_MI_MP_Y_SIZE_SHD		(CIF_MI_BASE + 0x0000007C)
>> +#define CIF_MI_MP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000080)
>> +#define CIF_MI_MP_Y_IRQ_OFFS_SHD	(CIF_MI_BASE + 0x00000084)
>> +#define CIF_MI_MP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x00000088)
>> +#define CIF_MI_MP_CB_SIZE_SHD		(CIF_MI_BASE + 0x0000008C)
>> +#define CIF_MI_MP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x00000090)
>> +#define CIF_MI_MP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x00000094)
>> +#define CIF_MI_MP_CR_SIZE_SHD		(CIF_MI_BASE + 0x00000098)
>> +#define CIF_MI_MP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x0000009C)
>> +#define CIF_MI_SP_Y_BASE_AD_SHD		(CIF_MI_BASE + 0x000000A0)
>> +#define CIF_MI_SP_Y_SIZE_SHD		(CIF_MI_BASE + 0x000000A4)
>> +#define CIF_MI_SP_Y_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000A8)
>> +#define CIF_MI_SP_CB_BASE_AD_SHD	(CIF_MI_BASE + 0x000000B0)
>> +#define CIF_MI_SP_CB_SIZE_SHD		(CIF_MI_BASE + 0x000000B4)
>> +#define CIF_MI_SP_CB_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000B8)
>> +#define CIF_MI_SP_CR_BASE_AD_SHD	(CIF_MI_BASE + 0x000000BC)
>> +#define CIF_MI_SP_CR_SIZE_SHD		(CIF_MI_BASE + 0x000000C0)
>> +#define CIF_MI_SP_CR_OFFS_CNT_SHD	(CIF_MI_BASE + 0x000000C4)
>> +#define CIF_MI_DMA_Y_PIC_START_AD	(CIF_MI_BASE + 0x000000C8)
>> +#define CIF_MI_DMA_Y_PIC_WIDTH		(CIF_MI_BASE + 0x000000CC)
>> +#define CIF_MI_DMA_Y_LLENGTH		(CIF_MI_BASE + 0x000000D0)
>> +#define CIF_MI_DMA_Y_PIC_SIZE		(CIF_MI_BASE + 0x000000D4)
>> +#define CIF_MI_DMA_CB_PIC_START_AD	(CIF_MI_BASE + 0x000000D8)
>> +#define CIF_MI_DMA_CR_PIC_START_AD	(CIF_MI_BASE + 0x000000E8)
>> +#define CIF_MI_IMSC			(CIF_MI_BASE + 0x000000F8)
>> +#define CIF_MI_RIS			(CIF_MI_BASE + 0x000000FC)
>> +#define CIF_MI_MIS			(CIF_MI_BASE + 0x00000100)
>> +#define CIF_MI_ICR			(CIF_MI_BASE + 0x00000104)
>> +#define CIF_MI_ISR			(CIF_MI_BASE + 0x00000108)
>> +#define CIF_MI_STATUS			(CIF_MI_BASE + 0x0000010C)
>> +#define CIF_MI_STATUS_CLR		(CIF_MI_BASE + 0x00000110)
>> +#define CIF_MI_SP_Y_PIC_WIDTH		(CIF_MI_BASE + 0x00000114)
>> +#define CIF_MI_SP_Y_PIC_HEIGHT		(CIF_MI_BASE + 0x00000118)
>> +#define CIF_MI_SP_Y_PIC_SIZE		(CIF_MI_BASE + 0x0000011C)
>> +#define CIF_MI_DMA_CTRL			(CIF_MI_BASE + 0x00000120)
>> +#define CIF_MI_DMA_START		(CIF_MI_BASE + 0x00000124)
>> +#define CIF_MI_DMA_STATUS		(CIF_MI_BASE + 0x00000128)
>> +#define CIF_MI_PIXEL_COUNT		(CIF_MI_BASE + 0x0000012C)
>> +#define CIF_MI_MP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000130)
>> +#define CIF_MI_MP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000134)
>> +#define CIF_MI_MP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000138)
>> +#define CIF_MI_SP_Y_BASE_AD_INIT2	(CIF_MI_BASE + 0x0000013C)
>> +#define CIF_MI_SP_CB_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000140)
>> +#define CIF_MI_SP_CR_BASE_AD_INIT2	(CIF_MI_BASE + 0x00000144)
>> +#define CIF_MI_XTD_FORMAT_CTRL		(CIF_MI_BASE + 0x00000148)
>> +
>> +#define CIF_SMIA_BASE			0x00001A00
>> +#define CIF_SMIA_CTRL			(CIF_SMIA_BASE + 0x00000000)
>> +#define CIF_SMIA_STATUS			(CIF_SMIA_BASE + 0x00000004)
>> +#define CIF_SMIA_IMSC			(CIF_SMIA_BASE + 0x00000008)
>> +#define CIF_SMIA_RIS			(CIF_SMIA_BASE + 0x0000000C)
>> +#define CIF_SMIA_MIS			(CIF_SMIA_BASE + 0x00000010)
>> +#define CIF_SMIA_ICR			(CIF_SMIA_BASE + 0x00000014)
>> +#define CIF_SMIA_ISR			(CIF_SMIA_BASE + 0x00000018)
>> +#define CIF_SMIA_DATA_FORMAT_SEL	(CIF_SMIA_BASE + 0x0000001C)
>> +#define CIF_SMIA_SOF_EMB_DATA_LINES	(CIF_SMIA_BASE + 0x00000020)
>> +#define CIF_SMIA_EMB_HSTART		(CIF_SMIA_BASE + 0x00000024)
>> +#define CIF_SMIA_EMB_HSIZE		(CIF_SMIA_BASE + 0x00000028)
>> +#define CIF_SMIA_EMB_VSTART		(CIF_SMIA_BASE + 0x0000002c)
>> +#define CIF_SMIA_NUM_LINES		(CIF_SMIA_BASE + 0x00000030)
>> +#define CIF_SMIA_EMB_DATA_FIFO		(CIF_SMIA_BASE + 0x00000034)
>> +#define CIF_SMIA_EMB_DATA_WATERMARK	(CIF_SMIA_BASE + 0x00000038)
>> +
>> +#define CIF_MIPI_BASE			0x00001C00
>> +#define CIF_MIPI_CTRL			(CIF_MIPI_BASE + 0x00000000)
>> +#define CIF_MIPI_STATUS			(CIF_MIPI_BASE + 0x00000004)
>> +#define CIF_MIPI_IMSC			(CIF_MIPI_BASE + 0x00000008)
>> +#define CIF_MIPI_RIS			(CIF_MIPI_BASE + 0x0000000C)
>> +#define CIF_MIPI_MIS			(CIF_MIPI_BASE + 0x00000010)
>> +#define CIF_MIPI_ICR			(CIF_MIPI_BASE + 0x00000014)
>> +#define CIF_MIPI_ISR			(CIF_MIPI_BASE + 0x00000018)
>> +#define CIF_MIPI_CUR_DATA_ID		(CIF_MIPI_BASE + 0x0000001C)
>> +#define CIF_MIPI_IMG_DATA_SEL		(CIF_MIPI_BASE + 0x00000020)
>> +#define CIF_MIPI_ADD_DATA_SEL_1		(CIF_MIPI_BASE + 0x00000024)
>> +#define CIF_MIPI_ADD_DATA_SEL_2		(CIF_MIPI_BASE + 0x00000028)
>> +#define CIF_MIPI_ADD_DATA_SEL_3		(CIF_MIPI_BASE + 0x0000002C)
>> +#define CIF_MIPI_ADD_DATA_SEL_4		(CIF_MIPI_BASE + 0x00000030)
>> +#define CIF_MIPI_ADD_DATA_FIFO		(CIF_MIPI_BASE + 0x00000034)
>> +#define CIF_MIPI_FIFO_FILL_LEVEL	(CIF_MIPI_BASE + 0x00000038)
>> +#define CIF_MIPI_COMPRESSED_MODE	(CIF_MIPI_BASE + 0x0000003C)
>> +#define CIF_MIPI_FRAME			(CIF_MIPI_BASE + 0x00000040)
>> +#define CIF_MIPI_GEN_SHORT_DT		(CIF_MIPI_BASE + 0x00000044)
>> +#define CIF_MIPI_GEN_SHORT_8_9		(CIF_MIPI_BASE + 0x00000048)
>> +#define CIF_MIPI_GEN_SHORT_A_B		(CIF_MIPI_BASE + 0x0000004C)
>> +#define CIF_MIPI_GEN_SHORT_C_D		(CIF_MIPI_BASE + 0x00000050)
>> +#define CIF_MIPI_GEN_SHORT_E_F		(CIF_MIPI_BASE + 0x00000054)
>> +
>> +#define CIF_ISP_AFM_BASE		0x00002000
>> +#define CIF_ISP_AFM_CTRL		(CIF_ISP_AFM_BASE + 0x00000000)
>> +#define CIF_ISP_AFM_LT_A		(CIF_ISP_AFM_BASE + 0x00000004)
>> +#define CIF_ISP_AFM_RB_A		(CIF_ISP_AFM_BASE + 0x00000008)
>> +#define CIF_ISP_AFM_LT_B		(CIF_ISP_AFM_BASE + 0x0000000C)
>> +#define CIF_ISP_AFM_RB_B		(CIF_ISP_AFM_BASE + 0x00000010)
>> +#define CIF_ISP_AFM_LT_C		(CIF_ISP_AFM_BASE + 0x00000014)
>> +#define CIF_ISP_AFM_RB_C		(CIF_ISP_AFM_BASE + 0x00000018)
>> +#define CIF_ISP_AFM_THRES		(CIF_ISP_AFM_BASE + 0x0000001C)
>> +#define CIF_ISP_AFM_VAR_SHIFT		(CIF_ISP_AFM_BASE + 0x00000020)
>> +#define CIF_ISP_AFM_SUM_A		(CIF_ISP_AFM_BASE + 0x00000024)
>> +#define CIF_ISP_AFM_SUM_B		(CIF_ISP_AFM_BASE + 0x00000028)
>> +#define CIF_ISP_AFM_SUM_C		(CIF_ISP_AFM_BASE + 0x0000002C)
>> +#define CIF_ISP_AFM_LUM_A		(CIF_ISP_AFM_BASE + 0x00000030)
>> +#define CIF_ISP_AFM_LUM_B		(CIF_ISP_AFM_BASE + 0x00000034)
>> +#define CIF_ISP_AFM_LUM_C		(CIF_ISP_AFM_BASE + 0x00000038)
>> +
>> +#define CIF_ISP_LSC_BASE		0x00002200
>> +#define CIF_ISP_LSC_CTRL		(CIF_ISP_LSC_BASE + 0x00000000)
>> +#define CIF_ISP_LSC_R_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000004)
>> +#define CIF_ISP_LSC_GR_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000008)
>> +#define CIF_ISP_LSC_B_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x0000000C)
>> +#define CIF_ISP_LSC_GB_TABLE_ADDR	(CIF_ISP_LSC_BASE + 0x00000010)
>> +#define CIF_ISP_LSC_R_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000014)
>> +#define CIF_ISP_LSC_GR_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000018)
>> +#define CIF_ISP_LSC_B_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x0000001C)
>> +#define CIF_ISP_LSC_GB_TABLE_DATA	(CIF_ISP_LSC_BASE + 0x00000020)
>> +#define CIF_ISP_LSC_XGRAD_01		(CIF_ISP_LSC_BASE + 0x00000024)
>> +#define CIF_ISP_LSC_XGRAD_23		(CIF_ISP_LSC_BASE + 0x00000028)
>> +#define CIF_ISP_LSC_XGRAD_45		(CIF_ISP_LSC_BASE + 0x0000002C)
>> +#define CIF_ISP_LSC_XGRAD_67		(CIF_ISP_LSC_BASE + 0x00000030)
>> +#define CIF_ISP_LSC_YGRAD_01		(CIF_ISP_LSC_BASE + 0x00000034)
>> +#define CIF_ISP_LSC_YGRAD_23		(CIF_ISP_LSC_BASE + 0x00000038)
>> +#define CIF_ISP_LSC_YGRAD_45		(CIF_ISP_LSC_BASE + 0x0000003C)
>> +#define CIF_ISP_LSC_YGRAD_67		(CIF_ISP_LSC_BASE + 0x00000040)
>> +#define CIF_ISP_LSC_XSIZE_01		(CIF_ISP_LSC_BASE + 0x00000044)
>> +#define CIF_ISP_LSC_XSIZE_23		(CIF_ISP_LSC_BASE + 0x00000048)
>> +#define CIF_ISP_LSC_XSIZE_45		(CIF_ISP_LSC_BASE + 0x0000004C)
>> +#define CIF_ISP_LSC_XSIZE_67		(CIF_ISP_LSC_BASE + 0x00000050)
>> +#define CIF_ISP_LSC_YSIZE_01		(CIF_ISP_LSC_BASE + 0x00000054)
>> +#define CIF_ISP_LSC_YSIZE_23		(CIF_ISP_LSC_BASE + 0x00000058)
>> +#define CIF_ISP_LSC_YSIZE_45		(CIF_ISP_LSC_BASE + 0x0000005C)
>> +#define CIF_ISP_LSC_YSIZE_67		(CIF_ISP_LSC_BASE + 0x00000060)
>> +#define CIF_ISP_LSC_TABLE_SEL		(CIF_ISP_LSC_BASE + 0x00000064)
>> +#define CIF_ISP_LSC_STATUS		(CIF_ISP_LSC_BASE + 0x00000068)
>> +
>> +#define CIF_ISP_IS_BASE			0x00002300
>> +#define CIF_ISP_IS_CTRL			(CIF_ISP_IS_BASE + 0x00000000)
>> +#define CIF_ISP_IS_RECENTER		(CIF_ISP_IS_BASE + 0x00000004)
>> +#define CIF_ISP_IS_H_OFFS		(CIF_ISP_IS_BASE + 0x00000008)
>> +#define CIF_ISP_IS_V_OFFS		(CIF_ISP_IS_BASE + 0x0000000C)
>> +#define CIF_ISP_IS_H_SIZE		(CIF_ISP_IS_BASE + 0x00000010)
>> +#define CIF_ISP_IS_V_SIZE		(CIF_ISP_IS_BASE + 0x00000014)
>> +#define CIF_ISP_IS_MAX_DX		(CIF_ISP_IS_BASE + 0x00000018)
>> +#define CIF_ISP_IS_MAX_DY		(CIF_ISP_IS_BASE + 0x0000001C)
>> +#define CIF_ISP_IS_DISPLACE		(CIF_ISP_IS_BASE + 0x00000020)
>> +#define CIF_ISP_IS_H_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000024)
>> +#define CIF_ISP_IS_V_OFFS_SHD		(CIF_ISP_IS_BASE + 0x00000028)
>> +#define CIF_ISP_IS_H_SIZE_SHD		(CIF_ISP_IS_BASE + 0x0000002C)
>> +#define CIF_ISP_IS_V_SIZE_SHD		(CIF_ISP_IS_BASE + 0x00000030)
>> +
>> +#define CIF_ISP_HIST_BASE		0x00002400
>> +
>> +#define CIF_ISP_HIST_PROP		(CIF_ISP_HIST_BASE + 0x00000000)
>> +#define CIF_ISP_HIST_H_OFFS		(CIF_ISP_HIST_BASE + 0x00000004)
>> +#define CIF_ISP_HIST_V_OFFS		(CIF_ISP_HIST_BASE + 0x00000008)
>> +#define CIF_ISP_HIST_H_SIZE		(CIF_ISP_HIST_BASE + 0x0000000C)
>> +#define CIF_ISP_HIST_V_SIZE		(CIF_ISP_HIST_BASE + 0x00000010)
>> +#define CIF_ISP_HIST_BIN_0		(CIF_ISP_HIST_BASE + 0x00000014)
>> +#define CIF_ISP_HIST_BIN_1		(CIF_ISP_HIST_BASE + 0x00000018)
>> +#define CIF_ISP_HIST_BIN_2		(CIF_ISP_HIST_BASE + 0x0000001C)
>> +#define CIF_ISP_HIST_BIN_3		(CIF_ISP_HIST_BASE + 0x00000020)
>> +#define CIF_ISP_HIST_BIN_4		(CIF_ISP_HIST_BASE + 0x00000024)
>> +#define CIF_ISP_HIST_BIN_5		(CIF_ISP_HIST_BASE + 0x00000028)
>> +#define CIF_ISP_HIST_BIN_6		(CIF_ISP_HIST_BASE + 0x0000002C)
>> +#define CIF_ISP_HIST_BIN_7		(CIF_ISP_HIST_BASE + 0x00000030)
>> +#define CIF_ISP_HIST_BIN_8		(CIF_ISP_HIST_BASE + 0x00000034)
>> +#define CIF_ISP_HIST_BIN_9		(CIF_ISP_HIST_BASE + 0x00000038)
>> +#define CIF_ISP_HIST_BIN_10		(CIF_ISP_HIST_BASE + 0x0000003C)
>> +#define CIF_ISP_HIST_BIN_11		(CIF_ISP_HIST_BASE + 0x00000040)
>> +#define CIF_ISP_HIST_BIN_12		(CIF_ISP_HIST_BASE + 0x00000044)
>> +#define CIF_ISP_HIST_BIN_13		(CIF_ISP_HIST_BASE + 0x00000048)
>> +#define CIF_ISP_HIST_BIN_14		(CIF_ISP_HIST_BASE + 0x0000004C)
>> +#define CIF_ISP_HIST_BIN_15		(CIF_ISP_HIST_BASE + 0x00000050)
>> +#define CIF_ISP_HIST_WEIGHT_00TO30	(CIF_ISP_HIST_BASE + 0x00000054)
>> +#define CIF_ISP_HIST_WEIGHT_40TO21	(CIF_ISP_HIST_BASE + 0x00000058)
>> +#define CIF_ISP_HIST_WEIGHT_31TO12	(CIF_ISP_HIST_BASE + 0x0000005C)
>> +#define CIF_ISP_HIST_WEIGHT_22TO03	(CIF_ISP_HIST_BASE + 0x00000060)
>> +#define CIF_ISP_HIST_WEIGHT_13TO43	(CIF_ISP_HIST_BASE + 0x00000064)
>> +#define CIF_ISP_HIST_WEIGHT_04TO34	(CIF_ISP_HIST_BASE + 0x00000068)
>> +#define CIF_ISP_HIST_WEIGHT_44		(CIF_ISP_HIST_BASE + 0x0000006C)
>> +
>> +#define CIF_ISP_FILT_BASE		0x00002500
>> +#define CIF_ISP_FILT_MODE		(CIF_ISP_FILT_BASE + 0x00000000)
>> +#define CIF_ISP_FILT_THRESH_BL0		(CIF_ISP_FILT_BASE + 0x00000028)
>> +#define CIF_ISP_FILT_THRESH_BL1		(CIF_ISP_FILT_BASE + 0x0000002c)
>> +#define CIF_ISP_FILT_THRESH_SH0		(CIF_ISP_FILT_BASE + 0x00000030)
>> +#define CIF_ISP_FILT_THRESH_SH1		(CIF_ISP_FILT_BASE + 0x00000034)
>> +#define CIF_ISP_FILT_LUM_WEIGHT		(CIF_ISP_FILT_BASE + 0x00000038)
>> +#define CIF_ISP_FILT_FAC_SH1		(CIF_ISP_FILT_BASE + 0x0000003c)
>> +#define CIF_ISP_FILT_FAC_SH0		(CIF_ISP_FILT_BASE + 0x00000040)
>> +#define CIF_ISP_FILT_FAC_MID		(CIF_ISP_FILT_BASE + 0x00000044)
>> +#define CIF_ISP_FILT_FAC_BL0		(CIF_ISP_FILT_BASE + 0x00000048)
>> +#define CIF_ISP_FILT_FAC_BL1		(CIF_ISP_FILT_BASE + 0x0000004C)
>> +
>> +#define CIF_ISP_CAC_BASE		0x00002580
>> +#define CIF_ISP_CAC_CTRL		(CIF_ISP_CAC_BASE + 0x00000000)
>> +#define CIF_ISP_CAC_COUNT_START		(CIF_ISP_CAC_BASE + 0x00000004)
>> +#define CIF_ISP_CAC_A			(CIF_ISP_CAC_BASE + 0x00000008)
>> +#define CIF_ISP_CAC_B			(CIF_ISP_CAC_BASE + 0x0000000C)
>> +#define CIF_ISP_CAC_C			(CIF_ISP_CAC_BASE + 0x00000010)
>> +#define CIF_ISP_X_NORM			(CIF_ISP_CAC_BASE + 0x00000014)
>> +#define CIF_ISP_Y_NORM			(CIF_ISP_CAC_BASE + 0x00000018)
>> +
>> +#define CIF_ISP_EXP_BASE		0x00002600
>> +#define CIF_ISP_EXP_CTRL		(CIF_ISP_EXP_BASE + 0x00000000)
>> +#define CIF_ISP_EXP_H_OFFSET		(CIF_ISP_EXP_BASE + 0x00000004)
>> +#define CIF_ISP_EXP_V_OFFSET		(CIF_ISP_EXP_BASE + 0x00000008)
>> +#define CIF_ISP_EXP_H_SIZE		(CIF_ISP_EXP_BASE + 0x0000000C)
>> +#define CIF_ISP_EXP_V_SIZE		(CIF_ISP_EXP_BASE + 0x00000010)
>> +#define CIF_ISP_EXP_MEAN_00		(CIF_ISP_EXP_BASE + 0x00000014)
>> +#define CIF_ISP_EXP_MEAN_10		(CIF_ISP_EXP_BASE + 0x00000018)
>> +#define CIF_ISP_EXP_MEAN_20		(CIF_ISP_EXP_BASE + 0x0000001c)
>> +#define CIF_ISP_EXP_MEAN_30		(CIF_ISP_EXP_BASE + 0x00000020)
>> +#define CIF_ISP_EXP_MEAN_40		(CIF_ISP_EXP_BASE + 0x00000024)
>> +#define CIF_ISP_EXP_MEAN_01		(CIF_ISP_EXP_BASE + 0x00000028)
>> +#define CIF_ISP_EXP_MEAN_11		(CIF_ISP_EXP_BASE + 0x0000002c)
>> +#define CIF_ISP_EXP_MEAN_21		(CIF_ISP_EXP_BASE + 0x00000030)
>> +#define CIF_ISP_EXP_MEAN_31		(CIF_ISP_EXP_BASE + 0x00000034)
>> +#define CIF_ISP_EXP_MEAN_41		(CIF_ISP_EXP_BASE + 0x00000038)
>> +#define CIF_ISP_EXP_MEAN_02		(CIF_ISP_EXP_BASE + 0x0000003c)
>> +#define CIF_ISP_EXP_MEAN_12		(CIF_ISP_EXP_BASE + 0x00000040)
>> +#define CIF_ISP_EXP_MEAN_22		(CIF_ISP_EXP_BASE + 0x00000044)
>> +#define CIF_ISP_EXP_MEAN_32		(CIF_ISP_EXP_BASE + 0x00000048)
>> +#define CIF_ISP_EXP_MEAN_42		(CIF_ISP_EXP_BASE + 0x0000004c)
>> +#define CIF_ISP_EXP_MEAN_03		(CIF_ISP_EXP_BASE + 0x00000050)
>> +#define CIF_ISP_EXP_MEAN_13		(CIF_ISP_EXP_BASE + 0x00000054)
>> +#define CIF_ISP_EXP_MEAN_23		(CIF_ISP_EXP_BASE + 0x00000058)
>> +#define CIF_ISP_EXP_MEAN_33		(CIF_ISP_EXP_BASE + 0x0000005c)
>> +#define CIF_ISP_EXP_MEAN_43		(CIF_ISP_EXP_BASE + 0x00000060)
>> +#define CIF_ISP_EXP_MEAN_04		(CIF_ISP_EXP_BASE + 0x00000064)
>> +#define CIF_ISP_EXP_MEAN_14		(CIF_ISP_EXP_BASE + 0x00000068)
>> +#define CIF_ISP_EXP_MEAN_24		(CIF_ISP_EXP_BASE + 0x0000006c)
>> +#define CIF_ISP_EXP_MEAN_34		(CIF_ISP_EXP_BASE + 0x00000070)
>> +#define CIF_ISP_EXP_MEAN_44		(CIF_ISP_EXP_BASE + 0x00000074)
>> +
>> +#define CIF_ISP_BLS_BASE		0x00002700
>> +#define CIF_ISP_BLS_CTRL		(CIF_ISP_BLS_BASE + 0x00000000)
>> +#define CIF_ISP_BLS_SAMPLES		(CIF_ISP_BLS_BASE + 0x00000004)
>> +#define CIF_ISP_BLS_H1_START		(CIF_ISP_BLS_BASE + 0x00000008)
>> +#define CIF_ISP_BLS_H1_STOP		(CIF_ISP_BLS_BASE + 0x0000000c)
>> +#define CIF_ISP_BLS_V1_START		(CIF_ISP_BLS_BASE + 0x00000010)
>> +#define CIF_ISP_BLS_V1_STOP		(CIF_ISP_BLS_BASE + 0x00000014)
>> +#define CIF_ISP_BLS_H2_START		(CIF_ISP_BLS_BASE + 0x00000018)
>> +#define CIF_ISP_BLS_H2_STOP		(CIF_ISP_BLS_BASE + 0x0000001c)
>> +#define CIF_ISP_BLS_V2_START		(CIF_ISP_BLS_BASE + 0x00000020)
>> +#define CIF_ISP_BLS_V2_STOP		(CIF_ISP_BLS_BASE + 0x00000024)
>> +#define CIF_ISP_BLS_A_FIXED		(CIF_ISP_BLS_BASE + 0x00000028)
>> +#define CIF_ISP_BLS_B_FIXED		(CIF_ISP_BLS_BASE + 0x0000002c)
>> +#define CIF_ISP_BLS_C_FIXED		(CIF_ISP_BLS_BASE + 0x00000030)
>> +#define CIF_ISP_BLS_D_FIXED		(CIF_ISP_BLS_BASE + 0x00000034)
>> +#define CIF_ISP_BLS_A_MEASURED		(CIF_ISP_BLS_BASE + 0x00000038)
>> +#define CIF_ISP_BLS_B_MEASURED		(CIF_ISP_BLS_BASE + 0x0000003c)
>> +#define CIF_ISP_BLS_C_MEASURED		(CIF_ISP_BLS_BASE + 0x00000040)
>> +#define CIF_ISP_BLS_D_MEASURED		(CIF_ISP_BLS_BASE + 0x00000044)
>> +
>> +#define CIF_ISP_DPF_BASE		0x00002800
>> +#define CIF_ISP_DPF_MODE		(CIF_ISP_DPF_BASE + 0x00000000)
>> +#define CIF_ISP_DPF_STRENGTH_R		(CIF_ISP_DPF_BASE + 0x00000004)
>> +#define CIF_ISP_DPF_STRENGTH_G		(CIF_ISP_DPF_BASE + 0x00000008)
>> +#define CIF_ISP_DPF_STRENGTH_B		(CIF_ISP_DPF_BASE + 0x0000000C)
>> +#define CIF_ISP_DPF_S_WEIGHT_G_1_4	(CIF_ISP_DPF_BASE + 0x00000010)
>> +#define CIF_ISP_DPF_S_WEIGHT_G_5_6	(CIF_ISP_DPF_BASE + 0x00000014)
>> +#define CIF_ISP_DPF_S_WEIGHT_RB_1_4	(CIF_ISP_DPF_BASE + 0x00000018)
>> +#define CIF_ISP_DPF_S_WEIGHT_RB_5_6	(CIF_ISP_DPF_BASE + 0x0000001C)
>> +#define CIF_ISP_DPF_NULL_COEFF_0	(CIF_ISP_DPF_BASE + 0x00000020)
>> +#define CIF_ISP_DPF_NULL_COEFF_1	(CIF_ISP_DPF_BASE + 0x00000024)
>> +#define CIF_ISP_DPF_NULL_COEFF_2	(CIF_ISP_DPF_BASE + 0x00000028)
>> +#define CIF_ISP_DPF_NULL_COEFF_3	(CIF_ISP_DPF_BASE + 0x0000002C)
>> +#define CIF_ISP_DPF_NULL_COEFF_4	(CIF_ISP_DPF_BASE + 0x00000030)
>> +#define CIF_ISP_DPF_NULL_COEFF_5	(CIF_ISP_DPF_BASE + 0x00000034)
>> +#define CIF_ISP_DPF_NULL_COEFF_6	(CIF_ISP_DPF_BASE + 0x00000038)
>> +#define CIF_ISP_DPF_NULL_COEFF_7	(CIF_ISP_DPF_BASE + 0x0000003C)
>> +#define CIF_ISP_DPF_NULL_COEFF_8	(CIF_ISP_DPF_BASE + 0x00000040)
>> +#define CIF_ISP_DPF_NULL_COEFF_9	(CIF_ISP_DPF_BASE + 0x00000044)
>> +#define CIF_ISP_DPF_NULL_COEFF_10	(CIF_ISP_DPF_BASE + 0x00000048)
>> +#define CIF_ISP_DPF_NULL_COEFF_11	(CIF_ISP_DPF_BASE + 0x0000004C)
>> +#define CIF_ISP_DPF_NULL_COEFF_12	(CIF_ISP_DPF_BASE + 0x00000050)
>> +#define CIF_ISP_DPF_NULL_COEFF_13	(CIF_ISP_DPF_BASE + 0x00000054)
>> +#define CIF_ISP_DPF_NULL_COEFF_14	(CIF_ISP_DPF_BASE + 0x00000058)
>> +#define CIF_ISP_DPF_NULL_COEFF_15	(CIF_ISP_DPF_BASE + 0x0000005C)
>> +#define CIF_ISP_DPF_NULL_COEFF_16	(CIF_ISP_DPF_BASE + 0x00000060)
>> +#define CIF_ISP_DPF_NF_GAIN_R		(CIF_ISP_DPF_BASE + 0x00000064)
>> +#define CIF_ISP_DPF_NF_GAIN_GR		(CIF_ISP_DPF_BASE + 0x00000068)
>> +#define CIF_ISP_DPF_NF_GAIN_GB		(CIF_ISP_DPF_BASE + 0x0000006C)
>> +#define CIF_ISP_DPF_NF_GAIN_B		(CIF_ISP_DPF_BASE + 0x00000070)
>> +
>> +#define CIF_ISP_DPCC_BASE		0x00002900
>> +#define CIF_ISP_DPCC_MODE		(CIF_ISP_DPCC_BASE + 0x00000000)
>> +#define CIF_ISP_DPCC_OUTPUT_MODE	(CIF_ISP_DPCC_BASE + 0x00000004)
>> +#define CIF_ISP_DPCC_SET_USE		(CIF_ISP_DPCC_BASE + 0x00000008)
>> +#define CIF_ISP_DPCC_METHODS_SET_1	(CIF_ISP_DPCC_BASE + 0x0000000C)
>> +#define CIF_ISP_DPCC_METHODS_SET_2	(CIF_ISP_DPCC_BASE + 0x00000010)
>> +#define CIF_ISP_DPCC_METHODS_SET_3	(CIF_ISP_DPCC_BASE + 0x00000014)
>> +#define CIF_ISP_DPCC_LINE_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000018)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_1	(CIF_ISP_DPCC_BASE + 0x0000001C)
>> +#define CIF_ISP_DPCC_PG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000020)
>> +#define CIF_ISP_DPCC_RND_THRESH_1	(CIF_ISP_DPCC_BASE + 0x00000024)
>> +#define CIF_ISP_DPCC_RG_FAC_1		(CIF_ISP_DPCC_BASE + 0x00000028)
>> +#define CIF_ISP_DPCC_LINE_THRESH_2	(CIF_ISP_DPCC_BASE + 0x0000002C)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_2	(CIF_ISP_DPCC_BASE + 0x00000030)
>> +#define CIF_ISP_DPCC_PG_FAC_2		(CIF_ISP_DPCC_BASE + 0x00000034)
>> +#define CIF_ISP_DPCC_RND_THRESH_2	(CIF_ISP_DPCC_BASE + 0x00000038)
>> +#define CIF_ISP_DPCC_RG_FAC_2		(CIF_ISP_DPCC_BASE + 0x0000003C)
>> +#define CIF_ISP_DPCC_LINE_THRESH_3	(CIF_ISP_DPCC_BASE + 0x00000040)
>> +#define CIF_ISP_DPCC_LINE_MAD_FAC_3	(CIF_ISP_DPCC_BASE + 0x00000044)
>> +#define CIF_ISP_DPCC_PG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000048)
>> +#define CIF_ISP_DPCC_RND_THRESH_3	(CIF_ISP_DPCC_BASE + 0x0000004C)
>> +#define CIF_ISP_DPCC_RG_FAC_3		(CIF_ISP_DPCC_BASE + 0x00000050)
>> +#define CIF_ISP_DPCC_RO_LIMITS		(CIF_ISP_DPCC_BASE + 0x00000054)
>> +#define CIF_ISP_DPCC_RND_OFFS		(CIF_ISP_DPCC_BASE + 0x00000058)
>> +#define CIF_ISP_DPCC_BPT_CTRL		(CIF_ISP_DPCC_BASE + 0x0000005C)
>> +#define CIF_ISP_DPCC_BPT_NUMBER		(CIF_ISP_DPCC_BASE + 0x00000060)
>> +#define CIF_ISP_DPCC_BPT_ADDR		(CIF_ISP_DPCC_BASE + 0x00000064)
>> +#define CIF_ISP_DPCC_BPT_DATA		(CIF_ISP_DPCC_BASE + 0x00000068)
>> +
>> +#define CIF_ISP_WDR_BASE		0x00002A00
>> +#define CIF_ISP_WDR_CTRL		(CIF_ISP_WDR_BASE + 0x00000000)
>> +#define CIF_ISP_WDR_TONECURVE_1		(CIF_ISP_WDR_BASE + 0x00000004)
>> +#define CIF_ISP_WDR_TONECURVE_2		(CIF_ISP_WDR_BASE + 0x00000008)
>> +#define CIF_ISP_WDR_TONECURVE_3		(CIF_ISP_WDR_BASE + 0x0000000C)
>> +#define CIF_ISP_WDR_TONECURVE_4		(CIF_ISP_WDR_BASE + 0x00000010)
>> +#define CIF_ISP_WDR_TONECURVE_YM_0	(CIF_ISP_WDR_BASE + 0x00000014)
>> +#define CIF_ISP_WDR_TONECURVE_YM_1	(CIF_ISP_WDR_BASE + 0x00000018)
>> +#define CIF_ISP_WDR_TONECURVE_YM_2	(CIF_ISP_WDR_BASE + 0x0000001C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_3	(CIF_ISP_WDR_BASE + 0x00000020)
>> +#define CIF_ISP_WDR_TONECURVE_YM_4	(CIF_ISP_WDR_BASE + 0x00000024)
>> +#define CIF_ISP_WDR_TONECURVE_YM_5	(CIF_ISP_WDR_BASE + 0x00000028)
>> +#define CIF_ISP_WDR_TONECURVE_YM_6	(CIF_ISP_WDR_BASE + 0x0000002C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_7	(CIF_ISP_WDR_BASE + 0x00000030)
>> +#define CIF_ISP_WDR_TONECURVE_YM_8	(CIF_ISP_WDR_BASE + 0x00000034)
>> +#define CIF_ISP_WDR_TONECURVE_YM_9	(CIF_ISP_WDR_BASE + 0x00000038)
>> +#define CIF_ISP_WDR_TONECURVE_YM_10	(CIF_ISP_WDR_BASE + 0x0000003C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_11	(CIF_ISP_WDR_BASE + 0x00000040)
>> +#define CIF_ISP_WDR_TONECURVE_YM_12	(CIF_ISP_WDR_BASE + 0x00000044)
>> +#define CIF_ISP_WDR_TONECURVE_YM_13	(CIF_ISP_WDR_BASE + 0x00000048)
>> +#define CIF_ISP_WDR_TONECURVE_YM_14	(CIF_ISP_WDR_BASE + 0x0000004C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_15	(CIF_ISP_WDR_BASE + 0x00000050)
>> +#define CIF_ISP_WDR_TONECURVE_YM_16	(CIF_ISP_WDR_BASE + 0x00000054)
>> +#define CIF_ISP_WDR_TONECURVE_YM_17	(CIF_ISP_WDR_BASE + 0x00000058)
>> +#define CIF_ISP_WDR_TONECURVE_YM_18	(CIF_ISP_WDR_BASE + 0x0000005C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_19	(CIF_ISP_WDR_BASE + 0x00000060)
>> +#define CIF_ISP_WDR_TONECURVE_YM_20	(CIF_ISP_WDR_BASE + 0x00000064)
>> +#define CIF_ISP_WDR_TONECURVE_YM_21	(CIF_ISP_WDR_BASE + 0x00000068)
>> +#define CIF_ISP_WDR_TONECURVE_YM_22	(CIF_ISP_WDR_BASE + 0x0000006C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_23	(CIF_ISP_WDR_BASE + 0x00000070)
>> +#define CIF_ISP_WDR_TONECURVE_YM_24	(CIF_ISP_WDR_BASE + 0x00000074)
>> +#define CIF_ISP_WDR_TONECURVE_YM_25	(CIF_ISP_WDR_BASE + 0x00000078)
>> +#define CIF_ISP_WDR_TONECURVE_YM_26	(CIF_ISP_WDR_BASE + 0x0000007C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_27	(CIF_ISP_WDR_BASE + 0x00000080)
>> +#define CIF_ISP_WDR_TONECURVE_YM_28	(CIF_ISP_WDR_BASE + 0x00000084)
>> +#define CIF_ISP_WDR_TONECURVE_YM_29	(CIF_ISP_WDR_BASE + 0x00000088)
>> +#define CIF_ISP_WDR_TONECURVE_YM_30	(CIF_ISP_WDR_BASE + 0x0000008C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_31	(CIF_ISP_WDR_BASE + 0x00000090)
>> +#define CIF_ISP_WDR_TONECURVE_YM_32	(CIF_ISP_WDR_BASE + 0x00000094)
>> +#define CIF_ISP_WDR_OFFSET		(CIF_ISP_WDR_BASE + 0x00000098)
>> +#define CIF_ISP_WDR_DELTAMIN		(CIF_ISP_WDR_BASE + 0x0000009C)
>> +#define CIF_ISP_WDR_TONECURVE_1_SHD	(CIF_ISP_WDR_BASE + 0x000000A0)
>> +#define CIF_ISP_WDR_TONECURVE_2_SHD	(CIF_ISP_WDR_BASE + 0x000000A4)
>> +#define CIF_ISP_WDR_TONECURVE_3_SHD	(CIF_ISP_WDR_BASE + 0x000000A8)
>> +#define CIF_ISP_WDR_TONECURVE_4_SHD	(CIF_ISP_WDR_BASE + 0x000000AC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_0_SHD	(CIF_ISP_WDR_BASE + 0x000000B0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_1_SHD	(CIF_ISP_WDR_BASE + 0x000000B4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_2_SHD	(CIF_ISP_WDR_BASE + 0x000000B8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_3_SHD	(CIF_ISP_WDR_BASE + 0x000000BC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_4_SHD	(CIF_ISP_WDR_BASE + 0x000000C0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_5_SHD	(CIF_ISP_WDR_BASE + 0x000000C4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_6_SHD	(CIF_ISP_WDR_BASE + 0x000000C8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_7_SHD	(CIF_ISP_WDR_BASE + 0x000000CC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_8_SHD	(CIF_ISP_WDR_BASE + 0x000000D0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_9_SHD	(CIF_ISP_WDR_BASE + 0x000000D4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_10_SHD	(CIF_ISP_WDR_BASE + 0x000000D8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_11_SHD	(CIF_ISP_WDR_BASE + 0x000000DC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_12_SHD	(CIF_ISP_WDR_BASE + 0x000000E0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_13_SHD	(CIF_ISP_WDR_BASE + 0x000000E4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_14_SHD	(CIF_ISP_WDR_BASE + 0x000000E8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_15_SHD	(CIF_ISP_WDR_BASE + 0x000000EC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_16_SHD	(CIF_ISP_WDR_BASE + 0x000000F0)
>> +#define CIF_ISP_WDR_TONECURVE_YM_17_SHD	(CIF_ISP_WDR_BASE + 0x000000F4)
>> +#define CIF_ISP_WDR_TONECURVE_YM_18_SHD	(CIF_ISP_WDR_BASE + 0x000000F8)
>> +#define CIF_ISP_WDR_TONECURVE_YM_19_SHD	(CIF_ISP_WDR_BASE + 0x000000FC)
>> +#define CIF_ISP_WDR_TONECURVE_YM_20_SHD	(CIF_ISP_WDR_BASE + 0x00000100)
>> +#define CIF_ISP_WDR_TONECURVE_YM_21_SHD	(CIF_ISP_WDR_BASE + 0x00000104)
>> +#define CIF_ISP_WDR_TONECURVE_YM_22_SHD	(CIF_ISP_WDR_BASE + 0x00000108)
>> +#define CIF_ISP_WDR_TONECURVE_YM_23_SHD	(CIF_ISP_WDR_BASE + 0x0000010C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_24_SHD	(CIF_ISP_WDR_BASE + 0x00000110)
>> +#define CIF_ISP_WDR_TONECURVE_YM_25_SHD	(CIF_ISP_WDR_BASE + 0x00000114)
>> +#define CIF_ISP_WDR_TONECURVE_YM_26_SHD	(CIF_ISP_WDR_BASE + 0x00000118)
>> +#define CIF_ISP_WDR_TONECURVE_YM_27_SHD	(CIF_ISP_WDR_BASE + 0x0000011C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_28_SHD	(CIF_ISP_WDR_BASE + 0x00000120)
>> +#define CIF_ISP_WDR_TONECURVE_YM_29_SHD	(CIF_ISP_WDR_BASE + 0x00000124)
>> +#define CIF_ISP_WDR_TONECURVE_YM_30_SHD	(CIF_ISP_WDR_BASE + 0x00000128)
>> +#define CIF_ISP_WDR_TONECURVE_YM_31_SHD	(CIF_ISP_WDR_BASE + 0x0000012C)
>> +#define CIF_ISP_WDR_TONECURVE_YM_32_SHD	(CIF_ISP_WDR_BASE + 0x00000130)
>> +
>> +#define CIF_ISP_VSM_BASE		0x00002F00
>> +#define CIF_ISP_VSM_MODE		(CIF_ISP_VSM_BASE + 0x00000000)
>> +#define CIF_ISP_VSM_H_OFFS		(CIF_ISP_VSM_BASE + 0x00000004)
>> +#define CIF_ISP_VSM_V_OFFS		(CIF_ISP_VSM_BASE + 0x00000008)
>> +#define CIF_ISP_VSM_H_SIZE		(CIF_ISP_VSM_BASE + 0x0000000C)
>> +#define CIF_ISP_VSM_V_SIZE		(CIF_ISP_VSM_BASE + 0x00000010)
>> +#define CIF_ISP_VSM_H_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000014)
>> +#define CIF_ISP_VSM_V_SEGMENTS		(CIF_ISP_VSM_BASE + 0x00000018)
>> +#define CIF_ISP_VSM_DELTA_H		(CIF_ISP_VSM_BASE + 0x0000001C)
>> +#define CIF_ISP_VSM_DELTA_V		(CIF_ISP_VSM_BASE + 0x00000020)
>> +
>> +void disable_dcrop(struct rkisp1_stream *stream, bool async);
>> +void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect,
>> +		  bool async);
>> +
>> +void dump_rsz_regs(struct rkisp1_stream *stream);
>> +void disable_rsz(struct rkisp1_stream *stream, bool async);
>> +void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
>> +		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
>> +		struct v4l2_rect *out_c, bool async);
>> +
>> +void config_mi_ctrl(struct rkisp1_stream *stream);
>> +
>> +void mp_clr_frame_end_int(void __iomem *base);
>> +void sp_clr_frame_end_int(void __iomem *base);
>> +
>> +bool mp_is_frame_end_int_masked(void __iomem *base);
>> +bool sp_is_frame_end_int_masked(void __iomem *base);
>> +bool mp_is_stream_stopped(void __iomem *base);
>> +bool sp_is_stream_stopped(void __iomem *base);
>> +
>> +static inline void mi_set_y_size(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.y_size_init);
>> +}
>> +
>> +static inline void mi_set_cb_size(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cb_size_init);
>> +}
>> +
>> +static inline void mi_set_cr_size(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cr_size_init);
>> +}
>> +
>> +static inline void mi_set_y_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.y_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_cb_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cb_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_cr_addr(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cr_base_ad_init);
>> +}
>> +
>> +static inline void mi_set_y_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.y_offs_cnt_init);
>> +}
>> +
>> +static inline void mi_set_cb_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cb_offs_cnt_init);
>> +}
>> +
>> +static inline void mi_set_cr_offset(struct rkisp1_stream *stream, int val)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +
>> +	writel(val, base + stream->config->mi.cr_offs_cnt_init);
>> +}
>> +
>> +static inline void mi_frame_end_int_enable(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +	writel(CIF_MI_FRAME(stream) | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_frame_end_int_disable(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *addr = base + CIF_MI_IMSC;
>> +
>> +	writel(~CIF_MI_FRAME(stream) & readl(addr), addr);
>> +}
>> +
>> +static inline void mi_frame_end_int_clear(struct rkisp1_stream *stream)
>> +{
>> +	void __iomem *base = stream->ispdev->base_addr;
>> +	void __iomem *addr = base + CIF_MI_ICR;
>> +
>> +	writel(CIF_MI_FRAME(stream), addr);
>> +}
>> +
>> +static inline void mp_set_chain_mode(void __iomem *base)
>> +{
>> +	u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
>> +	writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void sp_set_chain_mode(void __iomem *base)
>> +{
>> +	u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
>> +	writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void mp_set_data_path(void __iomem *base)
>> +{
>> +	u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +	dpcl = dpcl | CIF_VI_DPCL_CHAN_MODE_MP | CIF_VI_DPCL_MP_MUX_MRSZ_MI;
>> +	writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void sp_set_data_path(void __iomem *base)
>> +{
>> +	u32 dpcl = readl(base + CIF_VI_DPCL);
>> +
>> +	dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
>> +	writel(dpcl, base + CIF_VI_DPCL);
>> +}
>> +
>> +static inline void mp_set_uv_swap(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
>> +	u32 reg = readl(addr) & ~BIT(0);
>> +
>> +	writel(reg | CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP, addr);
>> +}
>> +
>> +static inline void sp_set_uv_swap(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_XTD_FORMAT_CTRL;
>> +	u32 reg = readl(addr) & ~BIT(1);
>> +
>> +	writel(reg | CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP, addr);
>> +}
>> +
>> +static inline void sp_set_y_width(void __iomem *base, u32 val)
>> +{
>> +	writel(val, base + CIF_MI_SP_Y_PIC_WIDTH);
>> +}
>> +
>> +static inline void sp_set_y_height(void __iomem *base, u32 val)
>> +{
>> +	writel(val, base + CIF_MI_SP_Y_PIC_HEIGHT);
>> +}
>> +
>> +static inline void sp_set_y_line_length(void __iomem *base, u32 val)
>> +{
>> +	writel(val, base + CIF_MI_SP_Y_LLENGTH);
>> +}
>> +
>> +static inline void mp_mi_ctrl_set_format(void __iomem *base, u32 val)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +	u32 reg = readl(addr) & ~MI_CTRL_MP_FMT_MASK;
>> +
>> +	writel(reg | val, addr);
>> +}
>> +
>> +static inline void sp_mi_ctrl_set_format(void __iomem *base, u32 val)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +	u32 reg = readl(addr) & ~MI_CTRL_SP_FMT_MASK;
>> +
>> +	writel(reg | val, addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpyuv_enable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(CIF_MI_CTRL_MP_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpyuv_disable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(~CIF_MI_CTRL_MP_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mp_disable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(~(CIF_MI_CTRL_MP_ENABLE | CIF_MI_CTRL_RAW_ENABLE) & readl(addr),
>> +	       addr);
>> +}
>> +
>> +static inline void mi_ctrl_spyuv_enable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(CIF_MI_CTRL_SP_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_spyuv_disable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(~CIF_MI_CTRL_SP_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_sp_disable(void __iomem *base)
>> +{
>> +	mi_ctrl_spyuv_disable(base);
>> +}
>> +
>> +static inline void mi_ctrl_mpraw_enable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(CIF_MI_CTRL_RAW_ENABLE | readl(addr), addr);
>> +}
>> +
>> +static inline void mi_ctrl_mpraw_disable(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(~CIF_MI_CTRL_RAW_ENABLE & readl(addr), addr);
>> +}
>> +
>> +static inline void mp_mi_ctrl_autoupdate_en(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(readl(addr) | CIF_MI_MP_AUTOUPDATE_ENABLE, addr);
>> +}
>> +
>> +static inline void sp_mi_ctrl_autoupdate_en(void __iomem *base)
>> +{
>> +	void __iomem *addr = base + CIF_MI_CTRL;
>> +
>> +	writel(readl(addr) | CIF_MI_SP_AUTOUPDATE_ENABLE, addr);
>> +}
>> +
>> +static inline void force_cfg_update(void __iomem *base)
>> +{
>> +	writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT);
>> +}
>> +
>> +#endif /* _RKISP1_REGS_H */

^ permalink raw reply

* Re: [PATCH v2] ARM: dts: vf610-bk4: Fix qspi node description
From: Fabio Estevam @ 2019-07-31 13:49 UTC (permalink / raw)
  To: Lukasz Majewski
  Cc: Shawn Guo, Sascha Hauer, Stefan Agner, Rob Herring, Mark Rutland,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel
In-Reply-To: <20190730214833.30659-1-lukma@denx.de>

Hi Lukasz,

On Tue, Jul 30, 2019 at 6:48 PM Lukasz Majewski <lukma@denx.de> wrote:
>
> Before this change the device tree description of qspi node for
> second memory on BK4 board was wrong (applicable to old, removed
> fsl-quadspi.c driver).
>
> As a result this memory was not recognized correctly when used
> with the new spi-fsl-qspi.c driver.
>
> From the dt-bindings:
>
> "Required SPI slave node properties:
>   - reg: There are two buses (A and B) with two chip selects each.
> This encodes to which bus and CS the flash is connected:
> <0>: Bus A, CS 0
> <1>: Bus A, CS 1
> <2>: Bus B, CS 0
> <3>: Bus B, CS 1"
>
> According to above with new driver the second SPI-NOR memory shall
> have reg=<2> as it is connected to Bus B, CS 0.
>
> Signed-off-by: Lukasz Majewski <lukma@denx.de>
> Suggested-by: Fabio Estevam <festevam@gmail.com>
> Fixes: a67d2c52a82f ("ARM: dts: Add support for Liebherr's BK4 device
> (vf610 based)")

Please fix the order of the tags.

- Fixes tag goes first (do not split it into two lines)
- Suggested-by
- Your Signed-off-by

With these changes you can add as the last tag:

Reviewed-by: Fabio Estevam <festevam@gmail.com>

^ permalink raw reply

* RE: [PATCH V7 00/11] misc: xilinx sd-fec drive
From: Dragan Cvetic @ 2019-07-31 13:56 UTC (permalink / raw)
  To: Greg KH
  Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, arnd@arndb.de,
	linux-kernel@vger.kernel.org, robh+dt@kernel.org, Michal Simek,
	Derek Kiernan, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190731124853.GA4905@kroah.com>



> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Wednesday 31 July 2019 13:49
> To: Dragan Cvetic <draganc@xilinx.com>
> Cc: arnd@arndb.de; Michal Simek <michals@xilinx.com>; linux-arm-kernel@lists.infradead.org; robh+dt@kernel.org;
> mark.rutland@arm.com; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Derek Kiernan <dkiernan@xilinx.com>
> Subject: Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
> 
> On Sat, Jun 22, 2019 at 05:54:04PM +0000, Dragan Cvetic wrote:
> >
> >
> > > -----Original Message-----
> > > From: Greg KH [mailto:gregkh@linuxfoundation.org]
> > > Sent: Saturday 22 June 2019 07:02
> > > To: Dragan Cvetic <draganc@xilinx.com>
> > > Cc: arnd@arndb.de; Michal Simek <michals@xilinx.com>; linux-arm-kernel@lists.infradead.org; robh+dt@kernel.org;
> > > mark.rutland@arm.com; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Derek Kiernan <dkiernan@xilinx.com>
> > > Subject: Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
> > >
> > > On Fri, Jun 21, 2019 at 05:49:45PM +0000, Dragan Cvetic wrote:
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Greg KH [mailto:gregkh@linuxfoundation.org]
> > > > > Sent: Friday 21 June 2019 15:16
> > > > > To: Dragan Cvetic <draganc@xilinx.com>
> > > > > Cc: arnd@arndb.de; Michal Simek <michals@xilinx.com>; linux-arm-kernel@lists.infradead.org; robh+dt@kernel.org;
> > > > > mark.rutland@arm.com; devicetree@vger.kernel.org; linux-kernel@vger.kernel.org; Derek Kiernan <dkiernan@xilinx.com>
> > > > > Subject: Re: [PATCH V7 00/11] misc: xilinx sd-fec drive
> > > > >
> > > > > On Tue, Jun 11, 2019 at 06:29:34PM +0100, Dragan Cvetic wrote:
> > > > > > This patchset is adding the full Soft Decision Forward Error
> > > > > > Correction (SD-FEC) driver implementation, driver DT binding and
> > > > > > driver documentation.
> > > > > >
> > > > > > Forward Error Correction (FEC) codes such as Low Density Parity
> > > > > > Check (LDPC) and turbo codes provide a means to control errors in
> > > > > > data transmissions over unreliable or noisy communication
> > > > > > channels. The SD-FEC Integrated Block is an optimized block for
> > > > > > soft-decision decoding of these codes. Fixed turbo codes are
> > > > > > supported directly, whereas custom and standardized LDPC codes
> > > > > > are supported through the ability to specify the parity check
> > > > > > matrix through an AXI4-Lite bus or using the optional programmable
> > > > > > (PL)-based support logic. For the further information see
> > > > > > https://www.xilinx.com/support/documentation/ip_documentation/
> > > > > > sd_fec/v1_1/pg256-sdfec-integrated-block.pdf
> > > > > >
> > > > > > This driver is a platform device driver which supports SDFEC16
> > > > > > (16nm) IP. SD-FEC driver supports LDPC decoding and encoding and
> > > > > > Turbo code decoding. LDPC codes can be specified on
> > > > > > a codeword-by-codeword basis, also a custom LDPC code can be used.
> > > > > >
> > > > > > The SD-FEC driver exposes a char device interface and supports
> > > > > > file operations: open(), close(), poll() and ioctl(). The driver
> > > > > > allows only one usage of the device, open() limits the number of
> > > > > > driver instances. The driver also utilize Common Clock Framework
> > > > > > (CCF).
> > > > > >
> > > > > > The control and monitoring is supported over ioctl system call.
> > > > > > The features supported by ioctl():
> > > > > > - enable or disable data pipes to/from device
> > > > > > - configure the FEC algorithm parameters
> > > > > > - set the order of data
> > > > > > - provide a control of a SDFEC bypass option
> > > > > > - activates/deactivates SD-FEC
> > > > > > - collect and provide statistical data
> > > > > > - enable/disable interrupt mode
> > > > >
> > > > > Is there any userspace tool that talks to this device using these custom
> > > > > ioctls yet?
> > > > >
> > > > Tools no, but could be the customer who is using the driver.
> > >
> > > I don't understand this.  Who has written code to talk to these
> > > special ioctls from userspace?  Is there a pointer to that code
> > > anywhere?
> > >
> >
> > The code which use this driver are written by the driver maintainers
> > they are examples APP and test code which are not public.
> 
> So, no open code is talking to this one specific driver?  And you have
> run this past your lawyers?  Please go talk to them about this and see
> what they say (hint, creating a custom ioctl that only you use is a
> "fun" legal area...)


Greg,
this driver and all example code APP will be public and open source 
fully. In that sense this code is same as any other driver. 


> 
> > > > > Doing a one-off ioctl api is always a risky thing, you are pretty much
> > > > > just creating brand new system calls for one piece of hardware.
> > > > >
> > > >
> > > > Why is that wrong and what is the risk?
> > >
> > > You now have custom syscalls for one specfic piece of hardware that you
> > > now have to maintain working properly for the next 40+ years.  You have
> > > to make sure those calls are correct and that this is the correct api to
> > > talk to this hardware.
> >
> > This is very specific HW, it's high speed Forward Error Correction HW.
> 
> I have no idea what that actually means.
> 
> What is "Forward Error Correction"?  What does it do?  Is this a network
> device?  Video device?  Random black box that sends radio waves?
> 
> Is there no other in-kernel driver that does much the same type of
> thing?  What "class" of driver would this be?

This is the RF data communication device, type "misc" driver.

> 
> > > > What would you propose?
> > > > Definitely, I have to read about this.
> > >
> > > What is this hardware and what is it used for?  Who will be talking to
> >
> > The Soft-Decision Forward Error Correction (SD-FEC) integrated block
> > supports Low Density Parity Check (LDPC) decoding and encoding and
> > Turbo code decoding.
> 
> I still don't understand what this means.
> 
> > SD-FEC use case is in high data rate applications such as 4G, 5G and
> > DOCSIS3.1 Cable Access.  A high performance SD-FEC (i.e. >1Gbps), is a
> > block used to enable these systems to function under non-ideal
> > environments.
> 
> Nor do I understand what this is either.  Do you have a pointer to this
> hardware somewhere online that might describe it better?  Given that I
> have no clue, odds are others do not know what it is either.

https://www.xilinx.com/support/documentation/ip_documentation/sd_fec/v1_1/pg256-sdfec-integrated-block.pdf

> 
> > > it from userspace?  What userspace workload uses it?  What tools need to
> >
> > There will be APP which configures the HW for the use cases listed above.
> 
> What exactly are these use cases?
> 
> Where is the application?  Who runs it?  Is it already in a distro
> somewhere?  Who is going to distribute it?  Who is going to support it?
> Is it only for sale?  What is the license of it?

According to marketing people here there are about 72 individual programs 
spanning probably ~40 different customers. These are possible users
and APP will be created and run by them.
Driver will be supported by us, APP by customers with our technical support.
Is it for sale? Xilinx gives away all drivers and examples for free, it's up to the
Customer what they do with it and they meet open source licence legal requirements.

Greg,
I'll be out of the office from Friday for a couple of weeks, and I'll try my best to respond on your replies after that.

> 
> thanks,
> 
> greg k-h

^ permalink raw reply

* [PATCH v4 1/2] iio: potentiometer: add a driver for Maxim 5432-5435
From: Martin Kaiser @ 2019-07-31 14:07 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen, Rob Herring
  Cc: linux-iio, devicetree, linux-kernel, Martin Kaiser
In-Reply-To: <20190721175915.27192-1-martin@kaiser.cx>

Add a driver for the Maxim Integrated MAX5432-MAX5435 family of digital
potentiometers.

These potentiometers are connected via I2C and have 32 wiper
positions.

Supported functionality
- set the volatile wiper position
- read the potentiometer scale

Datasheet:
https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf

Signed-off-by: Martin Kaiser <martin@kaiser.cx>
---
changes in v4
 - fix the dt bindings
   - replace ic20 with i2c
   - document the reg property
   - add additionalProperties and required

changes in v3
 - split dt bindings and driver code into separate patches
 - use yaml format for dt bindings
 - fix formatting of parameter lists

changes in v2
 - use MAX5432_ prefix for all defines
 - fix indentation
 - convert void * to unsigned long, not to u32
   (warning from kbuild test robot)

 drivers/iio/potentiometer/Kconfig   |  11 +++
 drivers/iio/potentiometer/Makefile  |   1 +
 drivers/iio/potentiometer/max5432.c | 135 ++++++++++++++++++++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 drivers/iio/potentiometer/max5432.c

diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig
index ebc7c72a5e36..4cac0173db8b 100644
--- a/drivers/iio/potentiometer/Kconfig
+++ b/drivers/iio/potentiometer/Kconfig
@@ -26,6 +26,17 @@ config DS1803
 	  To compile this driver as a module, choose M here: the
 	  module will be called ds1803.
 
+config MAX5432
+	tristate "Maxim MAX5432-MAX5435 Digital Potentiometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the Maxim
+	  MAX5432, MAX5433, MAX5434 and MAX5435 digital
+	  potentiometer chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called max5432.
+
 config MAX5481
 	tristate "Maxim MAX5481-MAX5484 Digital Potentiometer driver"
 	depends on SPI
diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile
index 8ff55138cf12..091adf3cdd0b 100644
--- a/drivers/iio/potentiometer/Makefile
+++ b/drivers/iio/potentiometer/Makefile
@@ -6,6 +6,7 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD5272) += ad5272.o
 obj-$(CONFIG_DS1803) += ds1803.o
+obj-$(CONFIG_MAX5432) += max5432.o
 obj-$(CONFIG_MAX5481) += max5481.o
 obj-$(CONFIG_MAX5487) += max5487.o
 obj-$(CONFIG_MCP4018) += mcp4018.o
diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c
new file mode 100644
index 000000000000..641b1821fdf6
--- /dev/null
+++ b/drivers/iio/potentiometer/max5432.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Maxim Integrated MAX5432-MAX5435 digital potentiometer driver
+ * Copyright (C) 2019 Martin Kaiser <martin@kaiser.cx>
+ *
+ * Datasheet:
+ * https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf
+ */
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+/* All chip variants have 32 wiper positions. */
+#define MAX5432_MAX_POS 31
+
+#define MAX5432_OHM_50K   (50  * 1000)
+#define MAX5432_OHM_100K  (100 * 1000)
+
+/* Update the volatile (currently active) setting. */
+#define MAX5432_CMD_VREG  0x11
+
+struct max5432_data {
+	struct i2c_client *client;
+	unsigned long ohm;
+};
+
+static const struct iio_chan_spec max5432_channels[] = {
+	{
+		.type = IIO_RESISTANCE,
+		.indexed = 1,
+		.output = 1,
+		.channel = 0,
+		.address = MAX5432_CMD_VREG,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+	}
+};
+
+static int max5432_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val, int *val2, long mask)
+{
+	struct max5432_data *data = iio_priv(indio_dev);
+
+	if (mask != IIO_CHAN_INFO_SCALE)
+		return -EINVAL;
+
+	if (unlikely(data->ohm > INT_MAX))
+		return -ERANGE;
+
+	*val = data->ohm;
+	*val2 = MAX5432_MAX_POS;
+
+	return IIO_VAL_FRACTIONAL;
+}
+
+static int max5432_write_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int val, int val2, long mask)
+{
+	struct max5432_data *data = iio_priv(indio_dev);
+	u8 data_byte;
+
+	if (mask != IIO_CHAN_INFO_RAW)
+		return -EINVAL;
+
+	if (val < 0 || val > MAX5432_MAX_POS)
+		return -EINVAL;
+
+	if (val2 != 0)
+		return -EINVAL;
+
+	/* Wiper position is in bits D7-D3. (D2-D0 are don't care bits.) */
+	data_byte = val << 3;
+	return i2c_smbus_write_byte_data(data->client, chan->address,
+			data_byte);
+}
+
+static const struct iio_info max5432_info = {
+	.read_raw = max5432_read_raw,
+	.write_raw = max5432_write_raw,
+};
+
+static int max5432_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct max5432_data *data;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(struct max5432_data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, indio_dev);
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	data->ohm = (unsigned long)of_device_get_match_data(dev);
+
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &max5432_info;
+	indio_dev->channels = max5432_channels;
+	indio_dev->num_channels = ARRAY_SIZE(max5432_channels);
+	indio_dev->name = client->name;
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id max5432_dt_ids[] = {
+	{ .compatible = "maxim,max5432", .data = (void *)MAX5432_OHM_50K  },
+	{ .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K },
+	{ .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K  },
+	{ .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, max5432_dt_ids);
+
+static struct i2c_driver max5432_driver = {
+	.driver = {
+		.name = "max5432",
+		.of_match_table = of_match_ptr(max5432_dt_ids),
+	},
+	.probe = max5432_probe,
+};
+
+module_i2c_driver(max5432_driver);
+
+MODULE_AUTHOR("Martin Kaiser <martin@kaiser.cx>");
+MODULE_DESCRIPTION("max5432-max5435 digital potentiometers");
+MODULE_LICENSE("GPL v2");
-- 
2.11.0

^ permalink raw reply related

* [PATCH v4 2/2] dt-bindings: iio: potentiometer: add max5432.yaml binding
From: Martin Kaiser @ 2019-07-31 14:07 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen, Rob Herring
  Cc: linux-iio, devicetree, linux-kernel, Martin Kaiser
In-Reply-To: <20190731140706.2765-1-martin@kaiser.cx>

Add a binding for the Maxim Integrated MAX5432-MAX5435 family of digital
potentiometers.

Signed-off-by: Martin Kaiser <martin@kaiser.cx>
---
changes in v4
 - fix the dt bindings
   - replace ic20 with i2c
   - document the reg property
   - add additionalProperties and required

changes in v3
 - split dt bindings and driver code into separate patches
 - use yaml format for dt bindings
 - fix formatting of parameter lists

changes in v2
 - use MAX5432_ prefix for all defines
 - fix indentation
 - convert void * to unsigned long, not to u32
   (warning from kbuild test robot)

 .../bindings/iio/potentiometer/max5432.yaml        | 44 ++++++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml

diff --git a/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml
new file mode 100644
index 000000000000..5082f919df2a
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/potentiometer/max5432.yaml
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/potentiometer/max5432.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim Integrated MAX5432-MAX5435 Digital Potentiometers
+
+maintainers:
+  - Martin Kaiser <martin@kaiser.cx>
+
+description: |
+  Maxim Integrated MAX5432-MAX5435 Digital Potentiometers connected via I2C
+
+  Datasheet:
+    https://datasheets.maximintegrated.com/en/ds/MAX5432-MAX5435.pdf
+
+properties:
+  compatible:
+    enum:
+      - maxim,max5432
+      - maxim,max5433
+      - maxim,max5434
+      - maxim,max5435
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      max5434@28 {
+        compatible = "maxim,max5434";
+        reg = <0x28>;
+      };
+    };
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v3 02/14] mbox: qcom: add APCS child device for QCS404
From: Jorge Ramirez @ 2019-07-31 14:10 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: mark.rutland, heiko, mturquette, will.deacon, david.brown,
	linux-clk, jassisinghbrar, sibis, jagan, devicetree,
	niklas.cassel, arnd, linux-arm-msm, olof, robh+dt, horms+renesas,
	linux-arm-kernel, sboyd, linux-kernel, amit.kucheria, vkoul,
	khasim.mohammed, enric.balletbo, georgi.djakov
In-Reply-To: <20190711144424.GD7234@tuxbook-pro>

On 7/11/19 16:44, Bjorn Andersson wrote:
> On Tue 25 Jun 09:47 PDT 2019, Jorge Ramirez-Ortiz wrote:
> 
>> There is clock controller functionality in the APCS hardware block of
>> qcs404 devices similar to msm8916.
>>
>> Co-developed-by: Niklas Cassel <niklas.cassel@linaro.org>
>> Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
>> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
>> ---
>>  drivers/mailbox/qcom-apcs-ipc-mailbox.c | 18 ++++++++++--------
>>  1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
>> index 705e17a5479c..a05dc3aabac7 100644
>> --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
>> +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
>> @@ -89,16 +89,18 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
>>  		return ret;
>>  	}
>>  
>> -	if (of_device_is_compatible(np, "qcom,msm8916-apcs-kpss-global")) {
>> -		apcs->clk = platform_device_register_data(&pdev->dev,
>> -							  "qcom-apcs-msm8916-clk",
>> -							  -1, NULL, 0);
>> -		if (IS_ERR(apcs->clk))
>> -			dev_err(&pdev->dev, "failed to register APCS clk\n");
>> -	}
>> -
>>  	platform_set_drvdata(pdev, apcs);
>>  
>> +	if (!of_device_is_compatible(np, "qcom,msm8916-apcs-kpss-global") &&
>> +	    !of_device_is_compatible(np, "qcom,qcs404-apcs-apps-global"))
> 
> If the remainder of the function was a long snippet I think this would
> motivate the somewhat unusual early return. But I think it would be
> cleaner to just add to the existing conditional.

sure can do that. I dont agree (I wouldnt have bothered otherwise :))
but will do

> 
> Regards,
> Bjorn
> 
>> +		return 0;
>> +
>> +	apcs->clk = platform_device_register_data(&pdev->dev,
>> +						  "qcom-apcs-msm8916-clk",
>> +						  -1, NULL, 0);
>> +	if (IS_ERR(apcs->clk))
>> +		dev_err(&pdev->dev, "failed to register APCS clk\n");
>> +
>>  	return 0;
>>  }
>>  
>> -- 
>> 2.21.0
>>
> 

^ permalink raw reply

* [PATCH v3] ARM: dts: vf610-bk4: Fix qspi node description
From: Lukasz Majewski @ 2019-07-31 14:11 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam
  Cc: Sascha Hauer, Stefan Agner, Rob Herring, Mark Rutland,
	linux-arm-kernel, devicetree, linux-kernel, Lukasz Majewski

Before this change the device tree description of qspi node for
second memory on BK4 board was wrong (applicable to old, removed
fsl-quadspi.c driver).

As a result this memory was not recognized correctly when used
with the new spi-fsl-qspi.c driver.

>From the dt-bindings:

"Required SPI slave node properties:
  - reg: There are two buses (A and B) with two chip selects each.
This encodes to which bus and CS the flash is connected:
<0>: Bus A, CS 0
<1>: Bus A, CS 1
<2>: Bus B, CS 0
<3>: Bus B, CS 1"

According to above with new driver the second SPI-NOR memory shall
have reg=<2> as it is connected to Bus B, CS 0.

Fixes: a67d2c52a82f ("ARM: dts: Add support for Liebherr's BK4 device (vf610 based)")
Suggested-by: Fabio Estevam <festevam@gmail.com>
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Fabio Estevam <festevam@gmail.com>

---
Changes for v3:
- Reorder Signed-off, Suggested-by and Fixes tags
- Add Reviewed-by: Fabio Estevam <festevam@gmail.com>

Changes for v2:
- Add proper Suggested-by tag as Fabio was the one who pointed out the
  the issue with wrong reg number assignment for the second SPI-NOR memory
- Add Fixes: tag, so the patch could be added to LTS kernels
- Fix the subject line to more appropriate
---
 arch/arm/boot/dts/vf610-bk4.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/vf610-bk4.dts b/arch/arm/boot/dts/vf610-bk4.dts
index 3fa0cbe456db..0f3870d3b099 100644
--- a/arch/arm/boot/dts/vf610-bk4.dts
+++ b/arch/arm/boot/dts/vf610-bk4.dts
@@ -246,13 +246,13 @@
 		reg = <0>;
 	};
 
-	n25q128a13_2: flash@1 {
+	n25q128a13_2: flash@2 {
 		compatible = "n25q128a13", "jedec,spi-nor";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		spi-max-frequency = <66000000>;
 		spi-rx-bus-width = <2>;
-		reg = <1>;
+		reg = <2>;
 	};
 };
 
-- 
2.11.0

^ permalink raw reply related

* RE: [PATCH/RFC] ARM: dts: rza2mevb: Fix numbering of Ethernet aliases
From: Chris Brandt @ 2019-07-31 14:28 UTC (permalink / raw)
  To: Geert Uytterhoeven, Simon Horman, Magnus Damm, Marek Vasut
  Cc: Rob Herring, Mark Rutland, linux-renesas-soc@vger.kernel.org,
	devicetree@vger.kernel.org
In-Reply-To: <20190731133936.18228-1-geert+renesas@glider.be>

Hi Geert,

On Wed, Jul 31, 2019, Geert Uytterhoeven wrote:
> The two Ethernet ports on the RZA2MEVB development board are labeled
> "Ether1" and "Ether2".  Reflect this numbering in the ethernet aliases.

However, the channels are labeled as ETHERC0 and ETHERC1 in the hardware
manual.

So I guess my question is, in general, is the board specific Device Tree
supposed to describe what is on the SoC? Or on the board silk screen?

Maybe this is like "COM1" is labeled on PC motherboard and we expect it 
to show up as /dev/ttyS0 regardless of what physical serial port it is 
connected to.

Thanks,
Chris

^ permalink raw reply

* Re: [PATCH v3 08/14] clk: qcom: hfpll: CLK_IGNORE_UNUSED
From: Jorge Ramirez @ 2019-07-31 14:30 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: sboyd, david.brown, jassisinghbrar, mark.rutland, mturquette,
	robh+dt, will.deacon, arnd, horms+renesas, heiko, sibis,
	enric.balletbo, jagan, olof, vkoul, niklas.cassel, georgi.djakov,
	amit.kucheria, devicetree, linux-kernel, linux-arm-kernel,
	linux-clk, linux-arm-msm, khasim.mohammed
In-Reply-To: <20190711151631.GI7234@tuxbook-pro>

On 7/11/19 17:16, Bjorn Andersson wrote:
> On Tue 25 Jun 09:47 PDT 2019, Jorge Ramirez-Ortiz wrote:
> 
>> When COMMON_CLK_DISABLED_UNUSED is set, in an effort to save power and
>> to keep the software model of the clock in line with reality, the
>> framework transverses the clock tree and disables those clocks that
>> were enabled by the firmware but have not been enabled by any device
>> driver.
>>
>> If CPUFREQ is enabled, early during the system boot, it might attempt
>> to change the CPU frequency ("set_rate"). If the HFPLL is selected as
>> a provider, it will then change the rate for this clock.
>>
>> As boot continues, clk_disable_unused_subtree will run. Since it wont
>> find a valid counter (enable_count) for a clock that is actually
>> enabled it will attempt to disable it which will cause the CPU to
>> stop.
> 
> But if CPUfreq has acquired the CPU clock and the hfpll is the currently
> selected input, why does the clock framework not know about this clock
> being used?

right, see the comment right below - maybe I should have been more
explicit at the time. sorry about it.

> 
>> Notice that in this driver, calls to check whether the clock is
>> enabled are routed via the is_enabled callback which queries the
>> hardware.

calls to check whether the clock is enabled dont use the usage counter
but a hardware read. IIRC the clock framework will check some counter to
know if the clock is being used.

>>
>> The following commit, rather than marking the clock critical and
>> forcing the clock to be always enabled, addresses the above scenario
>> making sure the clock is not disabled but it continues to rely on the
>> firmware to enable the clock.
>>
>> Co-developed-by: Niklas Cassel <niklas.cassel@linaro.org>
>> Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>
>> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
> 
> 
> I can see that we have a real issue in the case where CPUfreq is not
> enabled and hence there are no clients, according to Linux. And that I
> don't know another way to guard against.

the issue is there when CPUfreq is enabled that is for sure (if we just
remove this commit the system will not boot due to the situation I tried
to describe above).

> 
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> 
> Regards,
> Bjorn
> 
>> ---
>>  drivers/clk/qcom/hfpll.c | 7 +++++++
>>  1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c
>> index 0ffed0d41c50..d5fd27938e7b 100644
>> --- a/drivers/clk/qcom/hfpll.c
>> +++ b/drivers/clk/qcom/hfpll.c
>> @@ -58,6 +58,13 @@ static int qcom_hfpll_probe(struct platform_device *pdev)
>>  		.parent_names = (const char *[]){ "xo" },
>>  		.num_parents = 1,
>>  		.ops = &clk_ops_hfpll,
>> +		/*
>> +		 * rather than marking the clock critical and forcing the clock
>> +		 * to be always enabled, we make sure that the clock is not
>> +		 * disabled: the firmware remains responsible of enabling this
>> +		 * clock (for more info check the commit log)
>> +		 */
>> +		.flags = CLK_IGNORE_UNUSED,
>>  	};
>>  
>>  	h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);
>> -- 
>> 2.21.0
>>
> 

^ permalink raw reply

* Re: [PATCH 3/3] drm/bridge: Add NWL MIPI DSI host controller support
From: Guido Günther @ 2019-07-31 14:35 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: David Airlie, Daniel Vetter, Rob Herring, Mark Rutland, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, NXP Linux Team,
	Andrzej Hajda, Neil Armstrong, Laurent Pinchart, Jonas Karlman,
	Jernej Skrabec, Lee Jones, DRI mailing list,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAOMZO5BRbV_1du1b9eJqcBvvXSE2Mon3yxSPJxPpZgBqYNjBSg@mail.gmail.com>

Hi Fabio,
thanks for having a look! I followed most of your comments, there's some
things i'm unsure, see below:

On Fri, Jul 26, 2019 at 05:01:52PM -0300, Fabio Estevam wrote:
> Hi Guido,
> 
> Thanks for your work on this driver!
> 
> On Wed, Jul 24, 2019 at 12:52 PM Guido Günther <agx@sigxcpu.org> wrote:
> 
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/Kconfig
> > @@ -0,0 +1,15 @@
> > +config DRM_IMX_NWL_DSI
> > +       tristate "Support for Northwest Logic MIPI DSI Host controller"
> > +       depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST)
> 
> 
> This IP could potentially be found on other SoCs, so no need to make
> it depend on ARCH_MXC.

Done.

> > +#include <drm/drm_atomic_helper.h>
> > +#include <drm/drm_of.h>
> > +#include <drm/drm_panel.h>
> > +#include <drm/drm_print.h>
> > +#include <drm/drm_probe_helper.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/clk.h>
> > +#include <linux/component.h>
> > +#include <linux/gpio/consumer.h>
> 
> I did not find gpio AP used in this driver.

Dropped the include.

> 
> > +static void imx_nwl_dsi_set_clocks(struct imx_nwl_dsi *dsi, bool enable)
> 
> Better make it to return 'int' instead...

Done, but see below.

> 
> > +{
> > +       struct device *dev = dsi->dev;
> > +       const char *id;
> > +       struct clk *clk;
> > +       unsigned long new_rate, cur_rate;
> > +       bool enabled;
> > +       size_t i;
> > +       int ret;
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "%sabling platform clocks",
> 
> Please remove the letter 's' from 'sabling'.

The idea is to have

    "%sabling platform clocks", enable ? "en" : "dis");

depending whether clocks are enabled/disabled.

> 
> > +                            enable ? "en" : "dis");
> > +                       ret = clk_prepare_enable(clk);
> > +                       if (ret < 0) {
> > +                               DRM_DEV_ERROR(dev, "Failed to enable clock %s",
> > +                                             id);
> 
> and propagate the error in case of clk_prepare_enable() failure.

done.

> 
> > +                       }
> > +                       dsi->clk_config[i].enabled = true;
> > +                       cur_rate = clk_get_rate(clk);
> > +                       DRM_DEV_DEBUG_DRIVER(
> > +                               dev, "Enabled %s clk (rate: req=%lu act=%lu)\n",
> > +                               id, new_rate, cur_rate);
> > +               } else if (enabled) {
> > +                       clk_disable_unprepare(clk);
> > +                       dsi->clk_config[i].enabled = false;
> > +                       DRM_DEV_DEBUG_DRIVER(dev, "Disabled %s clk\n", id);
> > +               }
> > +       }
> > +}
> > +
> > +static void imx_nwl_dsi_enable(struct imx_nwl_dsi *dsi)
> 
> Same here. Please return 'int' instead.

This is from drm_bridge_funcs so the prototype is fixed. I'm not sure
how what's the best way to bubble up fatal errors through the drm layer?

> > +{
> > +       struct device *dev = dsi->dev;
> > +       int ret;
> > +
> > +       imx_nwl_dsi_set_clocks(dsi, true);
> > +
> > +       ret = dsi->pdata->poweron(dsi);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dev, "Failed to power on DSI (%d)\n", ret);
> 
> If the power domain failed to turn on, it is better to propagate the
> error.

If fixed the return type here as well but this will again get lost in
`_pre_enable` which again is void in drm_bridge_funcs (see below).

> 
> > +       phy_ref_rate = clk_get_rate(dsi->phy_ref_clk);
> > +       DRM_DEV_DEBUG_DRIVER(dev, "PHY at ref rate: %lu\n", phy_ref_rate);
> > +       if (ret < 0) {
> 
> This check looks wrong. At this point ret is always 0.

Fixed.

> 
> > +               DRM_DEV_ERROR(dsi->dev,
> > +                             "Cannot setup PHY for mode: %ux%u @%d Hz\n",
> > +                             adjusted_mode->hdisplay, adjusted_mode->vdisplay,
> > +                             adjusted_mode->clock);
> > +               DRM_DEV_ERROR(dsi->dev, "PHY ref clk: %lu, bit clk: %lu\n",
> > +                             phy_ref_rate, new_cfg.mipi_dphy.hs_clk_rate);
> > +       } else {
> > +               /* Save the new desired phy config */
> > +               memcpy(&dsi->phy_cfg, &new_cfg, sizeof(new_cfg));
> > +       }
> > +
> > +       /* LCDIF + NWL needs active high sync */
> 
> Would this still work if DCSS is used instead?

I'll check once there's a DCSS driver that can drive this. The current
vendor one is bound to imx-displays-subsystem and cant' drive a bridge.

> 
> > +       adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
> > +       adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
> > +
> > +       drm_display_mode_to_videomode(adjusted_mode, &dsi->vm);
> > +       drm_mode_debug_printmodeline(adjusted_mode);
> > +
> > +       return ret == 0;
> 
> At this point ret is always 0.

Right, there was some more logic in there that got removed. Changed to
always signal success.

> 
> > +static void imx_nwl_dsi_bridge_pre_enable(struct drm_bridge *bridge)
> > +{
> > +       struct imx_nwl_dsi *dsi = bridge_to_dsi(bridge);
> > +
> > +       if (dsi->dpms_mode == DRM_MODE_DPMS_ON)
> > +               return;
> > +
> > +       imx_nwl_select_input_source(dsi);
> 
> This function is i.MX8M specific, so better protect it to run only for
> the i.MX8M variant.

Moved into imx_nwl_platform_data.

> 
> > +       pm_runtime_get_sync(dsi->dev);
> > +       imx_nwl_dsi_enable(dsi);
> > +       nwl_dsi_enable(dsi);
> 
> Please check the error and propagate in the case of failure.

This one is again hooked in from drm_bridge_funcs which is void.

> 
> > +       dsi->dpms_mode = DRM_MODE_DPMS_ON;
> > +}
> > +
> 
> > +       dsi->csr = syscon_regmap_lookup_by_phandle(np, "csr");
> > +       if (IS_ERR(dsi->csr) && dsi->pdata->ext_regs & IMX_REG_CSR) {
> > +               ret = PTR_ERR(dsi->csr);
> > +               DRM_DEV_ERROR(dsi->dev, "Failed to get CSR regmap: %d\n",
> 
> In this function (and globally in the driver) there is a mix of
> DRM_DEV_ERROR() and dev_err().
> 
> Can we just pick one of the two and use it consistently?
> 
> Not sure what is the norm in drm code, but IMHO dev_err() looks
> prettier :-)

I went for DRM_DEV_ERROR() since that what i used in the rest of the
driver and these ones were omission. Hope that's o.k.

> 
> > +
> > +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       base = devm_ioremap_resource(dsi->dev, res);
> 
> Could use devm_platform_ioremap_resource(), which makes it simpler.

Done.

> 
> > +err_cleanup:
> > +       devm_free_irq(dev, dsi->irq, dsi);
> 
> No need to call devm_free_irq() here. The devm functions do not need
> to be freed on probe.

Removed.

> 
> > diff --git a/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c
> > new file mode 100644
> > index 000000000000..0e1463af162f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/bridge/imx-nwl/nwl-dsi.c
> > @@ -0,0 +1,745 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * NWL DSI host driver
> > + *
> > + * Copyright (C) 2017 NXP
> > + * Copyright (C) 2019 Purism SPC
> > + */
> > +
> > +#include <asm/unaligned.h>
> 
> Is this asm header required?

I dropped it after removing get_unaligned_le32.

> 
> > +/*
> > + * DSI Video mode
> > + */
> 
> Single line comment would suffice.
> 
> > +#define VIDEO_MODE_BURST_MODE_WITH_SYNC_PULSES         0
> > +#define VIDEO_MODE_NON_BURST_MODE_WITH_SYNC_EVENTS     BIT(0)
> > +#define VIDEO_MODE_BURST_MODE                          BIT(1)
> > +
> > +/*
> > + * DPI color coding
> > + */
> 
> Ditto.
> 
> > +#define DPI_16_BIT_565_PACKED  0
> > +#define DPI_16_BIT_565_ALIGNED 1
> > +#define DPI_16_BIT_565_SHIFTED 2
> > +#define DPI_18_BIT_PACKED      3
> > +#define DPI_18_BIT_ALIGNED     4
> > +#define DPI_24_BIT             5
> > +
> > +/*
> > + * DPI Pixel format
> > + */
> 
> Ditto.

all fixed

> 
> > +#define PIXEL_FORMAT_16  0
> > +#define PIXEL_FORMAT_18  BIT(0)
> > +#define PIXEL_FORMAT_18L BIT(1)
> > +#define PIXEL_FORMAT_24  (BIT(0) | BIT(1))
> > +
> > +enum transfer_direction { DSI_PACKET_SEND, DSI_PACKET_RECEIVE };
> > +
> > +struct mipi_dsi_transfer {
> > +       const struct mipi_dsi_msg *msg;
> > +       struct mipi_dsi_packet packet;
> > +       struct completion completed;
> > +
> > +       int status; /* status of transmission */
> > +       enum transfer_direction direction;
> > +       bool need_bta;
> > +       u8 cmd;
> > +       u16 rx_word_count;
> > +       size_t tx_len; /* bytes sent */
> > +       size_t rx_len; /* bytes received */
> > +};
> 
> The comments here are kind of obvious, so I would just remove them.

I wanted to have the unit here so i changed to /* in bytes */

> 
> > +static inline int nwl_dsi_write(struct imx_nwl_dsi *dsi, unsigned int reg,
> 
> inline can be dropped.

done.
> 
> > +                               u32 val)
> > +{
> > +       int ret;
> > +
> > +       ret = regmap_write(dsi->regmap, reg, val);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dsi->dev,
> > +                             "Failed to write NWL DSI reg 0x%x: %d\n", reg,
> > +                             ret);
> > +       return ret;
> > +}
> > +
> > +static inline u32 nwl_dsi_read(struct imx_nwl_dsi *dsi, u32 reg)
> 
> Same here.

done.

> > +{
> > +       unsigned int val;
> > +       int ret;
> > +
> > +       ret = regmap_read(dsi->regmap, reg, &val);
> > +       if (ret < 0)
> > +               DRM_DEV_ERROR(dsi->dev, "Failed to read NWL DSI reg 0x%x: %d\n",
> > +                             reg, ret);
> > +
> > +       return val;
> > +}
> 
> It seems that we could simply use regmap_read/write() directly instead
> of these functions.

I've checked some other drm drivers most of them seem to
regmap_{read,write} without looking at errors. While we can't do
anything sensible when writing fails it's seems at least useful to print
an error. I've seen these happening and the messages were very useful
for debugging so if possible i'd keep them.

> > +int nwl_dsi_get_dphy_params(struct imx_nwl_dsi *dsi,
> > +                           const struct drm_display_mode *mode,
> > +                           union phy_configure_opts *phy_opts)
> > +{
> > +       unsigned long rate;
> > +
> > +       if (dsi->lanes < 1 || dsi->lanes > 4)
> > +               return -EINVAL;
> > +
> > +       /*
> > +        * So far the DPHY spec minimal timings work for both mixel
> > +        * dphy and nwl dsi host
> > +        */
> > +       phy_mipi_dphy_get_default_config(
> > +               mode->crtc_clock * 1000,
> > +               mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes,
> > +               &phy_opts->mipi_dphy);
> > +       rate = clk_get_rate(dsi->tx_esc_clk);
> > +       DRM_DEV_DEBUG_DRIVER(dsi->dev, "LP clk is @%lu Hz\n", rate);
> > +       phy_opts->mipi_dphy.lp_clk_rate = rate;
> > +
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_get_dphy_params);
> 
> Does it really need to be exported? Why can't it be placed inside
> nwl-drv.c and be made static?

Moved.

> 
> > +/**
> 
> /* is enough

Fixed.

> 
> 
> > + * ui2bc - UI time periods to byte clock cycles
> > + */
> > +static u32 ui2bc(struct imx_nwl_dsi *dsi, unsigned long long ui)
> > +{
> > +       int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
> > +
> > +       return DIV_ROUND_UP(ui * dsi->lanes, dsi->vm.pixelclock * bpp);
> > +}
> > +
> > +#define USEC_PER_SEC 1000000L
> 
> This definition already exists in include/linux/time64.h. No need to
> redefine it.

Dropped that define.

> 
> > +static int nwl_dsi_enable_tx_clock(struct imx_nwl_dsi *dsi)
> > +{
> > +       struct device *dev = dsi->dev;
> > +       int ret;
> > +
> > +       ret = clk_prepare_enable(dsi->tx_esc_clk);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to enable tx_esc clk: %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "Enabled tx_esc clk @%lu Hz\n",
> > +                            clk_get_rate(dsi->tx_esc_clk));
> > +       return 0;
> > +}
> 
> Do we really need this function? It looks like it would be simpler
> just to call clk_prepare_enable() directly.

Dropped since it's only used once, there were more users before.

> 
> > +
> > +static int nwl_dsi_enable_rx_clock(struct imx_nwl_dsi *dsi)
> > +{
> > +       struct device *dev = dsi->dev;
> > +       int ret;
> > +
> > +       ret = clk_prepare_enable(dsi->rx_esc_clk);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to enable rx_esc clk: %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "Enabled rx_esc clk @%lu Hz\n",
> > +                            clk_get_rate(dsi->rx_esc_clk));
> > +       return 0;
> > +}
> 
> Same here.

Dropped since it's only used once.

> > +static ssize_t nwl_dsi_host_transfer(struct mipi_dsi_host *dsi_host,
> > +                                    const struct mipi_dsi_msg *msg)
> > +{
> > +       struct imx_nwl_dsi *dsi =
> > +               container_of(dsi_host, struct imx_nwl_dsi, dsi_host);
> > +       struct mipi_dsi_transfer xfer;
> > +       ssize_t ret = 0;
> > +
> > +       /* Create packet to be sent */
> > +       dsi->xfer = &xfer;
> > +       ret = mipi_dsi_create_packet(&xfer.packet, msg);
> > +       if (ret < 0) {
> > +               dsi->xfer = NULL;
> > +               return ret;
> > +       }
> > +
> > +       if ((msg->type & MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM ||
> > +            msg->type & MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM ||
> > +            msg->type & MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM ||
> > +            msg->type & MIPI_DSI_DCS_READ) &&
> > +           msg->rx_len > 0 && msg->rx_buf != NULL)
> > +               xfer.direction = DSI_PACKET_RECEIVE;
> > +       else
> > +               xfer.direction = DSI_PACKET_SEND;
> > +
> > +       xfer.need_bta = (xfer.direction == DSI_PACKET_RECEIVE);
> > +       xfer.need_bta |= (msg->flags & MIPI_DSI_MSG_REQ_ACK) ? 1 : 0;
> > +       xfer.msg = msg;
> > +       xfer.status = -ETIMEDOUT;
> > +       xfer.rx_word_count = 0;
> > +       xfer.rx_len = 0;
> > +       xfer.cmd = 0x00;
> > +       if (msg->tx_len > 0)
> > +               xfer.cmd = ((u8 *)(msg->tx_buf))[0];
> > +       init_completion(&xfer.completed);
> > +
> > +       nwl_dsi_enable_rx_clock(dsi);
> 
> This may fail, so better check the error.
> 
> ret = clk_prepare_enable()
> if (ret < 0)
>    return ret;

Done.

> > +irqreturn_t nwl_dsi_irq_handler(int irq, void *data)
> > +{
> > +       u32 irq_status;
> > +       struct imx_nwl_dsi *dsi = data;
> > +
> > +       irq_status = nwl_dsi_read(dsi, IRQ_STATUS);
> > +
> > +       if (irq_status & TX_PKT_DONE || irq_status & RX_PKT_HDR_RCVD ||
> > +           irq_status & RX_PKT_PAYLOAD_DATA_RCVD)
> > +               nwl_dsi_finish_transmission(dsi, irq_status);
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_irq_handler);
> 
> What about placing this function inside nwl-drv.c and make it static?

Then nwl_dsi_finish_transmission would need to either be moved as well
or we'd have another non-static function. I'd like to keeping the irq
handling in one file and only have the registration over in imx-nwl-drv.
I've dropped the EXPORT_SYMBOL_GPL though.

> > +
> > +int nwl_dsi_enable(struct imx_nwl_dsi *dsi)
> > +{
> > +       struct device *dev = dsi->dev;
> > +       union phy_configure_opts *phy_cfg = &dsi->phy_cfg;
> > +       int ret;
> > +
> > +       if (!dsi->lanes) {
> > +               DRM_DEV_ERROR(dev, "Need DSI lanes: %d\n", dsi->lanes);
> > +               return -EINVAL;
> > +       }
> > +
> > +       ret = phy_init(dsi->phy);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to init DSI phy: %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret = phy_configure(dsi->phy, phy_cfg);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to configure DSI phy: %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret = nwl_dsi_enable_tx_clock(dsi);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to enable tx clock: %d\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret = nwl_dsi_config_host(dsi);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to set up DSI: %d", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret = nwl_dsi_config_dpi(dsi);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to set up DPI: %d", ret);
> > +               return ret;
> > +       }
> > +
> > +       ret = phy_power_on(dsi->phy);
> > +       if (ret < 0) {
> > +               DRM_DEV_ERROR(dev, "Failed to power on DPHY (%d)\n", ret);
> > +               return ret;
> > +       }
> > +
> > +       nwl_dsi_init_interrupts(dsi);
> > +
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_enable);
> 
> Same here.

The idea was to keep the dsi related operations here. Dropped
EXPORT_SYMBOL_GPL though.

> 
> > +
> > +int nwl_dsi_disable(struct imx_nwl_dsi *dsi)
> > +{
> > +       struct device *dev = dsi->dev;
> > +
> > +       DRM_DEV_DEBUG_DRIVER(dev, "Disabling clocks and phy\n");
> > +
> > +       phy_power_off(dsi->phy);
> > +       phy_exit(dsi->phy);
> > +
> > +       /* Disabling the clock before the phy breaks enabling dsi again */
> > +       clk_disable_unprepare(dsi->tx_esc_clk);
> > +
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(nwl_dsi_disable);
> 
> Same here.

Same as above. I can move things if wanted but then it might make sense
to only use one large file which I avoided so we can have a split
between DSI operations and probing / bridge chaining and platform
specific functions.

Thanks again for having a look,
 -- Guido

^ permalink raw reply

* Re: [PATCH 2/3] dt-bindings: display/bridge: Add binding for IMX NWL mipi dsi host controller
From: Guido Günther @ 2019-07-31 14:37 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: David Airlie, Daniel Vetter, Rob Herring, Mark Rutland, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Andrzej Hajda, Neil Armstrong, Jonas Karlman,
	Jernej Skrabec, Lee Jones, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, Robert Chiras
In-Reply-To: <20190727015716.GA4902@pendragon.ideasonboard.com>

Hi Laurent,

thanks for having a look.

On Sat, Jul 27, 2019 at 04:57:16AM +0300, Laurent Pinchart wrote:
> Hi Guido,
> 
> Thank you for the patch.
> 
> On Wed, Jul 24, 2019 at 05:52:25PM +0200, Guido Günther wrote:
> > The Northwest Logic MIPI DSI IP core can be found in NXPs i.MX8 SoCs.
> > 
> > Signed-off-by: Guido Günther <agx@sigxcpu.org>
> > ---
> >  .../bindings/display/bridge/imx-nwl-dsi.txt   | 89 +++++++++++++++++++
> >  1 file changed, 89 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/bridge/imx-nwl-dsi.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/display/bridge/imx-nwl-dsi.txt b/Documentation/devicetree/bindings/display/bridge/imx-nwl-dsi.txt
> > new file mode 100644
> > index 000000000000..288fdb726d5a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/imx-nwl-dsi.txt
> > @@ -0,0 +1,89 @@
> > +Northwest Logic MIPI-DSI on imx SoCs
> > +=====================================
> 
> There's one too many =.
> 
> > +
> > +NWL MIPI-DSI host controller found on i.MX8 platforms. This is a
> > +dsi bridge for the for the NWL MIPI-DSI host.
> 
> s/dsi/DSI/
> s/for the for the /for the /
> 
> > +
> > +Required properties:
> > +- compatible: 		"fsl,<chip>-nwl-dsi"
> > +	The following strings are expected:
> > +			"fsl,imx8mq-nwl-dsi"
> > +- reg: 			the register range of the MIPI-DSI controller
> > +- interrupts: 		the interrupt number for this module
> 
> It's not just a number but a specifier (with flags).
> 
> > +- clock, clock-names: 	phandles to the MIPI-DSI clocks
> 
> That should be phandles and names.
> 
> > +	The following clocks are expected on all platforms:
> 
> Expected or required ?
> 
> s/ on all platforms// as you only support a single platform.
> 
> > +		"core"    - DSI core clock
> > +		"tx_esc"  - TX_ESC clock (used in escape mode)
> > +		"rx_esc"  - RX_ESC clock (used in escape mode)
> > +		"phy_ref" - PHY_REF clock. Clock is managed by the phy. Only
> > +                            used to read the clock rate.
> > +- assigned-clocks:	phandles to clocks that require initial configuration
> > +- assigned-clock-rates:	rates of the clocks that require initial configuration
> > +	The following clocks need to have an initial configuration:
> > +	"tx_esc" (20 MHz) and "rx_esc" (80 Mhz).
> 
> I think those two properties are out of scope for these bindings.
> 
> > +- phys: 		phandle to the phy module representing the DPHY
> > +			inside the MIPI-DSI IP block
> > +- phy-names: 		should be "dphy"
> > +
> > +Optional properties:
> > +- power-domains 	phandle to the power domain
> > +- src			phandle to the system reset controller (required on
> > +			i.MX8MQ)
> 
> Should this use the standard resets property ?
> 
> > +- mux-sel		phandle to the MUX register set (required on i.MX8MQ)
> > +- assigned-clock-parents phandles to parent clocks that needs to be assigned as
> > +			parents to clocks defined in assigned-clocks
> 
> This property is also out of scope.
> 
> > +
> > +Example:
> > +	mipi_dsi: mipi_dsi@30a00000 {
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +		compatible = "fsl,imx8mq-nwl-dsi";
> > +		reg = <0x30A00000 0x300>;
> > +		clocks = <&clk IMX8MQ_CLK_DSI_CORE>,
> > +			 <&clk IMX8MQ_CLK_DSI_AHB>,
> > +			 <&clk IMX8MQ_CLK_DSI_IPG_DIV>,
> > +			 <&clk IMX8MQ_CLK_DSI_PHY_REF>;
> > +		clock-names = "core", "rx_esc", "tx_esc", "phy_ref";
> > +		assigned-clocks = <&clk IMX8MQ_CLK_DSI_AHB>,
> > +				  <&clk IMX8MQ_CLK_DSI_CORE>,
> > +				  <&clk IMX8MQ_CLK_DSI_IPG_DIV>;
> > +		assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>,
> > +					 <&clk IMX8MQ_SYS1_PLL_266M>;
> > +		assigned-clock-rates = <80000000>,
> > +				       <266000000>,
> > +				       <20000000>;
> > +		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
> > +		power-domains = <&pgc_mipi>;
> > +		src = <&src>;
> > +		mux-sel = <&iomuxc_gpr>;
> > +		phys = <&dphy>;
> > +		phy-names = "dphy";
> > +		status = "okay";
> > +
> > +		panel@0 {
> > +			compatible = "...";
> > +			port {
> > +			     panel_in: endpoint {
> > +				       remote-endpoint = <&mipi_dsi_out>;
> > +			     };
> > +			};
> > +		};
> > +
> > +		ports {
> > +		      #address-cells = <1>;
> > +		      #size-cells = <0>;
> > +
> > +		      port@0 {
> > +			     reg = <0>;
> > +			     mipi_dsi_in: endpoint {
> > +					  remote-endpoint = <&dcss_disp0_mipi_dsi>;
> > +			     };
> > +		      };
> > +		      port@1 {
> > +			     reg = <1>;
> > +			     mipi_dsi_out: endpoint {
> > +					   remote-endpoint = <&panel_in>;
> > +			     };
> > +		      };
> > +		};
> 
> The ports should be documented too. There are multiple example bindings
> available.

I've followed you suggestions while moving the whole thing to YAML
syntax for an upcoming v2.

Thanks for having a look,
Cheers,
 -- Guido

> > +	};
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox