layerscape: remove useless pairs of kernel patches
authorAdrian Schmutzler <freifunk@adrianschmutzler.de>
Wed, 19 Aug 2020 13:41:30 +0000 (15:41 +0200)
committerAdrian Schmutzler <freifunk@adrianschmutzler.de>
Thu, 20 Aug 2020 12:19:39 +0000 (14:19 +0200)
The layerscape kernel patches appears to be just some uncleaned local
development tree, where patches are sometimes directly followed by
their revert. While this does not seem a problem in the first place,
it becomes incredibly unpleasant when the upstream kernel changes in
the relevant areas and requires rebase.

This removes all these patch-revert pairs and refreshs the rest.

It removes about 44000 lines of entirely useless code.

Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
47 files changed:
target/linux/layerscape/patches-5.4/302-dts-0085-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interrupt.patch [deleted file]
target/linux/layerscape/patches-5.4/302-dts-0092-arm64-dts-ls1028a-Add-DP-DT-nodes.patch
target/linux/layerscape/patches-5.4/302-dts-0108-Revert-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interr.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0275-mii-Add-helpers-for-parsing-SGMII-auto-negotiation.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0276-net-phylink-make-QSGMII-a-valid-PHY-mode-for-in-band.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0277-net-phylink-call-mac_an_restart-for-SGMII-QSGMII-inb.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0278-enetc-export-enetc_mdio-definitionns-to-include-linu.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0279-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-value-of-.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0280-net-mscc-ocelot-do-not-force-Felix-MACs-at-lower-spe.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0281-net-mscc-ocelot-convert-to-PHYLINK.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0282-net-mscc-ocelot-introduce-more-focused-PCS-ops-for-P.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0283-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0338-net-dsa-felix-Fix-probing-allocation-and-cleanup-pat.patch
target/linux/layerscape/patches-5.4/701-net-0341-LF-368-net-mscc-ocelot-add-VCAP-IS2-rule-to-trap-PTP.patch
target/linux/layerscape/patches-5.4/701-net-0367-net-mscc-ocelot-Workaround-to-allow-traffic-to-CPU-i.patch
target/linux/layerscape/patches-5.4/701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0369-Revert-net-mscc-ocelot-introduce-more-focused-PCS-op.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0370-Revert-net-mscc-ocelot-convert-to-PHYLINK.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0371-Revert-net-mscc-ocelot-do-not-force-Felix-MACs-at-lo.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0372-Revert-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-va.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0373-Revert-enetc-export-enetc_mdio-definitionns-to-inclu.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0374-Revert-net-phylink-call-mac_an_restart-for-SGMII-QSG.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0375-Revert-net-phylink-make-QSGMII-a-valid-PHY-mode-for-.patch [deleted file]
target/linux/layerscape/patches-5.4/701-net-0376-Revert-mii-Add-helpers-for-parsing-SGMII-auto-negoti.patch [deleted file]
target/linux/layerscape/patches-5.4/801-audio-0023-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-part-2.patch [deleted file]
target/linux/layerscape/patches-5.4/801-audio-0027-MLK-15140-1-ASoC-fsl_sai-support-latest-sai-module.patch
target/linux/layerscape/patches-5.4/801-audio-0030-MLK-15960-2-ASoC-fsl_sai-refine-the-pm-runtime-funct.patch
target/linux/layerscape/patches-5.4/801-audio-0036-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_data-pa.patch [deleted file]
target/linux/layerscape/patches-5.4/801-audio-0037-MLK-16224-4-ASoC-fsl_sai-support-multi-fifo-and-DSD.patch
target/linux/layerscape/patches-5.4/801-audio-0048-MLK-17580-ASoC-fsl-sai-Use-DSD-helper.patch
target/linux/layerscape/patches-5.4/801-audio-0049-MLK-17580-ASoC-fsl-sai-check-for-pinctrl-status.patch
target/linux/layerscape/patches-5.4/801-audio-0062-ASoC-fsl-sai-fix-build-failture-due-to-5.1-RC7-upgra.patch
target/linux/layerscape/patches-5.4/801-audio-0064-ASoC-fsl_sai-Mark-cache-dirty-at-resume.patch
target/linux/layerscape/patches-5.4/801-audio-0065-LF-106-ASoC-fsl_sai-request-BUS_FREQ_AUDIO.patch
target/linux/layerscape/patches-5.4/801-audio-0067-Revert-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_.patch [deleted file]
target/linux/layerscape/patches-5.4/801-audio-0068-Revert-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-p.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0030-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sinks.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0031-Revert-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sink.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0042-drm-imx-Revert-a-patch-which-merges-imx-drm-core-and.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0043-gpu-Move-ipu-v3-to-imx-folder.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0044-drm-imx-Extract-IPUv3-specific-KMS-functions-to-ipuv.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0045-drm-imx-Add-DPU-KMS-support-part-2.patch
target/linux/layerscape/patches-5.4/805-display-0046-MLK-22171-drm-imx-Avoid-leaking-dangling-pointer-dev.patch
target/linux/layerscape/patches-5.4/805-display-0047-MLK-18535-6-drm-imx-core-add-LCDIF-support.patch
target/linux/layerscape/patches-5.4/805-display-0048-Revert-drm-imx-Extract-IPUv3-specific-KMS-functions-.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0049-Revert-gpu-Move-ipu-v3-to-imx-folder.patch [deleted file]
target/linux/layerscape/patches-5.4/805-display-0050-Revert-drm-imx-Revert-a-patch-which-merges-imx-drm-c.patch [deleted file]

diff --git a/target/linux/layerscape/patches-5.4/302-dts-0085-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interrupt.patch b/target/linux/layerscape/patches-5.4/302-dts-0085-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interrupt.patch
deleted file mode 100644 (file)
index 17286a8..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 3dc3a4c6ac9e8a0940a9974b8fe2da7641bfa3dd Mon Sep 17 00:00:00 2001
-From: Alex Marginean <alexandru.marginean@nxp.com>
-Date: Thu, 22 Aug 2019 12:47:12 +0300
-Subject: [PATCH] arm64: dts: LS1028a-rdb: use Ethernet PHY interrupt
-
-Use the PHY interrupt wired to GPIO pins as part of MDIO WA performance
-impact mitigation.
-
-Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
----
- arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
-+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
-@@ -202,6 +202,8 @@
-               #size-cells = <0>;
-               sgmii_phy0: ethernet-phy@2 {
-                       reg = <0x2>;
-+                      interrupt-parent = <&gpio1>;
-+                      interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-               };
-       };
- };
-@@ -213,18 +215,26 @@
- &enetc_mdio_pf3 {
-       qsgmii_phy1: ethernet-phy@4 {
-               reg = <0x10>;
-+              interrupt-parent = <&gpio1>;
-+              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy2: ethernet-phy@5 {
-               reg = <0x11>;
-+              interrupt-parent = <&gpio1>;
-+              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy3: ethernet-phy@6 {
-               reg = <0x12>;
-+              interrupt-parent = <&gpio1>;
-+              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy4: ethernet-phy@7 {
-               reg = <0x13>;
-+              interrupt-parent = <&gpio1>;
-+              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
- };
index a6d2253c737f5042eda2ae39938c80470d1b893a..a0fd27e350f1d923b9956675222973a3a57ab6ef 100644 (file)
@@ -32,7 +32,7 @@ Signed-off-by: Wen He <wen.he_1@nxp.com>
  
 --- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
 +++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
-@@ -272,13 +272,6 @@
+@@ -262,13 +262,6 @@
  };
  
  &hdptx0 {
diff --git a/target/linux/layerscape/patches-5.4/302-dts-0108-Revert-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interr.patch b/target/linux/layerscape/patches-5.4/302-dts-0108-Revert-arm64-dts-LS1028a-rdb-use-Ethernet-PHY-interr.patch
deleted file mode 100644 (file)
index efb5cb6..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From c57a0efc17627d0077408544ded02674aefdecae Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 16:59:02 +0200
-Subject: [PATCH] Revert "arm64: dts: LS1028a-rdb: use Ethernet PHY interrupt"
-
-This reverts commit 841edb98671cfc4d6f010393ac429c78082ec4bd.
-
-There are 2 separate issues with interrupts on the LS1028A-RDB board:
-
-1. The GPIO1_DAT25 interrupt line is shared, so there is a real risk of
-   race conditions if used in edge-triggered mode, as we currently do.
-   This can be illustrated in the following setup:
-   - Take 2 LS1028A-RDB boards
-   - Connect swp0 to swp0, swp1 to swp1, swp2 to swp2
-   - Plug/unplug the power to board 2, 10 times in a row. This will make
-     the PHYs lose link simultaneously.
-   - Notice that at one point, the net devices on board 1 remain in a
-     state where not all the links are down (visible in "ip link"):
-
-     5: swp0: <BROADCAST,MULTICAST,UP> mtu 1468 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 1000
-         link/ether be:97:36:d3:3d:70 brd ff:ff:ff:ff:ff:ff
-     6: swp1: <BROADCAST,MULTICAST,UP> mtu 1468 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 1000
-         link/ether be:97:36:d3:3d:71 brd ff:ff:ff:ff:ff:ff
-     7: swp2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1468 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 1000
-         link/ether be:97:36:d3:3d:72 brd ff:ff:ff:ff:ff:ff
-
-   This cannot be solved by making the interrupts level-triggered,
-   because the gpio-mpc8xxx controller only supports generating
-   edge-triggered interrupts. So the effective reality is that we
-   cannot not use shared interrupts connected to the gpio1
-   interrupt-parent.
-
-2. The uBUS1 and uBUS2 slots that share this interrupt line with the
-   Ethernet PHYs are not pulled up by default, they are left floating on
-   current revisions of the LS1028A-RDB boards. So sufficient electrical
-   noise on these lines will make the CPLD think there's an interrupt
-   request, so it asserts the GPIO1_DAT25 signal and leaves it asserted.
-   This means that the PHYs on those boards will never have link when
-   used in interrupt mode, because their IRQ will be masked by the uBUS
-   line that is erroneously kept asserted. In poll mode this issue does
-   not occur.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts | 10 ----------
- 1 file changed, 10 deletions(-)
-
---- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
-+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
-@@ -206,8 +206,6 @@
-               #size-cells = <0>;
-               sgmii_phy0: ethernet-phy@2 {
-                       reg = <0x2>;
--                      interrupt-parent = <&gpio1>;
--                      interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-               };
-       };
- };
-@@ -219,26 +217,18 @@
- &enetc_mdio_pf3 {
-       qsgmii_phy1: ethernet-phy@4 {
-               reg = <0x10>;
--              interrupt-parent = <&gpio1>;
--              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy2: ethernet-phy@5 {
-               reg = <0x11>;
--              interrupt-parent = <&gpio1>;
--              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy3: ethernet-phy@6 {
-               reg = <0x12>;
--              interrupt-parent = <&gpio1>;
--              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
-       qsgmii_phy4: ethernet-phy@7 {
-               reg = <0x13>;
--              interrupt-parent = <&gpio1>;
--              interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
-       };
- };
diff --git a/target/linux/layerscape/patches-5.4/701-net-0275-mii-Add-helpers-for-parsing-SGMII-auto-negotiation.patch b/target/linux/layerscape/patches-5.4/701-net-0275-mii-Add-helpers-for-parsing-SGMII-auto-negotiation.patch
deleted file mode 100644 (file)
index c783143..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-From bc447c21304c1297f340d3daaf69915ebbc1f882 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 30 Sep 2019 19:20:26 +0300
-Subject: [PATCH] mii: Add helpers for parsing SGMII auto-negotiation
-
-Typically a MAC PCS auto-configures itself after it receives the
-negotiated link settings from the PHY, but some MAC devices are more
-special and need manual manipulation of the SGMII AN result.
-
-Therefore, add the bit definitions for the SGMII registers 4 and 5
-(local device ability, link partner ability), as well as a link_mode
-conversion helper that can be used to feed the AN results into
-phy_resolve_aneg_linkmode.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- include/linux/mii.h      | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
- include/uapi/linux/mii.h | 10 ++++++++++
- 2 files changed, 60 insertions(+)
-
---- a/include/linux/mii.h
-+++ b/include/linux/mii.h
-@@ -373,6 +373,56 @@ static inline u32 mii_lpa_to_ethtool_lpa
- }
- /**
-+ * mii_lpa_mod_linkmode_adv_sgmii
-+ * @lp_advertising: pointer to destination link mode.
-+ * @lpa: value of the MII_LPA register
-+ *
-+ * A small helper function that translates MII_LPA bits to
-+ * linkmode advertisement settings for SGMII.
-+ * Leaves other bits unchanged.
-+ */
-+static inline void
-+mii_lpa_mod_linkmode_lpa_sgmii(unsigned long *lp_advertising, u32 lpa)
-+{
-+      u32 speed_duplex = lpa & LPA_SGMII_DPX_SPD_MASK;
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_1000HALF);
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_1000FULL);
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_100HALF);
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_100FULL);
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_10HALF);
-+
-+      linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, lp_advertising,
-+                       speed_duplex == LPA_SGMII_10FULL);
-+}
-+
-+/**
-+ * mii_lpa_to_linkmode_adv_sgmii
-+ * @advertising: pointer to destination link mode.
-+ * @lpa: value of the MII_LPA register
-+ *
-+ * A small helper function that translates MII_ADVERTISE bits
-+ * to linkmode advertisement settings when in SGMII mode.
-+ * Clears the old value of advertising.
-+ */
-+static inline void mii_lpa_to_linkmode_lpa_sgmii(unsigned long *lp_advertising,
-+                                               u32 lpa)
-+{
-+      linkmode_zero(lp_advertising);
-+
-+      mii_lpa_mod_linkmode_lpa_sgmii(lp_advertising, lpa);
-+}
-+
-+/**
-  * mii_adv_mod_linkmode_adv_t
-  * @advertising:pointer to destination link mode.
-  * @adv: value of the MII_ADVERTISE register
---- a/include/uapi/linux/mii.h
-+++ b/include/uapi/linux/mii.h
-@@ -71,6 +71,7 @@
- /* Advertisement control register. */
- #define ADVERTISE_SLCT                0x001f  /* Selector bits               */
- #define ADVERTISE_CSMA                0x0001  /* Only selector supported     */
-+#define ADVERTISE_SGMII               0x0001  /* Can do SGMII                */
- #define ADVERTISE_10HALF      0x0020  /* Try for 10mbps half-duplex  */
- #define ADVERTISE_1000XFULL   0x0020  /* Try for 1000BASE-X full-duplex */
- #define ADVERTISE_10FULL      0x0040  /* Try for 10mbps full-duplex  */
-@@ -94,6 +95,7 @@
- /* Link partner ability register. */
- #define LPA_SLCT              0x001f  /* Same as advertise selector  */
-+#define LPA_SGMII             0x0001  /* Can do SGMII                */
- #define LPA_10HALF            0x0020  /* Can do 10mbps half-duplex   */
- #define LPA_1000XFULL         0x0020  /* Can do 1000BASE-X full-duplex */
- #define LPA_10FULL            0x0040  /* Can do 10mbps full-duplex   */
-@@ -104,11 +106,19 @@
- #define LPA_1000XPAUSE_ASYM   0x0100  /* Can do 1000BASE-X pause asym*/
- #define LPA_100BASE4          0x0200  /* Can do 100mbps 4k packets   */
- #define LPA_PAUSE_CAP         0x0400  /* Can pause                   */
-+#define LPA_SGMII_DPX_SPD_MASK        0x1C00  /* SGMII duplex and speed bits */
-+#define LPA_SGMII_10HALF      0x0000  /* Can do SGMII 10mbps half-duplex */
-+#define LPA_SGMII_10FULL      0x1000  /* Can do SGMII 10mbps full-duplex */
-+#define LPA_SGMII_100HALF     0x0400  /* Can do SGMII 100mbps half-duplex */
-+#define LPA_SGMII_100FULL     0x1400  /* Can do SGMII 100mbps full-duplex */
- #define LPA_PAUSE_ASYM                0x0800  /* Can pause asymetrically     */
-+#define LPA_SGMII_1000HALF    0x0800  /* Can do SGMII 1000mbps half-duplex */
-+#define LPA_SGMII_1000FULL    0x1800  /* Can do SGMII 1000mbps full-duplex */
- #define LPA_RESV              0x1000  /* Unused...                   */
- #define LPA_RFAULT            0x2000  /* Link partner faulted        */
- #define LPA_LPACK             0x4000  /* Link partner acked us       */
- #define LPA_NPAGE             0x8000  /* Next page bit               */
-+#define LPA_SGMII_LINK                0x8000  /* Link partner has link       */
- #define LPA_DUPLEX            (LPA_10FULL | LPA_100FULL)
- #define LPA_100                       (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
diff --git a/target/linux/layerscape/patches-5.4/701-net-0276-net-phylink-make-QSGMII-a-valid-PHY-mode-for-in-band.patch b/target/linux/layerscape/patches-5.4/701-net-0276-net-phylink-make-QSGMII-a-valid-PHY-mode-for-in-band.patch
deleted file mode 100644 (file)
index d04ed91..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 4446e9789e662fe53dfcfe34551b5b74a013086c Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 22 Nov 2019 13:46:46 +0200
-Subject: [PATCH] net: phylink: make QSGMII a valid PHY mode for in-band AN
-
-QSGMII is just SGMII clocked at a higher frequency (5 Gbaud vs 1.25
-Gbaud). Logically it is just 4 SGMII interfaces multiplexed onto the
-same physical lanes. Each MAC PCS has its own in-band AN process with
-the system side of the QSGMII PHY, which is identical to the regular
-SGMII AN process. So allow QSGMII as a valid in-band AN mode.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/phy/phylink.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/phy/phylink.c
-+++ b/drivers/net/phy/phylink.c
-@@ -283,6 +283,7 @@ static int phylink_parse_mode(struct phy
-               switch (pl->link_config.interface) {
-               case PHY_INTERFACE_MODE_SGMII:
-+              case PHY_INTERFACE_MODE_QSGMII:
-                       phylink_set(pl->supported, 10baseT_Half);
-                       phylink_set(pl->supported, 10baseT_Full);
-                       phylink_set(pl->supported, 100baseT_Half);
diff --git a/target/linux/layerscape/patches-5.4/701-net-0277-net-phylink-call-mac_an_restart-for-SGMII-QSGMII-inb.patch b/target/linux/layerscape/patches-5.4/701-net-0277-net-phylink-call-mac_an_restart-for-SGMII-QSGMII-inb.patch
deleted file mode 100644 (file)
index 487a520..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From d526228a8159d136c914c8f71d5944cda2f93d9a Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Thu, 28 Nov 2019 03:21:53 +0200
-Subject: [PATCH] net: phylink: call mac_an_restart for SGMII/QSGMII inband
- interfaces too
-
-It doesn't quite make sense why restarting the AN process should be
-unique to 802.3z (1000Base-X) modes. It is valid to put an SGMII PCS in
-in-band AN mode, therefore also make PHYLINK re-trigger an
-auto-negotiation if needed.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/phy/phylink.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/net/phy/phylink.c
-+++ b/drivers/net/phy/phylink.c
-@@ -360,7 +360,9 @@ static void phylink_mac_config_up(struct
- static void phylink_mac_an_restart(struct phylink *pl)
- {
-       if (pl->link_config.an_enabled &&
--          phy_interface_mode_is_8023z(pl->link_config.interface))
-+          (phy_interface_mode_is_8023z(pl->link_config.interface) ||
-+           pl->link_config.interface == PHY_INTERFACE_MODE_SGMII ||
-+           pl->link_config.interface == PHY_INTERFACE_MODE_QSGMII))
-               pl->ops->mac_an_restart(pl->config);
- }
diff --git a/target/linux/layerscape/patches-5.4/701-net-0278-enetc-export-enetc_mdio-definitionns-to-include-linu.patch b/target/linux/layerscape/patches-5.4/701-net-0278-enetc-export-enetc_mdio-definitionns-to-include-linu.patch
deleted file mode 100644 (file)
index b558a78..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-From 210fde07cd9e3f2dc826f538ccec4e90b54eb7e5 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 22 Nov 2019 17:47:56 +0200
-Subject: [PATCH] enetc: export enetc_mdio definitionns to include/linux/fsl
-
-The Felix DSA switch has an internal MDIO bus that has the same register
-map as the ENETC one, so the accessors can be reused.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/freescale/enetc/enetc_mdio.c  | 18 +++++++++-
- drivers/net/ethernet/freescale/enetc/enetc_mdio.h  | 12 -------
- .../net/ethernet/freescale/enetc/enetc_pci_mdio.c  | 41 +++++++++++++---------
- include/linux/fsl/enetc_mdio.h                     | 21 +++++++++++
- 4 files changed, 62 insertions(+), 30 deletions(-)
- delete mode 100644 drivers/net/ethernet/freescale/enetc/enetc_mdio.h
- create mode 100644 include/linux/fsl/enetc_mdio.h
-
---- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-@@ -1,13 +1,13 @@
- // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
- /* Copyright 2019 NXP */
-+#include <linux/fsl/enetc_mdio.h>
- #include <linux/mdio.h>
- #include <linux/of_mdio.h>
- #include <linux/iopoll.h>
- #include <linux/of.h>
- #include "enetc_pf.h"
--#include "enetc_mdio.h"
- #define       ENETC_MDIO_CFG  0x0     /* MDIO configuration and status */
- #define       ENETC_MDIO_CTL  0x4     /* MDIO control */
-@@ -99,6 +99,7 @@ int enetc_mdio_write(struct mii_bus *bus
-       return 0;
- }
-+EXPORT_SYMBOL_GPL(enetc_mdio_write);
- int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
- {
-@@ -154,6 +155,21 @@ int enetc_mdio_read(struct mii_bus *bus,
-       return value;
- }
-+EXPORT_SYMBOL_GPL(enetc_mdio_read);
-+
-+struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
-+{
-+      struct enetc_hw *hw;
-+
-+      hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
-+      if (!hw)
-+              return ERR_PTR(-ENOMEM);
-+
-+      hw->port = port_regs;
-+
-+      return hw;
-+}
-+EXPORT_SYMBOL_GPL(enetc_hw_alloc);
- int enetc_mdio_probe(struct enetc_pf *pf)
- {
---- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.h
-+++ /dev/null
-@@ -1,12 +0,0 @@
--/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
--/* Copyright 2019 NXP */
--
--#include <linux/phy.h>
--
--struct enetc_mdio_priv {
--      struct enetc_hw *hw;
--      int mdio_base;
--};
--
--int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
--int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
---- a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
-@@ -1,8 +1,8 @@
- // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
- /* Copyright 2019 NXP */
-+#include <linux/fsl/enetc_mdio.h>
- #include <linux/of_mdio.h>
- #include "enetc_pf.h"
--#include "enetc_mdio.h"
- #define ENETC_MDIO_DEV_ID     0xee01
- #define ENETC_MDIO_DEV_NAME   "FSL PCIe IE Central MDIO"
-@@ -14,17 +14,29 @@ static int enetc_pci_mdio_probe(struct p
- {
-       struct enetc_mdio_priv *mdio_priv;
-       struct device *dev = &pdev->dev;
-+      void __iomem *port_regs;
-       struct enetc_hw *hw;
-       struct mii_bus *bus;
-       int err;
--      hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
--      if (!hw)
--              return -ENOMEM;
-+      port_regs = pci_iomap(pdev, 0, 0);
-+      if (!port_regs) {
-+              dev_err(dev, "iomap failed\n");
-+              err = -ENXIO;
-+              goto err_ioremap;
-+      }
-+
-+      hw = enetc_hw_alloc(dev, port_regs);
-+      if (IS_ERR(enetc_hw_alloc)) {
-+              err = PTR_ERR(hw);
-+              goto err_hw_alloc;
-+      }
-       bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
--      if (!bus)
--              return -ENOMEM;
-+      if (!bus) {
-+              err = -ENOMEM;
-+              goto err_mdiobus_alloc;
-+      }
-       bus->name = ENETC_MDIO_BUS_NAME;
-       bus->read = enetc_mdio_read;
-@@ -39,7 +51,7 @@ static int enetc_pci_mdio_probe(struct p
-       err = pci_enable_device_mem(pdev);
-       if (err) {
-               dev_err(dev, "device enable failed\n");
--              return err;
-+              goto err_pci_enable;
-       }
-       err = pci_request_region(pdev, 0, KBUILD_MODNAME);
-@@ -48,13 +60,6 @@ static int enetc_pci_mdio_probe(struct p
-               goto err_pci_mem_reg;
-       }
--      hw->port = pci_iomap(pdev, 0, 0);
--      if (!hw->port) {
--              err = -ENXIO;
--              dev_err(dev, "iomap failed\n");
--              goto err_ioremap;
--      }
--
-       err = of_mdiobus_register(bus, dev->of_node);
-       if (err)
-               goto err_mdiobus_reg;
-@@ -64,12 +69,14 @@ static int enetc_pci_mdio_probe(struct p
-       return 0;
- err_mdiobus_reg:
--      iounmap(mdio_priv->hw->port);
--err_ioremap:
-       pci_release_mem_regions(pdev);
- err_pci_mem_reg:
-       pci_disable_device(pdev);
--
-+err_pci_enable:
-+err_mdiobus_alloc:
-+      iounmap(port_regs);
-+err_hw_alloc:
-+err_ioremap:
-       return err;
- }
---- /dev/null
-+++ b/include/linux/fsl/enetc_mdio.h
-@@ -0,0 +1,21 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-+/* Copyright 2019 NXP */
-+
-+#include <linux/phy.h>
-+
-+/* PCS registers */
-+#define ENETC_PCS_LINK_TIMER1         0x12
-+#define ENETC_PCS_LINK_TIMER1_VAL     0x06a0
-+#define ENETC_PCS_LINK_TIMER2         0x13
-+#define ENETC_PCS_LINK_TIMER2_VAL     0x0003
-+#define ENETC_PCS_IF_MODE             0x14
-+#define ENETC_PCS_IF_MODE_SGMII_AN    0x0003
-+
-+struct enetc_mdio_priv {
-+      struct enetc_hw *hw;
-+      int mdio_base;
-+};
-+
-+int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
-+int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
-+struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs);
diff --git a/target/linux/layerscape/patches-5.4/701-net-0279-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-value-of-.patch b/target/linux/layerscape/patches-5.4/701-net-0279-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-value-of-.patch
deleted file mode 100644 (file)
index 02ead27..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 5961ca6738507031a64f8580ceb8ab0b630d47a5 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Wed, 27 Nov 2019 19:21:13 +0200
-Subject: [PATCH] enetc: Set MDIO_CFG_HOLD to the recommended value of 2
-
-This increases the MDIO hold time to 5 enet_clk cycles from the previous
-value of 0. This is actually the out-of-reset value, that the driver was
-previously overwriting with 0. Zero worked for the external MDIO, but
-breaks communication with the internal MDIO buses on which the PCS of
-ENETC SI's and Felix switch are found.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
---- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-@@ -31,15 +31,19 @@ static inline void _enetc_mdio_wr(struct
-       _enetc_mdio_wr(mdio_priv, ENETC_##off, val)
- #define enetc_mdio_rd_reg(off)        enetc_mdio_rd(mdio_priv, off)
--#define ENETC_MDC_DIV         258
--
- #define MDIO_CFG_CLKDIV(x)    ((((x) >> 1) & 0xff) << 8)
- #define MDIO_CFG_BSY          BIT(0)
- #define MDIO_CFG_RD_ER                BIT(1)
-+#define MDIO_CFG_HOLD(x)      (((x) << 2) & GENMASK(4, 2))
- #define MDIO_CFG_ENC45                BIT(6)
-  /* external MDIO only - driven on neg MDC edge */
- #define MDIO_CFG_NEG          BIT(23)
-+#define ENETC_EMDIO_CFG \
-+      (MDIO_CFG_HOLD(2) | \
-+       MDIO_CFG_CLKDIV(258) | \
-+       MDIO_CFG_NEG)
-+
- #define MDIO_CTL_DEV_ADDR(x)  ((x) & 0x1f)
- #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
- #define MDIO_CTL_READ         BIT(15)
-@@ -61,7 +65,7 @@ int enetc_mdio_write(struct mii_bus *bus
-       u16 dev_addr;
-       int ret;
--      mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
-+      mdio_cfg = ENETC_EMDIO_CFG;
-       if (regnum & MII_ADDR_C45) {
-               dev_addr = (regnum >> 16) & 0x1f;
-               mdio_cfg |= MDIO_CFG_ENC45;
-@@ -108,7 +112,7 @@ int enetc_mdio_read(struct mii_bus *bus,
-       u16 dev_addr, value;
-       int ret;
--      mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
-+      mdio_cfg = ENETC_EMDIO_CFG;
-       if (regnum & MII_ADDR_C45) {
-               dev_addr = (regnum >> 16) & 0x1f;
-               mdio_cfg |= MDIO_CFG_ENC45;
diff --git a/target/linux/layerscape/patches-5.4/701-net-0280-net-mscc-ocelot-do-not-force-Felix-MACs-at-lower-spe.patch b/target/linux/layerscape/patches-5.4/701-net-0280-net-mscc-ocelot-do-not-force-Felix-MACs-at-lower-spe.patch
deleted file mode 100644 (file)
index a31321f..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-From 4ba6e00c2f45bf4189ec6a8ef71b45346ae804f2 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Thu, 28 Nov 2019 15:36:10 +0200
-Subject: [PATCH] net: mscc: ocelot: do not force Felix MACs at lower speeds
- than gigabit
-
-In the LS1028A, the VSC9959 switch was integrated with an NXP PCS which
-performs SGMII AN and rate adaptation autonomously. The MAC does not
-need to know about this, and forcing the MAC speed to something else,
-when connected to a 10/100 link partner, actually breaks the GMII
-internal link between the MAC and the PCS.
-
-Add a quirk system in the ocelot driver, and a first quirk called "PCS
-performs rate adaptation", to distinguish the VSC7514 from the VSC9959
-regarding this behavior.
-
-Signed-off-by: Catalin Horghidan <catalin.horghidan@nxp.com>
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c         |  1 +
- drivers/net/dsa/ocelot/felix.h         |  1 +
- drivers/net/dsa/ocelot/felix_vsc9959.c |  1 +
- drivers/net/ethernet/mscc/ocelot.c     | 32 ++++++++++++++++++--------------
- include/soc/mscc/ocelot.h              |  7 +++++++
- 5 files changed, 28 insertions(+), 14 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -249,6 +249,7 @@ static int felix_init_structs(struct fel
-       ocelot->num_stats       = felix->info->num_stats;
-       ocelot->shared_queue_sz = felix->info->shared_queue_sz;
-       ocelot->ops             = felix->info->ops;
-+      ocelot->quirks          = felix->info->quirks;
-       base = pci_resource_start(felix->pdev, felix->info->pci_bar);
---- a/drivers/net/dsa/ocelot/felix.h
-+++ b/drivers/net/dsa/ocelot/felix.h
-@@ -18,6 +18,7 @@ struct felix_info {
-       unsigned int                    num_stats;
-       int                             num_ports;
-       int                             pci_bar;
-+      unsigned long                   quirks;
- };
- extern struct felix_info              felix_info_vsc9959;
---- a/drivers/net/dsa/ocelot/felix_vsc9959.c
-+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
-@@ -584,4 +584,5 @@ struct felix_info felix_info_vsc9959 = {
-       .shared_queue_sz        = 128 * 1024,
-       .num_ports              = 6,
-       .pci_bar                = 4,
-+      .quirks                 = OCELOT_PCS_PERFORMS_RATE_ADAPTATION,
- };
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -409,27 +409,32 @@ static u16 ocelot_wm_enc(u16 value)
- void ocelot_adjust_link(struct ocelot *ocelot, int port,
-                       struct phy_device *phydev)
- {
-+      int speed, mac_speed, mac_mode = DEV_MAC_MODE_CFG_FDX_ENA;
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
--      int speed, mode = 0;
--      switch (phydev->speed) {
-+      if (ocelot->quirks & OCELOT_PCS_PERFORMS_RATE_ADAPTATION)
-+              speed = SPEED_1000;
-+      else
-+              speed = phydev->speed;
-+
-+      switch (speed) {
-       case SPEED_10:
--              speed = OCELOT_SPEED_10;
-+              mac_speed = OCELOT_SPEED_10;
-               break;
-       case SPEED_100:
--              speed = OCELOT_SPEED_100;
-+              mac_speed = OCELOT_SPEED_100;
-               break;
-       case SPEED_1000:
--              speed = OCELOT_SPEED_1000;
--              mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-+              mac_speed = OCELOT_SPEED_1000;
-+              mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       case SPEED_2500:
--              speed = OCELOT_SPEED_2500;
--              mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-+              mac_speed = OCELOT_SPEED_2500;
-+              mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       default:
-               dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
--                      port, phydev->speed);
-+                      port, speed);
-               return;
-       }
-@@ -439,8 +444,7 @@ void ocelot_adjust_link(struct ocelot *o
-               return;
-       /* Only full duplex supported for now */
--      ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
--                         mode, DEV_MAC_MODE_CFG);
-+      ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-       if (ocelot->ops->pcs_init)
-               ocelot->ops->pcs_init(ocelot, port);
-@@ -451,11 +455,11 @@ void ocelot_adjust_link(struct ocelot *o
-       /* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
-        * reset */
--      ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
-+      ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(mac_speed),
-                          DEV_CLOCK_CFG);
-       /* No PFC */
--      ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
-+      ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(mac_speed),
-                        ANA_PFC_PFC_CFG, port);
-       /* Core: Enable port for frame transfer */
-@@ -469,7 +473,7 @@ void ocelot_adjust_link(struct ocelot *o
-                        SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
-                        SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
-                        SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
--                       SYS_MAC_FC_CFG_FC_LINK_SPEED(speed),
-+                       SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed),
-                        SYS_MAC_FC_CFG, port);
-       ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
- }
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -404,6 +404,11 @@ enum ocelot_tag_prefix {
-       OCELOT_TAG_PREFIX_LONG,
- };
-+/* Hardware quirks (differences between switch instantiations) */
-+enum {
-+      OCELOT_PCS_PERFORMS_RATE_ADAPTATION     = BIT(0),
-+};
-+
- struct ocelot;
- struct ocelot_ops {
-@@ -464,6 +469,8 @@ struct ocelot {
-       struct delayed_work             stats_work;
-       struct workqueue_struct         *stats_queue;
-+      unsigned long                   quirks;
-+
-       u8                              ptp:1;
-       struct ptp_clock                *ptp_clock;
-       struct ptp_clock_info           ptp_info;
diff --git a/target/linux/layerscape/patches-5.4/701-net-0281-net-mscc-ocelot-convert-to-PHYLINK.patch b/target/linux/layerscape/patches-5.4/701-net-0281-net-mscc-ocelot-convert-to-PHYLINK.patch
deleted file mode 100644 (file)
index fcf28b8..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-From 0a2b7489bf60d24a54e16147b416f339ebe4f511 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 18 Nov 2019 18:05:01 +0200
-Subject: [PATCH] net: mscc: ocelot: convert to PHYLINK
-
-This patch reworks ocelot_board.c (aka the MIPS on the VSC7514) to
-register a PHYLINK instance for each port. The registration code is
-local to the VSC7514, but the PHYLINK callback implementation is common
-so that the Felix DSA front-end can use it as well (but DSA does its own
-registration).
-
-Now Felix can use native PHYLINK callbacks instead of the PHYLIB
-adaptation layer in DSA, which had issues supporting fixed-link slave
-ports (no struct phy_device to pass to the adjust_link callback), as
-well as fixed-link CPU port at 2.5Gbps.
-
-The old code from ocelot_port_enable and ocelot_port_disable has been
-moved into ocelot_phylink_mac_link_up and ocelot_phylink_mac_link_down.
-
-The PHY connect operation has been moved from ocelot_port_open to
-mscc_ocelot_probe in ocelot_board.c.
-
-The phy_set_mode_ext() call for the SerDes PHY has also been moved into
-mscc_ocelot_probe from ocelot_port_open, and since that was the only
-reason why a reference to it was kept in ocelot_port_private, that
-reference was removed.
-
-Again, the usage of phy_interface_t phy_mode is now local to
-mscc_ocelot_probe only, after moving the PHY connect operation.
-So it was also removed from ocelot_port_private.
-*Maybe* in the future, it can be added back to the common struct
-ocelot_port, with the purpose of validating mismatches between
-state->phy_interface and ocelot_port->phy_mode in PHYLINK callbacks.
-But at the moment that is not critical, since other DSA drivers are not
-doing that either. No SFP+ modules are in use with Felix/Ocelot yet, to
-my knowledge.
-
-In-band AN is not yet supported, due to the fact that this is a mostly
-mechanical patch for the moment. The mac_an_restart PHYLINK operation
-needs to be implemented, as well as mac_link_state. Both are SerDes
-specific, and Felix does not have its PCS configured yet (it works just
-by virtue of U-Boot initialization at the moment).
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c           |  65 +++++++++----
- drivers/net/ethernet/mscc/Kconfig        |   2 +-
- drivers/net/ethernet/mscc/ocelot.c       | 150 ++++++++++++++++--------------
- drivers/net/ethernet/mscc/ocelot.h       |  13 +--
- drivers/net/ethernet/mscc/ocelot_board.c | 154 +++++++++++++++++++++++++++----
- include/soc/mscc/ocelot.h                |  22 ++++-
- 6 files changed, 289 insertions(+), 117 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -58,14 +58,6 @@ static int felix_set_ageing_time(struct
-       return 0;
- }
--static void felix_adjust_link(struct dsa_switch *ds, int port,
--                            struct phy_device *phydev)
--{
--      struct ocelot *ocelot = ds->priv;
--
--      ocelot_adjust_link(ocelot, port, phydev);
--}
--
- static int felix_fdb_dump(struct dsa_switch *ds, int port,
-                         dsa_fdb_dump_cb_t *cb, void *data)
- {
-@@ -185,21 +177,59 @@ static int felix_tsn_enable(struct dsa_p
- }
- #endif
--static int felix_port_enable(struct dsa_switch *ds, int port,
--                           struct phy_device *phy)
-+static void felix_phylink_validate(struct dsa_switch *ds, int port,
-+                                 unsigned long *supported,
-+                                 struct phylink_link_state *state)
- {
-       struct ocelot *ocelot = ds->priv;
--      ocelot_port_enable(ocelot, port, phy);
-+      ocelot_phylink_validate(ocelot, port, supported, state);
-+}
-+
-+static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
-+                                         struct phylink_link_state *state)
-+{
-+      struct ocelot *ocelot = ds->priv;
-+
-+      ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
-       return 0;
- }
--static void felix_port_disable(struct dsa_switch *ds, int port)
-+static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
-+                                   unsigned int link_an_mode,
-+                                   const struct phylink_link_state *state)
-+{
-+      struct ocelot *ocelot = ds->priv;
-+
-+      ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
-+}
-+
-+static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port)
-+{
-+      struct ocelot *ocelot = ds->priv;
-+
-+      ocelot_phylink_mac_an_restart(ocelot, port);
-+}
-+
-+static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
-+                                      unsigned int link_an_mode,
-+                                      phy_interface_t interface)
-+{
-+      struct ocelot *ocelot = ds->priv;
-+
-+      ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface);
-+}
-+
-+static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
-+                                    unsigned int link_an_mode,
-+                                    phy_interface_t interface,
-+                                    struct phy_device *phydev)
- {
-       struct ocelot *ocelot = ds->priv;
--      return ocelot_port_disable(ocelot, port);
-+      ocelot_phylink_mac_link_up(ocelot, port, link_an_mode, interface,
-+                                 phydev);
- }
- static void felix_get_strings(struct dsa_switch *ds, int port,
-@@ -417,9 +447,12 @@ static const struct dsa_switch_ops felix
-       .get_ethtool_stats      = felix_get_ethtool_stats,
-       .get_sset_count         = felix_get_sset_count,
-       .get_ts_info            = felix_get_ts_info,
--      .adjust_link            = felix_adjust_link,
--      .port_enable            = felix_port_enable,
--      .port_disable           = felix_port_disable,
-+      .phylink_validate       = felix_phylink_validate,
-+      .phylink_mac_link_state = felix_phylink_mac_pcs_get_state,
-+      .phylink_mac_config     = felix_phylink_mac_config,
-+      .phylink_mac_an_restart = felix_phylink_mac_an_restart,
-+      .phylink_mac_link_down  = felix_phylink_mac_link_down,
-+      .phylink_mac_link_up    = felix_phylink_mac_link_up,
-       .port_fdb_dump          = felix_fdb_dump,
-       .port_fdb_add           = felix_fdb_add,
-       .port_fdb_del           = felix_fdb_del,
---- a/drivers/net/ethernet/mscc/Kconfig
-+++ b/drivers/net/ethernet/mscc/Kconfig
-@@ -15,7 +15,7 @@ config MSCC_OCELOT_SWITCH
-       tristate "Ocelot switch driver"
-       depends on NET_SWITCHDEV
-       depends on HAS_IOMEM
--      select PHYLIB
-+      select PHYLINK
-       select REGMAP_MMIO
-       help
-         This driver supports the Ocelot network switch device.
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -13,7 +13,7 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/netdevice.h>
--#include <linux/phy.h>
-+#include <linux/phylink.h>
- #include <linux/ptp_clock_kernel.h>
- #include <linux/skbuff.h>
- #include <linux/iopoll.h>
-@@ -406,18 +406,66 @@ static u16 ocelot_wm_enc(u16 value)
-       return value;
- }
--void ocelot_adjust_link(struct ocelot *ocelot, int port,
--                      struct phy_device *phydev)
-+void ocelot_phylink_validate(struct ocelot *ocelot, int port,
-+                           unsigned long *supported,
-+                           struct phylink_link_state *state)
-+{
-+      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-+
-+      if (state->interface != PHY_INTERFACE_MODE_NA &&
-+          state->interface != PHY_INTERFACE_MODE_GMII &&
-+          state->interface != PHY_INTERFACE_MODE_SGMII &&
-+          state->interface != PHY_INTERFACE_MODE_QSGMII) {
-+              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-+              return;
-+      }
-+
-+      /* No half-duplex. */
-+      phylink_set_port_modes(mask);
-+      phylink_set(mask, Autoneg);
-+      phylink_set(mask, Pause);
-+      phylink_set(mask, Asym_Pause);
-+      phylink_set(mask, 10baseT_Full);
-+      phylink_set(mask, 100baseT_Full);
-+      phylink_set(mask, 1000baseT_Full);
-+      phylink_set(mask, 2500baseT_Full);
-+
-+      bitmap_and(supported, supported, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+      bitmap_and(state->advertising, state->advertising, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+}
-+EXPORT_SYMBOL(ocelot_phylink_validate);
-+
-+void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
-+                                    struct phylink_link_state *state)
-+{
-+      state->link = 1;
-+}
-+EXPORT_SYMBOL(ocelot_phylink_mac_pcs_get_state);
-+
-+void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port)
-+{
-+      /* Not supported */
-+}
-+EXPORT_SYMBOL(ocelot_phylink_mac_an_restart);
-+
-+void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
-+                             unsigned int link_an_mode,
-+                             const struct phylink_link_state *state)
- {
-       int speed, mac_speed, mac_mode = DEV_MAC_MODE_CFG_FDX_ENA;
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
-+      u32 mac_fc_cfg;
-       if (ocelot->quirks & OCELOT_PCS_PERFORMS_RATE_ADAPTATION)
-               speed = SPEED_1000;
-       else
--              speed = phydev->speed;
-+              speed = state->speed;
-       switch (speed) {
-+      case SPEED_UNKNOWN:
-+              return;
-       case SPEED_10:
-               mac_speed = OCELOT_SPEED_10;
-               break;
-@@ -433,16 +481,11 @@ void ocelot_adjust_link(struct ocelot *o
-               mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       default:
--              dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
-+              dev_err(ocelot->dev, "Unsupported speed on port %d: %d\n",
-                       port, speed);
-               return;
-       }
--      phy_print_status(phydev);
--
--      if (!phydev->link)
--              return;
--
-       /* Only full duplex supported for now */
-       ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-@@ -469,27 +512,36 @@ void ocelot_adjust_link(struct ocelot *o
-                        QSYS_SWITCH_PORT_MODE, port);
-       /* Flow control */
--      ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
--                       SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
--                       SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
--                       SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
--                       SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed),
--                       SYS_MAC_FC_CFG, port);
-+      mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed);
-+      if (state->pause & MLO_PAUSE_RX)
-+              mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA;
-+      if (state->pause & MLO_PAUSE_TX)
-+              mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA |
-+                            SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
-+                            SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
-+                            SYS_MAC_FC_CFG_ZERO_PAUSE_ENA;
-+      ocelot_write_rix(ocelot, mac_fc_cfg, SYS_MAC_FC_CFG, port);
-+
-       ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
- }
--EXPORT_SYMBOL(ocelot_adjust_link);
-+EXPORT_SYMBOL(ocelot_phylink_mac_config);
--static void ocelot_port_adjust_link(struct net_device *dev)
-+void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
-+                                unsigned int link_an_mode,
-+                                phy_interface_t interface)
- {
--      struct ocelot_port_private *priv = netdev_priv(dev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
-+      struct ocelot_port *ocelot_port = ocelot->ports[port];
--      ocelot_adjust_link(ocelot, port, dev->phydev);
-+      ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
-+      ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-+                     QSYS_SWITCH_PORT_MODE, port);
- }
-+EXPORT_SYMBOL(ocelot_phylink_mac_link_down);
--void ocelot_port_enable(struct ocelot *ocelot, int port,
--                      struct phy_device *phy)
-+void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
-+                              unsigned int link_an_mode,
-+                              phy_interface_t interface,
-+                              struct phy_device *phy)
- {
-       /* Enable receiving frames on the port, and activate auto-learning of
-        * MAC addresses.
-@@ -499,62 +551,22 @@ void ocelot_port_enable(struct ocelot *o
-                        ANA_PORT_PORT_CFG_PORTID_VAL(port),
-                        ANA_PORT_PORT_CFG, port);
- }
--EXPORT_SYMBOL(ocelot_port_enable);
-+EXPORT_SYMBOL(ocelot_phylink_mac_link_up);
- static int ocelot_port_open(struct net_device *dev)
- {
-       struct ocelot_port_private *priv = netdev_priv(dev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--      int err;
--
--      if (priv->serdes) {
--              err = phy_set_mode_ext(priv->serdes, PHY_MODE_ETHERNET,
--                                     priv->phy_mode);
--              if (err) {
--                      netdev_err(dev, "Could not set mode of SerDes\n");
--                      return err;
--              }
--      }
--
--      err = phy_connect_direct(dev, priv->phy, &ocelot_port_adjust_link,
--                               priv->phy_mode);
--      if (err) {
--              netdev_err(dev, "Could not attach to PHY\n");
--              return err;
--      }
--      dev->phydev = priv->phy;
--
--      phy_attached_info(priv->phy);
--      phy_start(priv->phy);
--
--      ocelot_port_enable(ocelot, port, priv->phy);
-+      phylink_start(priv->phylink);
-       return 0;
- }
--void ocelot_port_disable(struct ocelot *ocelot, int port)
--{
--      struct ocelot_port *ocelot_port = ocelot->ports[port];
--
--      ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
--      ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
--                     QSYS_SWITCH_PORT_MODE, port);
--}
--EXPORT_SYMBOL(ocelot_port_disable);
--
- static int ocelot_port_stop(struct net_device *dev)
- {
-       struct ocelot_port_private *priv = netdev_priv(dev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      phy_disconnect(priv->phy);
--
--      dev->phydev = NULL;
--      ocelot_port_disable(ocelot, port);
-+      phylink_stop(priv->phylink);
-       return 0;
- }
-@@ -2251,8 +2263,7 @@ void ocelot_init_port(struct ocelot *oce
- EXPORT_SYMBOL(ocelot_init_port);
- int ocelot_probe_port(struct ocelot *ocelot, u8 port,
--                    void __iomem *regs,
--                    struct phy_device *phy)
-+                    void __iomem *regs)
- {
-       struct ocelot_port_private *priv;
-       struct ocelot_port *ocelot_port;
-@@ -2265,7 +2276,6 @@ int ocelot_probe_port(struct ocelot *oce
-       SET_NETDEV_DEV(dev, ocelot->dev);
-       priv = netdev_priv(dev);
-       priv->dev = dev;
--      priv->phy = phy;
-       priv->chip_port = port;
-       ocelot_port = &priv->port;
-       ocelot_port->ocelot = ocelot;
---- a/drivers/net/ethernet/mscc/ocelot.h
-+++ b/drivers/net/ethernet/mscc/ocelot.h
-@@ -12,8 +12,7 @@
- #include <linux/etherdevice.h>
- #include <linux/if_vlan.h>
- #include <linux/net_tstamp.h>
--#include <linux/phy.h>
--#include <linux/phy/phy.h>
-+#include <linux/phylink.h>
- #include <linux/platform_device.h>
- #include <linux/ptp_clock_kernel.h>
- #include <linux/regmap.h>
-@@ -65,14 +64,12 @@ struct ocelot_multicast {
- struct ocelot_port_private {
-       struct ocelot_port port;
-       struct net_device *dev;
--      struct phy_device *phy;
-+      struct phylink *phylink;
-+      struct phylink_config phylink_config;
-       u8 chip_port;
-       u8 vlan_aware;
--      phy_interface_t phy_mode;
--      struct phy *serdes;
--
-       struct ocelot_port_tc tc;
- };
-@@ -83,9 +80,7 @@ void ocelot_port_writel(struct ocelot_po
- #define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
- int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops);
--int ocelot_probe_port(struct ocelot *ocelot, u8 port,
--                    void __iomem *regs,
--                    struct phy_device *phy);
-+int ocelot_probe_port(struct ocelot *ocelot, u8 port, void __iomem *regs);
- void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
-                        enum ocelot_tag_prefix injection,
---- a/drivers/net/ethernet/mscc/ocelot_board.c
-+++ b/drivers/net/ethernet/mscc/ocelot_board.c
-@@ -13,6 +13,7 @@
- #include <linux/mfd/syscon.h>
- #include <linux/skbuff.h>
- #include <net/switchdev.h>
-+#include <linux/phy/phy.h>
- #include "ocelot.h"
-@@ -262,6 +263,91 @@ static const struct ocelot_ops ocelot_op
-       .reset                  = ocelot_reset,
- };
-+static void ocelot_port_phylink_validate(struct phylink_config *config,
-+                                       unsigned long *supported,
-+                                       struct phylink_link_state *state)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      ocelot_phylink_validate(ocelot, port, supported, state);
-+}
-+
-+static int
-+ocelot_port_phylink_mac_pcs_get_state(struct phylink_config *config,
-+                                    struct phylink_link_state *state)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
-+
-+      return 0;
-+}
-+
-+static void ocelot_port_phylink_mac_an_restart(struct phylink_config *config)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      ocelot_phylink_mac_an_restart(ocelot, port);
-+}
-+
-+static void
-+ocelot_port_phylink_mac_config(struct phylink_config *config,
-+                             unsigned int link_an_mode,
-+                             const struct phylink_link_state *state)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
-+}
-+
-+static void ocelot_port_phylink_mac_link_down(struct phylink_config *config,
-+                                            unsigned int link_an_mode,
-+                                            phy_interface_t interface)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      return ocelot_phylink_mac_link_down(ocelot, port, link_an_mode,
-+                                          interface);
-+}
-+
-+static void ocelot_port_phylink_mac_link_up(struct phylink_config *config,
-+                                          unsigned int link_an_mode,
-+                                          phy_interface_t interface,
-+                                          struct phy_device *phy)
-+{
-+      struct net_device *ndev = to_net_dev(config->dev);
-+      struct ocelot_port_private *priv = netdev_priv(ndev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      return ocelot_phylink_mac_link_up(ocelot, port, link_an_mode,
-+                                        interface, phy);
-+}
-+
-+static const struct phylink_mac_ops ocelot_phylink_ops = {
-+      .validate               = ocelot_port_phylink_validate,
-+      .mac_link_state         = ocelot_port_phylink_mac_pcs_get_state,
-+      .mac_an_restart         = ocelot_port_phylink_mac_an_restart,
-+      .mac_config             = ocelot_port_phylink_mac_config,
-+      .mac_link_down          = ocelot_port_phylink_mac_link_down,
-+      .mac_link_up            = ocelot_port_phylink_mac_link_up,
-+};
-+
- static int mscc_ocelot_probe(struct platform_device *pdev)
- {
-       struct device_node *np = pdev->dev.of_node;
-@@ -369,8 +455,6 @@ static int mscc_ocelot_probe(struct plat
-       for_each_available_child_of_node(ports, portnp) {
-               struct ocelot_port_private *priv;
-               struct ocelot_port *ocelot_port;
--              struct device_node *phy_node;
--              struct phy_device *phy;
-               struct resource *res;
-               struct phy *serdes;
-               void __iomem *regs;
-@@ -389,16 +473,7 @@ static int mscc_ocelot_probe(struct plat
-               if (IS_ERR(regs))
-                       continue;
--              phy_node = of_parse_phandle(portnp, "phy-handle", 0);
--              if (!phy_node)
--                      continue;
--
--              phy = of_phy_find_device(phy_node);
--              of_node_put(phy_node);
--              if (!phy)
--                      continue;
--
--              err = ocelot_probe_port(ocelot, port, regs, phy);
-+              err = ocelot_probe_port(ocelot, port, regs);
-               if (err) {
-                       of_node_put(portnp);
-                       goto out_put_ports;
-@@ -412,9 +487,7 @@ static int mscc_ocelot_probe(struct plat
-               if (phy_mode < 0)
-                       phy_mode = PHY_INTERFACE_MODE_NA;
--              priv->phy_mode = phy_mode;
--
--              switch (priv->phy_mode) {
-+              switch (phy_mode) {
-               case PHY_INTERFACE_MODE_NA:
-                       continue;
-               case PHY_INTERFACE_MODE_SGMII:
-@@ -451,7 +524,41 @@ static int mscc_ocelot_probe(struct plat
-                       goto out_put_ports;
-               }
--              priv->serdes = serdes;
-+              if (serdes) {
-+                      err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET,
-+                                             phy_mode);
-+                      if (err) {
-+                              dev_err(ocelot->dev,
-+                                      "Could not set mode of SerDes\n");
-+                              of_node_put(portnp);
-+                              goto out_put_ports;
-+                      }
-+              }
-+
-+              priv->phylink_config.dev = &priv->dev->dev;
-+              priv->phylink_config.type = PHYLINK_NETDEV;
-+
-+              priv->phylink = phylink_create(&priv->phylink_config,
-+                                             of_fwnode_handle(portnp),
-+                                             phy_mode, &ocelot_phylink_ops);
-+              if (IS_ERR(priv->phylink)) {
-+                      dev_err(ocelot->dev,
-+                              "Could not create a phylink instance (%ld)\n",
-+                              PTR_ERR(priv->phylink));
-+                      err = PTR_ERR(priv->phylink);
-+                      priv->phylink = NULL;
-+                      of_node_put(portnp);
-+                      goto out_put_ports;
-+              }
-+
-+              err = phylink_of_phy_connect(priv->phylink, portnp, 0);
-+              if (err) {
-+                      dev_err(ocelot->dev, "Could not connect to PHY: %d\n",
-+                              err);
-+                      phylink_destroy(priv->phylink);
-+                      of_node_put(portnp);
-+                      goto out_put_ports;
-+              }
-       }
-       register_netdevice_notifier(&ocelot_netdevice_nb);
-@@ -468,12 +575,27 @@ out_put_ports:
- static int mscc_ocelot_remove(struct platform_device *pdev)
- {
-       struct ocelot *ocelot = platform_get_drvdata(pdev);
-+      int port;
-       ocelot_deinit(ocelot);
-       unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
-       unregister_switchdev_notifier(&ocelot_switchdev_nb);
-       unregister_netdevice_notifier(&ocelot_netdevice_nb);
-+      for (port = 0; port < ocelot->num_phys_ports; port++) {
-+              struct ocelot_port_private *priv;
-+
-+              priv = container_of(ocelot->ports[port],
-+                                  struct ocelot_port_private,
-+                                  port);
-+
-+              if (priv->phylink) {
-+                      rtnl_lock();
-+                      phylink_destroy(priv->phylink);
-+                      rtnl_unlock();
-+              }
-+      }
-+
-       return 0;
- }
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -518,17 +518,12 @@ void ocelot_deinit(struct ocelot *ocelot
- void ocelot_init_port(struct ocelot *ocelot, int port);
- /* DSA callbacks */
--void ocelot_port_enable(struct ocelot *ocelot, int port,
--                      struct phy_device *phy);
--void ocelot_port_disable(struct ocelot *ocelot, int port);
- void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data);
- void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data);
- int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset);
- int ocelot_get_ts_info(struct ocelot *ocelot, int port,
-                      struct ethtool_ts_info *info);
- void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
--void ocelot_adjust_link(struct ocelot *ocelot, int port,
--                      struct phy_device *phydev);
- void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
-                               bool vlan_aware);
- void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state);
-@@ -597,4 +592,21 @@ int ocelot_rtag_parse_enable(struct ocel
- int ocelot_dscp_set(struct ocelot *ocelot, int port,
-                   bool enable, const u8 dscp_ix,
-                   struct tsn_qos_switch_dscp_conf *c);
-+void ocelot_phylink_validate(struct ocelot *ocelot, int port,
-+                           unsigned long *supported,
-+                           struct phylink_link_state *state);
-+void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
-+                                    struct phylink_link_state *state);
-+void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port);
-+void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
-+                             unsigned int link_an_mode,
-+                             const struct phylink_link_state *state);
-+void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
-+                                unsigned int link_an_mode,
-+                                phy_interface_t interface);
-+void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
-+                              unsigned int link_an_mode,
-+                              phy_interface_t interface,
-+                              struct phy_device *phy);
-+
- #endif
diff --git a/target/linux/layerscape/patches-5.4/701-net-0282-net-mscc-ocelot-introduce-more-focused-PCS-ops-for-P.patch b/target/linux/layerscape/patches-5.4/701-net-0282-net-mscc-ocelot-introduce-more-focused-PCS-ops-for-P.patch
deleted file mode 100644 (file)
index d7ae119..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-From 07f63e91f5e81f7f36c1e646f72c394c7f60c05c Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 22 Nov 2019 13:46:34 +0200
-Subject: [PATCH] net: mscc: ocelot: introduce more focused PCS ops for PHYLINK
-
-The reason for doing this is that the 2 mainline Ocelot switches so far,
-VSC7514 and VSC9959, have radically different SoC/SerDes integration. So
-although the PHYLINK callbacks are common, the implementations will
-actually lie in device-specific function pointers.
-
-Also, there was a duplicated and unused function pointer for pcs_init in
-struct ocelot, remove that.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/mscc/ocelot.c       | 36 ++++++++------------------------
- drivers/net/ethernet/mscc/ocelot_board.c | 35 ++++++++++++++++++++++++++++++-
- include/soc/mscc/ocelot.h                | 12 ++++++++---
- 3 files changed, 52 insertions(+), 31 deletions(-)
-
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -410,43 +410,25 @@ void ocelot_phylink_validate(struct ocel
-                            unsigned long *supported,
-                            struct phylink_link_state *state)
- {
--      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
--
--      if (state->interface != PHY_INTERFACE_MODE_NA &&
--          state->interface != PHY_INTERFACE_MODE_GMII &&
--          state->interface != PHY_INTERFACE_MODE_SGMII &&
--          state->interface != PHY_INTERFACE_MODE_QSGMII) {
--              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
--              return;
--      }
--
--      /* No half-duplex. */
--      phylink_set_port_modes(mask);
--      phylink_set(mask, Autoneg);
--      phylink_set(mask, Pause);
--      phylink_set(mask, Asym_Pause);
--      phylink_set(mask, 10baseT_Full);
--      phylink_set(mask, 100baseT_Full);
--      phylink_set(mask, 1000baseT_Full);
--      phylink_set(mask, 2500baseT_Full);
--
--      bitmap_and(supported, supported, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--      bitmap_and(state->advertising, state->advertising, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+      if (ocelot->ops->pcs_validate)
-+              ocelot->ops->pcs_validate(ocelot, port, supported, state);
- }
- EXPORT_SYMBOL(ocelot_phylink_validate);
- void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
-                                     struct phylink_link_state *state)
- {
--      state->link = 1;
-+      if (ocelot->ops->pcs_link_state)
-+              ocelot->ops->pcs_link_state(ocelot, port, state);
-+      else
-+              state->link = 1;
- }
- EXPORT_SYMBOL(ocelot_phylink_mac_pcs_get_state);
- void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port)
- {
--      /* Not supported */
-+      if (ocelot->ops->pcs_an_restart)
-+              ocelot->ops->pcs_an_restart(ocelot, port);
- }
- EXPORT_SYMBOL(ocelot_phylink_mac_an_restart);
-@@ -490,7 +472,7 @@ void ocelot_phylink_mac_config(struct oc
-       ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-       if (ocelot->ops->pcs_init)
--              ocelot->ops->pcs_init(ocelot, port);
-+              ocelot->ops->pcs_init(ocelot, port, link_an_mode, state);
-       /* Enable MAC module */
-       ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
---- a/drivers/net/ethernet/mscc/ocelot_board.c
-+++ b/drivers/net/ethernet/mscc/ocelot_board.c
-@@ -212,7 +212,9 @@ static const struct of_device_id mscc_oc
- };
- MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
--static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
-+static void ocelot_port_pcs_init(struct ocelot *ocelot, int port,
-+                               unsigned int link_an_mode,
-+                               const struct phylink_link_state *state)
- {
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
-@@ -235,6 +237,36 @@ static void ocelot_port_pcs_init(struct
-       ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
- }
-+void ocelot_port_pcs_validate(struct ocelot *ocelot, int port,
-+                            unsigned long *supported,
-+                            struct phylink_link_state *state)
-+{
-+      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-+
-+      if (state->interface != PHY_INTERFACE_MODE_NA &&
-+          state->interface != PHY_INTERFACE_MODE_GMII &&
-+          state->interface != PHY_INTERFACE_MODE_SGMII &&
-+          state->interface != PHY_INTERFACE_MODE_QSGMII) {
-+              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-+              return;
-+      }
-+
-+      /* No half-duplex. */
-+      phylink_set_port_modes(mask);
-+      phylink_set(mask, Autoneg);
-+      phylink_set(mask, Pause);
-+      phylink_set(mask, Asym_Pause);
-+      phylink_set(mask, 10baseT_Full);
-+      phylink_set(mask, 100baseT_Full);
-+      phylink_set(mask, 1000baseT_Full);
-+      phylink_set(mask, 2500baseT_Full);
-+
-+      bitmap_and(supported, supported, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+      bitmap_and(state->advertising, state->advertising, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+}
-+
- static int ocelot_reset(struct ocelot *ocelot)
- {
-       int retries = 100;
-@@ -260,6 +292,7 @@ static int ocelot_reset(struct ocelot *o
- static const struct ocelot_ops ocelot_ops = {
-       .pcs_init               = ocelot_port_pcs_init,
-+      .pcs_validate           = ocelot_port_pcs_validate,
-       .reset                  = ocelot_reset,
- };
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -412,7 +412,15 @@ enum {
- struct ocelot;
- struct ocelot_ops {
--      void (*pcs_init)(struct ocelot *ocelot, int port);
-+      void (*pcs_init)(struct ocelot *ocelot, int port,
-+                       unsigned int link_an_mode,
-+                       const struct phylink_link_state *state);
-+      void (*pcs_an_restart)(struct ocelot *ocelot, int port);
-+      void (*pcs_link_state)(struct ocelot *ocelot, int port,
-+                             struct phylink_link_state *state);
-+      void (*pcs_validate)(struct ocelot *ocelot, int port,
-+                           unsigned long *supported,
-+                           struct phylink_link_state *state);
-       int (*reset)(struct ocelot *ocelot);
- };
-@@ -479,8 +487,6 @@ struct ocelot {
-       struct mutex                    ptp_lock;
-       /* Protects the PTP clock */
-       spinlock_t                      ptp_clock_lock;
--
--      void (*port_pcs_init)(struct ocelot_port *port);
- };
- #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
diff --git a/target/linux/layerscape/patches-5.4/701-net-0283-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch b/target/linux/layerscape/patches-5.4/701-net-0283-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch
deleted file mode 100644 (file)
index e2de403..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-From 0e219a6aa07754d81a25c9e4408d81d194cd2000 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 22 Nov 2019 13:45:52 +0200
-Subject: [PATCH] net: dsa: felix: Add PCS operations for PHYLINK
-
-This removes the bootloader dependency for SGMII PCS pre-configuration,
-as well as adds support for monitoring the in-band SGMII AN between the
-PCS and the system-side link partner (PHY or other MAC).
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c         |  23 ++-
- drivers/net/dsa/ocelot/felix.h         |   7 +-
- drivers/net/dsa/ocelot/felix_vsc9959.c | 292 ++++++++++++++++++++++++++++++++-
- 3 files changed, 314 insertions(+), 8 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -265,7 +265,7 @@ static int felix_get_ts_info(struct dsa_
- static int felix_init_structs(struct felix *felix, int num_phys_ports)
- {
-       struct ocelot *ocelot = &felix->ocelot;
--      resource_size_t base;
-+      resource_size_t switch_base;
-       int port, i, err;
-       ocelot->num_phys_ports = num_phys_ports;
-@@ -281,7 +281,8 @@ static int felix_init_structs(struct fel
-       ocelot->ops             = felix->info->ops;
-       ocelot->quirks          = felix->info->quirks;
--      base = pci_resource_start(felix->pdev, felix->info->pci_bar);
-+      switch_base = pci_resource_start(felix->pdev,
-+                                       felix->info->switch_pci_bar);
-       for (i = 0; i < TARGET_MAX; i++) {
-               struct regmap *target;
-@@ -292,8 +293,8 @@ static int felix_init_structs(struct fel
-               res = &felix->info->target_io_res[i];
-               res->flags = IORESOURCE_MEM;
--              res->start += base;
--              res->end += base;
-+              res->start += switch_base;
-+              res->end += switch_base;
-               target = ocelot_regmap_init(ocelot, res);
-               if (IS_ERR(target)) {
-@@ -327,8 +328,8 @@ static int felix_init_structs(struct fel
-               res = &felix->info->port_io_res[port];
-               res->flags = IORESOURCE_MEM;
--              res->start += base;
--              res->end += base;
-+              res->start += switch_base;
-+              res->end += switch_base;
-               port_regs = devm_ioremap_resource(ocelot->dev, res);
-               if (IS_ERR(port_regs)) {
-@@ -342,6 +343,12 @@ static int felix_init_structs(struct fel
-               ocelot->ports[port] = ocelot_port;
-       }
-+      if (felix->info->mdio_bus_alloc) {
-+              err = felix->info->mdio_bus_alloc(ocelot);
-+              if (err < 0)
-+                      return err;
-+      }
-+
-       return 0;
- }
-@@ -377,6 +384,10 @@ static int felix_setup(struct dsa_switch
- static void felix_teardown(struct dsa_switch *ds)
- {
-       struct ocelot *ocelot = ds->priv;
-+      struct felix *felix = ocelot_to_felix(ocelot);
-+
-+      if (felix->imdio)
-+              mdiobus_unregister(felix->imdio);
-       /* stop workqueue thread */
-       ocelot_deinit(ocelot);
---- a/drivers/net/dsa/ocelot/felix.h
-+++ b/drivers/net/dsa/ocelot/felix.h
-@@ -10,6 +10,7 @@
- struct felix_info {
-       struct resource                 *target_io_res;
-       struct resource                 *port_io_res;
-+      struct resource                 *imdio_res;
-       const struct reg_field          *regfields;
-       const u32 *const                *map;
-       const struct ocelot_ops         *ops;
-@@ -17,8 +18,10 @@ struct felix_info {
-       const struct ocelot_stat_layout *stats_layout;
-       unsigned int                    num_stats;
-       int                             num_ports;
--      int                             pci_bar;
-+      int                             switch_pci_bar;
-+      int                             imdio_pci_bar;
-       unsigned long                   quirks;
-+      int (*mdio_bus_alloc)(struct ocelot *ocelot);
- };
- extern struct felix_info              felix_info_vsc9959;
-@@ -33,6 +36,8 @@ struct felix {
-       struct pci_dev                  *pdev;
-       struct felix_info               *info;
-       struct ocelot                   ocelot;
-+      struct mii_bus                  *imdio;
-+      struct phy_device               **pcs;
- };
- #endif
---- a/drivers/net/dsa/ocelot/felix_vsc9959.c
-+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
-@@ -2,6 +2,7 @@
- /* Copyright 2017 Microsemi Corporation
-  * Copyright 2018-2019 NXP Semiconductors
-  */
-+#include <linux/fsl/enetc_mdio.h>
- #include <soc/mscc/ocelot_sys.h>
- #include <soc/mscc/ocelot.h>
- #include <linux/iopoll.h>
-@@ -390,6 +391,15 @@ static struct resource vsc9959_port_io_r
-       },
- };
-+/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
-+ * SGMII/QSGMII MAC PCS can be found.
-+ */
-+static struct resource vsc9959_imdio_res = {
-+      .start          = 0x8030,
-+      .end            = 0x8040,
-+      .name           = "imdio",
-+};
-+
- static const struct reg_field vsc9959_regfields[] = {
-       [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
-       [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),
-@@ -569,13 +579,291 @@ static int vsc9959_reset(struct ocelot *
-       return 0;
- }
-+void vsc9959_pcs_validate(struct ocelot *ocelot, int port,
-+                        unsigned long *supported,
-+                        struct phylink_link_state *state)
-+{
-+      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-+
-+      if (state->interface != PHY_INTERFACE_MODE_NA &&
-+          state->interface != PHY_INTERFACE_MODE_GMII &&
-+          state->interface != PHY_INTERFACE_MODE_SGMII &&
-+          state->interface != PHY_INTERFACE_MODE_QSGMII &&
-+          state->interface != PHY_INTERFACE_MODE_USXGMII) {
-+              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-+              return;
-+      }
-+
-+      /* No half-duplex. */
-+      phylink_set_port_modes(mask);
-+      phylink_set(mask, Autoneg);
-+      phylink_set(mask, Pause);
-+      phylink_set(mask, Asym_Pause);
-+      phylink_set(mask, 10baseT_Full);
-+      phylink_set(mask, 100baseT_Full);
-+      phylink_set(mask, 1000baseT_Full);
-+      phylink_set(mask, 1000baseX_Full);
-+      phylink_set(mask, 2500baseT_Full);
-+      phylink_set(mask, 2500baseX_Full);
-+      phylink_set(mask, 1000baseKX_Full);
-+
-+      bitmap_and(supported, supported, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+      bitmap_and(state->advertising, state->advertising, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+}
-+
-+static void vsc9959_pcs_an_restart(struct ocelot *ocelot, int port)
-+{
-+      struct felix *felix = ocelot_to_felix(ocelot);
-+      struct phy_device *pcs = felix->pcs[port];
-+
-+      if (!pcs)
-+              return;
-+
-+      phy_set_bits(pcs, MII_BMCR, BMCR_ANRESTART);
-+}
-+
-+static void vsc9959_pcs_init_sgmii(struct phy_device *pcs,
-+                                 unsigned int link_an_mode,
-+                                 const struct phylink_link_state *state)
-+{
-+      /* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
-+       * for the MAC PCS in order to acknowledge the AN.
-+       */
-+      phy_write(pcs, MII_ADVERTISE, ADVERTISE_SGMII | ADVERTISE_LPACK);
-+
-+      /* Set to SGMII mode, use AN */
-+      phy_write(pcs, ENETC_PCS_IF_MODE, ENETC_PCS_IF_MODE_SGMII_AN);
-+
-+      /* Adjust link timer for SGMII */
-+      phy_write(pcs, ENETC_PCS_LINK_TIMER1, ENETC_PCS_LINK_TIMER1_VAL);
-+      phy_write(pcs, ENETC_PCS_LINK_TIMER2, ENETC_PCS_LINK_TIMER2_VAL);
-+
-+      phy_write(pcs, MII_BMCR, BMCR_SPEED1000 |
-+                               BMCR_FULLDPLX |
-+                               BMCR_ANENABLE);
-+}
-+
-+#define ADVERTISE_USXGMII_FDX         BIT(12)
-+
-+static void vsc9959_pcs_init_sxgmii(struct phy_device *pcs,
-+                                  unsigned int link_an_mode,
-+                                  const struct phylink_link_state *state)
-+{
-+      /* Configure device ability for the USXGMII Replicator */
-+      phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_ADVERTISE,
-+                    ADVERTISE_SGMII |
-+                    ADVERTISE_LPACK |
-+                    ADVERTISE_USXGMII_FDX);
-+}
-+
-+static void vsc9959_pcs_init(struct ocelot *ocelot, int port,
-+                           unsigned int link_an_mode,
-+                           const struct phylink_link_state *state)
-+{
-+      struct felix *felix = ocelot_to_felix(ocelot);
-+      struct phy_device *pcs = felix->pcs[port];
-+
-+      if (!pcs)
-+              return;
-+
-+      if (link_an_mode == MLO_AN_FIXED) {
-+              phydev_err(pcs, "Fixed modes are not yet supported.\n");
-+              return;
-+      }
-+
-+      pcs->interface = state->interface;
-+      if (pcs->interface == PHY_INTERFACE_MODE_USXGMII)
-+              pcs->is_c45 = true;
-+      else
-+              pcs->is_c45 = false;
-+
-+      /* The PCS does not implement the BMSR register fully, so capability
-+       * detection via genphy_read_abilities does not work. Since we can get
-+       * the PHY config word from the LPA register though, there is still
-+       * value in using the generic phy_resolve_aneg_linkmode function. So
-+       * populate the supported and advertising link modes manually here.
-+       */
-+      linkmode_set_bit_array(phy_basic_ports_array,
-+                             ARRAY_SIZE(phy_basic_ports_array),
-+                             pcs->supported);
-+      linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, pcs->supported);
-+      linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pcs->supported);
-+      linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pcs->supported);
-+      linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pcs->supported);
-+      phy_advertise_supported(pcs);
-+
-+      switch (pcs->interface) {
-+      case PHY_INTERFACE_MODE_SGMII:
-+      case PHY_INTERFACE_MODE_QSGMII:
-+              vsc9959_pcs_init_sgmii(pcs, link_an_mode, state);
-+              break;
-+      case PHY_INTERFACE_MODE_USXGMII:
-+              vsc9959_pcs_init_sxgmii(pcs, link_an_mode, state);
-+              break;
-+      default:
-+              dev_err(ocelot->dev, "Unsupported link mode %s\n",
-+                      phy_modes(pcs->interface));
-+      }
-+}
-+
-+static void vsc9959_pcs_link_state(struct ocelot *ocelot, int port,
-+                                 struct phylink_link_state *state)
-+{
-+      struct felix *felix = ocelot_to_felix(ocelot);
-+      struct phy_device *pcs = felix->pcs[port];
-+      int err;
-+
-+      if (!pcs)
-+              return;
-+
-+      /* Reading PCS status not yet supported for USXGMII */
-+      if (pcs->is_c45) {
-+              state->link = 1;
-+              return;
-+      }
-+
-+      pcs->speed = SPEED_UNKNOWN;
-+      pcs->duplex = DUPLEX_UNKNOWN;
-+      pcs->pause = 0;
-+      pcs->asym_pause = 0;
-+
-+      err = genphy_update_link(pcs);
-+      if (err < 0)
-+              return;
-+
-+      if (pcs->autoneg_complete) {
-+              u16 lpa = phy_read(pcs, MII_LPA);
-+
-+              switch (state->interface) {
-+              case PHY_INTERFACE_MODE_SGMII:
-+              case PHY_INTERFACE_MODE_QSGMII:
-+                      mii_lpa_to_linkmode_lpa_sgmii(pcs->lp_advertising, lpa);
-+                      break;
-+              default:
-+                      return;
-+              }
-+
-+              phy_resolve_aneg_linkmode(pcs);
-+      }
-+
-+      state->an_complete = pcs->autoneg_complete;
-+      state->an_enabled = pcs->autoneg;
-+      state->link = pcs->link;
-+      state->duplex = pcs->duplex;
-+      state->speed = pcs->speed;
-+      /* SGMII AN does not negotiate flow control, but that's ok,
-+       * since phylink already knows that, and does:
-+       *      link_state.pause |= pl->phy_state.pause;
-+       */
-+      state->pause = pcs->pause;
-+
-+      dev_dbg(ocelot->dev,
-+              "%s: mode=%s/%s/%s adv=%*pb lpa=%*pb link=%u an_enabled=%u an_complete=%u\n",
-+              __func__,
-+              phy_modes(state->interface),
-+              phy_speed_to_str(state->speed),
-+              phy_duplex_to_str(state->duplex),
-+              __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
-+              __ETHTOOL_LINK_MODE_MASK_NBITS, state->lp_advertising,
-+              state->link, state->an_enabled, state->an_complete);
-+}
-+
- static const struct ocelot_ops vsc9959_ops = {
-       .reset                  = vsc9959_reset,
-+      .pcs_init               = vsc9959_pcs_init,
-+      .pcs_an_restart         = vsc9959_pcs_an_restart,
-+      .pcs_link_state         = vsc9959_pcs_link_state,
-+      .pcs_validate           = vsc9959_pcs_validate,
- };
-+static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
-+{
-+      struct felix *felix = ocelot_to_felix(ocelot);
-+      struct enetc_mdio_priv *mdio_priv;
-+      struct device *dev = ocelot->dev;
-+      resource_size_t imdio_base;
-+      void __iomem *imdio_regs;
-+      struct resource *res;
-+      struct enetc_hw *hw;
-+      struct mii_bus *bus;
-+      int port;
-+      int rc;
-+
-+      felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
-+                                sizeof(struct phy_device),
-+                                GFP_KERNEL);
-+      if (!felix->pcs) {
-+              dev_err(dev, "failed to allocate array for PCS PHYs\n");
-+              return -ENOMEM;
-+      }
-+
-+      imdio_base = pci_resource_start(felix->pdev,
-+                                      felix->info->imdio_pci_bar);
-+
-+      res = felix->info->imdio_res;
-+      res->flags = IORESOURCE_MEM;
-+      res->start += imdio_base;
-+      res->end += imdio_base;
-+
-+      imdio_regs = devm_ioremap_resource(dev, res);
-+      if (IS_ERR(imdio_regs)) {
-+              dev_err(dev, "failed to map internal MDIO registers\n");
-+              return PTR_ERR(imdio_regs);
-+      }
-+
-+      hw = enetc_hw_alloc(dev, imdio_regs);
-+      if (IS_ERR(hw)) {
-+              dev_err(dev, "failed to allocate ENETC HW structure\n");
-+              return PTR_ERR(hw);
-+      }
-+
-+      bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
-+      if (!bus)
-+              return -ENOMEM;
-+
-+      bus->name = "VSC9959 internal MDIO bus";
-+      bus->read = enetc_mdio_read;
-+      bus->write = enetc_mdio_write;
-+      bus->parent = dev;
-+      mdio_priv = bus->priv;
-+      mdio_priv->hw = hw;
-+      /* This gets added to imdio_regs, which already maps addresses
-+       * starting with the proper offset.
-+       */
-+      mdio_priv->mdio_base = 0;
-+      snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
-+
-+      /* Needed in order to initialize the bus mutex lock */
-+      rc = mdiobus_register(bus);
-+      if (rc < 0) {
-+              dev_err(dev, "failed to register MDIO bus\n");
-+              return rc;
-+      }
-+
-+      felix->imdio = bus;
-+
-+      for (port = 0; port < felix->info->num_ports; port++) {
-+              struct phy_device *pcs;
-+              bool is_c45 = false;
-+
-+              pcs = get_phy_device(felix->imdio, port, is_c45);
-+              if (IS_ERR(pcs))
-+                      continue;
-+
-+              felix->pcs[port] = pcs;
-+
-+              dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
-+      }
-+
-+      return 0;
-+}
-+
- struct felix_info felix_info_vsc9959 = {
-       .target_io_res          = vsc9959_target_io_res,
-       .port_io_res            = vsc9959_port_io_res,
-+      .imdio_res              = &vsc9959_imdio_res,
-       .regfields              = vsc9959_regfields,
-       .map                    = vsc9959_regmap,
-       .ops                    = &vsc9959_ops,
-@@ -583,6 +871,8 @@ struct felix_info felix_info_vsc9959 = {
-       .num_stats              = ARRAY_SIZE(vsc9959_stats_layout),
-       .shared_queue_sz        = 128 * 1024,
-       .num_ports              = 6,
--      .pci_bar                = 4,
-+      .switch_pci_bar         = 4,
-+      .imdio_pci_bar          = 0,
-       .quirks                 = OCELOT_PCS_PERFORMS_RATE_ADAPTATION,
-+      .mdio_bus_alloc         = vsc9959_mdio_bus_alloc,
- };
index 3e99861d1689538d6462f7d4420826209ed6c805..ec4c62a7a525e188b49c214c6967110ae024acea 100644 (file)
@@ -90,7 +90,7 @@ Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
 
 --- a/drivers/net/dsa/ocelot/felix.c
 +++ b/drivers/net/dsa/ocelot/felix.c
-@@ -530,7 +530,7 @@ static int felix_pci_probe(struct pci_de
+@@ -485,7 +485,7 @@ static int felix_pci_probe(struct pci_de
                }
        }
  
@@ -99,7 +99,7 @@ Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
        if (!felix) {
                err = -ENOMEM;
                dev_err(&pdev->dev, "Failed to allocate driver memory\n");
-@@ -577,11 +577,9 @@ static int felix_pci_probe(struct pci_de
+@@ -532,11 +532,9 @@ static int felix_pci_probe(struct pci_de
        return 0;
  
  err_register_ds:
@@ -111,7 +111,7 @@ Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
  err_dma:
        pci_disable_device(pdev);
  err_pci_enable:
-@@ -596,9 +594,6 @@ static void felix_pci_remove(struct pci_
+@@ -551,9 +549,6 @@ static void felix_pci_remove(struct pci_
  
        dsa_unregister_switch(felix->ds);
  
index af80b9f666cecb260f80aaf032b93707b5f4e01f..0b4cb969550c65325e7c39ff32fb1d4a73954162 100644 (file)
@@ -14,7 +14,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
 
 --- a/drivers/net/ethernet/mscc/ocelot.c
 +++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -2338,6 +2338,20 @@ void ocelot_set_cpu_port(struct ocelot *
+@@ -2342,6 +2342,20 @@ void ocelot_set_cpu_port(struct ocelot *
  }
  EXPORT_SYMBOL(ocelot_set_cpu_port);
  
@@ -35,7 +35,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
  int ocelot_init(struct ocelot *ocelot)
  {
        char queue_name[32];
-@@ -2475,6 +2489,13 @@ int ocelot_init(struct ocelot *ocelot)
+@@ -2479,6 +2493,13 @@ int ocelot_init(struct ocelot *ocelot)
                                "Timestamp initialization failed\n");
                        return ret;
                }
@@ -49,7 +49,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
        }
  
        return 0;
-@@ -2489,6 +2510,8 @@ void ocelot_deinit(struct ocelot *ocelot
+@@ -2493,6 +2514,8 @@ void ocelot_deinit(struct ocelot *ocelot
        cancel_delayed_work(&ocelot->stats_work);
        destroy_workqueue(ocelot->stats_queue);
        mutex_destroy(&ocelot->stats_lock);
index 069c518389c26ca5bbba58f437029a4a389d5562..f2d69b6333424832d6da7d9eb56c44e82ecd1d53 100644 (file)
@@ -128,7 +128,7 @@ Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
 
 --- a/drivers/net/ethernet/mscc/ocelot.c
 +++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -2292,6 +2292,18 @@ void ocelot_set_cpu_port(struct ocelot *
+@@ -2296,6 +2296,18 @@ void ocelot_set_cpu_port(struct ocelot *
                         enum ocelot_tag_prefix injection,
                         enum ocelot_tag_prefix extraction)
  {
diff --git a/target/linux/layerscape/patches-5.4/701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch b/target/linux/layerscape/patches-5.4/701-net-0368-Revert-net-dsa-felix-Add-PCS-operations-for-PHYLINK.patch
deleted file mode 100644 (file)
index ea01a8b..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-From 9ee918eb911853c7b46cd84779d857988366e845 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:30:24 +0200
-Subject: [PATCH] Revert "net: dsa: felix: Add PCS operations for PHYLINK"
-
-This reverts commit 1082a3ef9e832cc52c4b0053c7c52453376f4830.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c         |  23 +--
- drivers/net/dsa/ocelot/felix.h         |   7 +-
- drivers/net/dsa/ocelot/felix_vsc9959.c | 292 +--------------------------------
- 3 files changed, 8 insertions(+), 314 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -265,7 +265,7 @@ static int felix_get_ts_info(struct dsa_
- static int felix_init_structs(struct felix *felix, int num_phys_ports)
- {
-       struct ocelot *ocelot = &felix->ocelot;
--      resource_size_t switch_base;
-+      resource_size_t base;
-       int port, i, err;
-       ocelot->num_phys_ports = num_phys_ports;
-@@ -281,8 +281,7 @@ static int felix_init_structs(struct fel
-       ocelot->ops             = felix->info->ops;
-       ocelot->quirks          = felix->info->quirks;
--      switch_base = pci_resource_start(felix->pdev,
--                                       felix->info->switch_pci_bar);
-+      base = pci_resource_start(felix->pdev, felix->info->pci_bar);
-       for (i = 0; i < TARGET_MAX; i++) {
-               struct regmap *target;
-@@ -293,8 +292,8 @@ static int felix_init_structs(struct fel
-               res = &felix->info->target_io_res[i];
-               res->flags = IORESOURCE_MEM;
--              res->start += switch_base;
--              res->end += switch_base;
-+              res->start += base;
-+              res->end += base;
-               target = ocelot_regmap_init(ocelot, res);
-               if (IS_ERR(target)) {
-@@ -328,8 +327,8 @@ static int felix_init_structs(struct fel
-               res = &felix->info->port_io_res[port];
-               res->flags = IORESOURCE_MEM;
--              res->start += switch_base;
--              res->end += switch_base;
-+              res->start += base;
-+              res->end += base;
-               port_regs = devm_ioremap_resource(ocelot->dev, res);
-               if (IS_ERR(port_regs)) {
-@@ -343,12 +342,6 @@ static int felix_init_structs(struct fel
-               ocelot->ports[port] = ocelot_port;
-       }
--      if (felix->info->mdio_bus_alloc) {
--              err = felix->info->mdio_bus_alloc(ocelot);
--              if (err < 0)
--                      return err;
--      }
--
-       return 0;
- }
-@@ -384,10 +377,6 @@ static int felix_setup(struct dsa_switch
- static void felix_teardown(struct dsa_switch *ds)
- {
-       struct ocelot *ocelot = ds->priv;
--      struct felix *felix = ocelot_to_felix(ocelot);
--
--      if (felix->imdio)
--              mdiobus_unregister(felix->imdio);
-       /* stop workqueue thread */
-       ocelot_deinit(ocelot);
---- a/drivers/net/dsa/ocelot/felix.h
-+++ b/drivers/net/dsa/ocelot/felix.h
-@@ -10,7 +10,6 @@
- struct felix_info {
-       struct resource                 *target_io_res;
-       struct resource                 *port_io_res;
--      struct resource                 *imdio_res;
-       const struct reg_field          *regfields;
-       const u32 *const                *map;
-       const struct ocelot_ops         *ops;
-@@ -18,10 +17,8 @@ struct felix_info {
-       const struct ocelot_stat_layout *stats_layout;
-       unsigned int                    num_stats;
-       int                             num_ports;
--      int                             switch_pci_bar;
--      int                             imdio_pci_bar;
-+      int                             pci_bar;
-       unsigned long                   quirks;
--      int (*mdio_bus_alloc)(struct ocelot *ocelot);
- };
- extern struct felix_info              felix_info_vsc9959;
-@@ -36,8 +33,6 @@ struct felix {
-       struct pci_dev                  *pdev;
-       struct felix_info               *info;
-       struct ocelot                   ocelot;
--      struct mii_bus                  *imdio;
--      struct phy_device               **pcs;
- };
- #endif
---- a/drivers/net/dsa/ocelot/felix_vsc9959.c
-+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
-@@ -2,7 +2,6 @@
- /* Copyright 2017 Microsemi Corporation
-  * Copyright 2018-2019 NXP Semiconductors
-  */
--#include <linux/fsl/enetc_mdio.h>
- #include <soc/mscc/ocelot_sys.h>
- #include <soc/mscc/ocelot.h>
- #include <linux/iopoll.h>
-@@ -391,15 +390,6 @@ static struct resource vsc9959_port_io_r
-       },
- };
--/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
-- * SGMII/QSGMII MAC PCS can be found.
-- */
--static struct resource vsc9959_imdio_res = {
--      .start          = 0x8030,
--      .end            = 0x8040,
--      .name           = "imdio",
--};
--
- static const struct reg_field vsc9959_regfields[] = {
-       [ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 6, 6),
-       [ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 5),
-@@ -579,291 +569,13 @@ static int vsc9959_reset(struct ocelot *
-       return 0;
- }
--void vsc9959_pcs_validate(struct ocelot *ocelot, int port,
--                        unsigned long *supported,
--                        struct phylink_link_state *state)
--{
--      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
--
--      if (state->interface != PHY_INTERFACE_MODE_NA &&
--          state->interface != PHY_INTERFACE_MODE_GMII &&
--          state->interface != PHY_INTERFACE_MODE_SGMII &&
--          state->interface != PHY_INTERFACE_MODE_QSGMII &&
--          state->interface != PHY_INTERFACE_MODE_USXGMII) {
--              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
--              return;
--      }
--
--      /* No half-duplex. */
--      phylink_set_port_modes(mask);
--      phylink_set(mask, Autoneg);
--      phylink_set(mask, Pause);
--      phylink_set(mask, Asym_Pause);
--      phylink_set(mask, 10baseT_Full);
--      phylink_set(mask, 100baseT_Full);
--      phylink_set(mask, 1000baseT_Full);
--      phylink_set(mask, 1000baseX_Full);
--      phylink_set(mask, 2500baseT_Full);
--      phylink_set(mask, 2500baseX_Full);
--      phylink_set(mask, 1000baseKX_Full);
--
--      bitmap_and(supported, supported, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--      bitmap_and(state->advertising, state->advertising, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--}
--
--static void vsc9959_pcs_an_restart(struct ocelot *ocelot, int port)
--{
--      struct felix *felix = ocelot_to_felix(ocelot);
--      struct phy_device *pcs = felix->pcs[port];
--
--      if (!pcs)
--              return;
--
--      phy_set_bits(pcs, MII_BMCR, BMCR_ANRESTART);
--}
--
--static void vsc9959_pcs_init_sgmii(struct phy_device *pcs,
--                                 unsigned int link_an_mode,
--                                 const struct phylink_link_state *state)
--{
--      /* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
--       * for the MAC PCS in order to acknowledge the AN.
--       */
--      phy_write(pcs, MII_ADVERTISE, ADVERTISE_SGMII | ADVERTISE_LPACK);
--
--      /* Set to SGMII mode, use AN */
--      phy_write(pcs, ENETC_PCS_IF_MODE, ENETC_PCS_IF_MODE_SGMII_AN);
--
--      /* Adjust link timer for SGMII */
--      phy_write(pcs, ENETC_PCS_LINK_TIMER1, ENETC_PCS_LINK_TIMER1_VAL);
--      phy_write(pcs, ENETC_PCS_LINK_TIMER2, ENETC_PCS_LINK_TIMER2_VAL);
--
--      phy_write(pcs, MII_BMCR, BMCR_SPEED1000 |
--                               BMCR_FULLDPLX |
--                               BMCR_ANENABLE);
--}
--
--#define ADVERTISE_USXGMII_FDX         BIT(12)
--
--static void vsc9959_pcs_init_sxgmii(struct phy_device *pcs,
--                                  unsigned int link_an_mode,
--                                  const struct phylink_link_state *state)
--{
--      /* Configure device ability for the USXGMII Replicator */
--      phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_ADVERTISE,
--                    ADVERTISE_SGMII |
--                    ADVERTISE_LPACK |
--                    ADVERTISE_USXGMII_FDX);
--}
--
--static void vsc9959_pcs_init(struct ocelot *ocelot, int port,
--                           unsigned int link_an_mode,
--                           const struct phylink_link_state *state)
--{
--      struct felix *felix = ocelot_to_felix(ocelot);
--      struct phy_device *pcs = felix->pcs[port];
--
--      if (!pcs)
--              return;
--
--      if (link_an_mode == MLO_AN_FIXED) {
--              phydev_err(pcs, "Fixed modes are not yet supported.\n");
--              return;
--      }
--
--      pcs->interface = state->interface;
--      if (pcs->interface == PHY_INTERFACE_MODE_USXGMII)
--              pcs->is_c45 = true;
--      else
--              pcs->is_c45 = false;
--
--      /* The PCS does not implement the BMSR register fully, so capability
--       * detection via genphy_read_abilities does not work. Since we can get
--       * the PHY config word from the LPA register though, there is still
--       * value in using the generic phy_resolve_aneg_linkmode function. So
--       * populate the supported and advertising link modes manually here.
--       */
--      linkmode_set_bit_array(phy_basic_ports_array,
--                             ARRAY_SIZE(phy_basic_ports_array),
--                             pcs->supported);
--      linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, pcs->supported);
--      linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, pcs->supported);
--      linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pcs->supported);
--      linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, pcs->supported);
--      phy_advertise_supported(pcs);
--
--      switch (pcs->interface) {
--      case PHY_INTERFACE_MODE_SGMII:
--      case PHY_INTERFACE_MODE_QSGMII:
--              vsc9959_pcs_init_sgmii(pcs, link_an_mode, state);
--              break;
--      case PHY_INTERFACE_MODE_USXGMII:
--              vsc9959_pcs_init_sxgmii(pcs, link_an_mode, state);
--              break;
--      default:
--              dev_err(ocelot->dev, "Unsupported link mode %s\n",
--                      phy_modes(pcs->interface));
--      }
--}
--
--static void vsc9959_pcs_link_state(struct ocelot *ocelot, int port,
--                                 struct phylink_link_state *state)
--{
--      struct felix *felix = ocelot_to_felix(ocelot);
--      struct phy_device *pcs = felix->pcs[port];
--      int err;
--
--      if (!pcs)
--              return;
--
--      /* Reading PCS status not yet supported for USXGMII */
--      if (pcs->is_c45) {
--              state->link = 1;
--              return;
--      }
--
--      pcs->speed = SPEED_UNKNOWN;
--      pcs->duplex = DUPLEX_UNKNOWN;
--      pcs->pause = 0;
--      pcs->asym_pause = 0;
--
--      err = genphy_update_link(pcs);
--      if (err < 0)
--              return;
--
--      if (pcs->autoneg_complete) {
--              u16 lpa = phy_read(pcs, MII_LPA);
--
--              switch (state->interface) {
--              case PHY_INTERFACE_MODE_SGMII:
--              case PHY_INTERFACE_MODE_QSGMII:
--                      mii_lpa_to_linkmode_lpa_sgmii(pcs->lp_advertising, lpa);
--                      break;
--              default:
--                      return;
--              }
--
--              phy_resolve_aneg_linkmode(pcs);
--      }
--
--      state->an_complete = pcs->autoneg_complete;
--      state->an_enabled = pcs->autoneg;
--      state->link = pcs->link;
--      state->duplex = pcs->duplex;
--      state->speed = pcs->speed;
--      /* SGMII AN does not negotiate flow control, but that's ok,
--       * since phylink already knows that, and does:
--       *      link_state.pause |= pl->phy_state.pause;
--       */
--      state->pause = pcs->pause;
--
--      dev_dbg(ocelot->dev,
--              "%s: mode=%s/%s/%s adv=%*pb lpa=%*pb link=%u an_enabled=%u an_complete=%u\n",
--              __func__,
--              phy_modes(state->interface),
--              phy_speed_to_str(state->speed),
--              phy_duplex_to_str(state->duplex),
--              __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
--              __ETHTOOL_LINK_MODE_MASK_NBITS, state->lp_advertising,
--              state->link, state->an_enabled, state->an_complete);
--}
--
- static const struct ocelot_ops vsc9959_ops = {
-       .reset                  = vsc9959_reset,
--      .pcs_init               = vsc9959_pcs_init,
--      .pcs_an_restart         = vsc9959_pcs_an_restart,
--      .pcs_link_state         = vsc9959_pcs_link_state,
--      .pcs_validate           = vsc9959_pcs_validate,
- };
--static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
--{
--      struct felix *felix = ocelot_to_felix(ocelot);
--      struct enetc_mdio_priv *mdio_priv;
--      struct device *dev = ocelot->dev;
--      resource_size_t imdio_base;
--      void __iomem *imdio_regs;
--      struct resource *res;
--      struct enetc_hw *hw;
--      struct mii_bus *bus;
--      int port;
--      int rc;
--
--      felix->pcs = devm_kcalloc(dev, felix->info->num_ports,
--                                sizeof(struct phy_device),
--                                GFP_KERNEL);
--      if (!felix->pcs) {
--              dev_err(dev, "failed to allocate array for PCS PHYs\n");
--              return -ENOMEM;
--      }
--
--      imdio_base = pci_resource_start(felix->pdev,
--                                      felix->info->imdio_pci_bar);
--
--      res = felix->info->imdio_res;
--      res->flags = IORESOURCE_MEM;
--      res->start += imdio_base;
--      res->end += imdio_base;
--
--      imdio_regs = devm_ioremap_resource(dev, res);
--      if (IS_ERR(imdio_regs)) {
--              dev_err(dev, "failed to map internal MDIO registers\n");
--              return PTR_ERR(imdio_regs);
--      }
--
--      hw = enetc_hw_alloc(dev, imdio_regs);
--      if (IS_ERR(hw)) {
--              dev_err(dev, "failed to allocate ENETC HW structure\n");
--              return PTR_ERR(hw);
--      }
--
--      bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
--      if (!bus)
--              return -ENOMEM;
--
--      bus->name = "VSC9959 internal MDIO bus";
--      bus->read = enetc_mdio_read;
--      bus->write = enetc_mdio_write;
--      bus->parent = dev;
--      mdio_priv = bus->priv;
--      mdio_priv->hw = hw;
--      /* This gets added to imdio_regs, which already maps addresses
--       * starting with the proper offset.
--       */
--      mdio_priv->mdio_base = 0;
--      snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
--
--      /* Needed in order to initialize the bus mutex lock */
--      rc = mdiobus_register(bus);
--      if (rc < 0) {
--              dev_err(dev, "failed to register MDIO bus\n");
--              return rc;
--      }
--
--      felix->imdio = bus;
--
--      for (port = 0; port < felix->info->num_ports; port++) {
--              struct phy_device *pcs;
--              bool is_c45 = false;
--
--              pcs = get_phy_device(felix->imdio, port, is_c45);
--              if (IS_ERR(pcs))
--                      continue;
--
--              felix->pcs[port] = pcs;
--
--              dev_info(dev, "Found PCS at internal MDIO address %d\n", port);
--      }
--
--      return 0;
--}
--
- struct felix_info felix_info_vsc9959 = {
-       .target_io_res          = vsc9959_target_io_res,
-       .port_io_res            = vsc9959_port_io_res,
--      .imdio_res              = &vsc9959_imdio_res,
-       .regfields              = vsc9959_regfields,
-       .map                    = vsc9959_regmap,
-       .ops                    = &vsc9959_ops,
-@@ -871,8 +583,6 @@ struct felix_info felix_info_vsc9959 = {
-       .num_stats              = ARRAY_SIZE(vsc9959_stats_layout),
-       .shared_queue_sz        = 128 * 1024,
-       .num_ports              = 6,
--      .switch_pci_bar         = 4,
--      .imdio_pci_bar          = 0,
-+      .pci_bar                = 4,
-       .quirks                 = OCELOT_PCS_PERFORMS_RATE_ADAPTATION,
--      .mdio_bus_alloc         = vsc9959_mdio_bus_alloc,
- };
diff --git a/target/linux/layerscape/patches-5.4/701-net-0369-Revert-net-mscc-ocelot-introduce-more-focused-PCS-op.patch b/target/linux/layerscape/patches-5.4/701-net-0369-Revert-net-mscc-ocelot-introduce-more-focused-PCS-op.patch
deleted file mode 100644 (file)
index 9ba2030..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-From e1aa2a770cc5f4d46693bb491ed2ca7f066c3585 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:30:41 +0200
-Subject: [PATCH] Revert "net: mscc: ocelot: introduce more focused PCS ops for
- PHYLINK"
-
-This reverts commit 423c8b04007c85907f8f514de459ebc8541f0a54.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/mscc/ocelot.c       | 36 ++++++++++++++++++++++++--------
- drivers/net/ethernet/mscc/ocelot_board.c | 35 +------------------------------
- include/soc/mscc/ocelot.h                | 12 +++--------
- 3 files changed, 31 insertions(+), 52 deletions(-)
-
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -410,25 +410,43 @@ void ocelot_phylink_validate(struct ocel
-                            unsigned long *supported,
-                            struct phylink_link_state *state)
- {
--      if (ocelot->ops->pcs_validate)
--              ocelot->ops->pcs_validate(ocelot, port, supported, state);
-+      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-+
-+      if (state->interface != PHY_INTERFACE_MODE_NA &&
-+          state->interface != PHY_INTERFACE_MODE_GMII &&
-+          state->interface != PHY_INTERFACE_MODE_SGMII &&
-+          state->interface != PHY_INTERFACE_MODE_QSGMII) {
-+              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-+              return;
-+      }
-+
-+      /* No half-duplex. */
-+      phylink_set_port_modes(mask);
-+      phylink_set(mask, Autoneg);
-+      phylink_set(mask, Pause);
-+      phylink_set(mask, Asym_Pause);
-+      phylink_set(mask, 10baseT_Full);
-+      phylink_set(mask, 100baseT_Full);
-+      phylink_set(mask, 1000baseT_Full);
-+      phylink_set(mask, 2500baseT_Full);
-+
-+      bitmap_and(supported, supported, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
-+      bitmap_and(state->advertising, state->advertising, mask,
-+                 __ETHTOOL_LINK_MODE_MASK_NBITS);
- }
- EXPORT_SYMBOL(ocelot_phylink_validate);
- void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
-                                     struct phylink_link_state *state)
- {
--      if (ocelot->ops->pcs_link_state)
--              ocelot->ops->pcs_link_state(ocelot, port, state);
--      else
--              state->link = 1;
-+      state->link = 1;
- }
- EXPORT_SYMBOL(ocelot_phylink_mac_pcs_get_state);
- void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port)
- {
--      if (ocelot->ops->pcs_an_restart)
--              ocelot->ops->pcs_an_restart(ocelot, port);
-+      /* Not supported */
- }
- EXPORT_SYMBOL(ocelot_phylink_mac_an_restart);
-@@ -472,7 +490,7 @@ void ocelot_phylink_mac_config(struct oc
-       ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-       if (ocelot->ops->pcs_init)
--              ocelot->ops->pcs_init(ocelot, port, link_an_mode, state);
-+              ocelot->ops->pcs_init(ocelot, port);
-       /* Enable MAC module */
-       ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA |
---- a/drivers/net/ethernet/mscc/ocelot_board.c
-+++ b/drivers/net/ethernet/mscc/ocelot_board.c
-@@ -212,9 +212,7 @@ static const struct of_device_id mscc_oc
- };
- MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
--static void ocelot_port_pcs_init(struct ocelot *ocelot, int port,
--                               unsigned int link_an_mode,
--                               const struct phylink_link_state *state)
-+static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
- {
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
-@@ -237,36 +235,6 @@ static void ocelot_port_pcs_init(struct
-       ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
- }
--void ocelot_port_pcs_validate(struct ocelot *ocelot, int port,
--                            unsigned long *supported,
--                            struct phylink_link_state *state)
--{
--      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
--
--      if (state->interface != PHY_INTERFACE_MODE_NA &&
--          state->interface != PHY_INTERFACE_MODE_GMII &&
--          state->interface != PHY_INTERFACE_MODE_SGMII &&
--          state->interface != PHY_INTERFACE_MODE_QSGMII) {
--              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
--              return;
--      }
--
--      /* No half-duplex. */
--      phylink_set_port_modes(mask);
--      phylink_set(mask, Autoneg);
--      phylink_set(mask, Pause);
--      phylink_set(mask, Asym_Pause);
--      phylink_set(mask, 10baseT_Full);
--      phylink_set(mask, 100baseT_Full);
--      phylink_set(mask, 1000baseT_Full);
--      phylink_set(mask, 2500baseT_Full);
--
--      bitmap_and(supported, supported, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--      bitmap_and(state->advertising, state->advertising, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--}
--
- static int ocelot_reset(struct ocelot *ocelot)
- {
-       int retries = 100;
-@@ -292,7 +260,6 @@ static int ocelot_reset(struct ocelot *o
- static const struct ocelot_ops ocelot_ops = {
-       .pcs_init               = ocelot_port_pcs_init,
--      .pcs_validate           = ocelot_port_pcs_validate,
-       .reset                  = ocelot_reset,
- };
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -412,15 +412,7 @@ enum {
- struct ocelot;
- struct ocelot_ops {
--      void (*pcs_init)(struct ocelot *ocelot, int port,
--                       unsigned int link_an_mode,
--                       const struct phylink_link_state *state);
--      void (*pcs_an_restart)(struct ocelot *ocelot, int port);
--      void (*pcs_link_state)(struct ocelot *ocelot, int port,
--                             struct phylink_link_state *state);
--      void (*pcs_validate)(struct ocelot *ocelot, int port,
--                           unsigned long *supported,
--                           struct phylink_link_state *state);
-+      void (*pcs_init)(struct ocelot *ocelot, int port);
-       int (*reset)(struct ocelot *ocelot);
- };
-@@ -487,6 +479,8 @@ struct ocelot {
-       struct mutex                    ptp_lock;
-       /* Protects the PTP clock */
-       spinlock_t                      ptp_clock_lock;
-+
-+      void (*port_pcs_init)(struct ocelot_port *port);
- };
- #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri))
diff --git a/target/linux/layerscape/patches-5.4/701-net-0370-Revert-net-mscc-ocelot-convert-to-PHYLINK.patch b/target/linux/layerscape/patches-5.4/701-net-0370-Revert-net-mscc-ocelot-convert-to-PHYLINK.patch
deleted file mode 100644 (file)
index 1423104..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-From 74e550d54d7c8142aefc06d1f00c506cd9039b6d Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:30:48 +0200
-Subject: [PATCH] Revert "net: mscc: ocelot: convert to PHYLINK"
-
-This reverts commit e51cc023c37902e10d1e0109ff0c6ddcce3d5c03.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c           |  65 ++++---------
- drivers/net/ethernet/mscc/Kconfig        |   2 +-
- drivers/net/ethernet/mscc/ocelot.c       | 150 ++++++++++++++----------------
- drivers/net/ethernet/mscc/ocelot.h       |  13 ++-
- drivers/net/ethernet/mscc/ocelot_board.c | 154 ++++---------------------------
- include/soc/mscc/ocelot.h                |  22 +----
- 6 files changed, 117 insertions(+), 289 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -58,6 +58,14 @@ static int felix_set_ageing_time(struct
-       return 0;
- }
-+static void felix_adjust_link(struct dsa_switch *ds, int port,
-+                            struct phy_device *phydev)
-+{
-+      struct ocelot *ocelot = ds->priv;
-+
-+      ocelot_adjust_link(ocelot, port, phydev);
-+}
-+
- static int felix_fdb_dump(struct dsa_switch *ds, int port,
-                         dsa_fdb_dump_cb_t *cb, void *data)
- {
-@@ -177,59 +185,21 @@ static int felix_tsn_enable(struct dsa_p
- }
- #endif
--static void felix_phylink_validate(struct dsa_switch *ds, int port,
--                                 unsigned long *supported,
--                                 struct phylink_link_state *state)
-+static int felix_port_enable(struct dsa_switch *ds, int port,
-+                           struct phy_device *phy)
- {
-       struct ocelot *ocelot = ds->priv;
--      ocelot_phylink_validate(ocelot, port, supported, state);
--}
--
--static int felix_phylink_mac_pcs_get_state(struct dsa_switch *ds, int port,
--                                         struct phylink_link_state *state)
--{
--      struct ocelot *ocelot = ds->priv;
--
--      ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
-+      ocelot_port_enable(ocelot, port, phy);
-       return 0;
- }
--static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
--                                   unsigned int link_an_mode,
--                                   const struct phylink_link_state *state)
--{
--      struct ocelot *ocelot = ds->priv;
--
--      ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
--}
--
--static void felix_phylink_mac_an_restart(struct dsa_switch *ds, int port)
--{
--      struct ocelot *ocelot = ds->priv;
--
--      ocelot_phylink_mac_an_restart(ocelot, port);
--}
--
--static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,
--                                      unsigned int link_an_mode,
--                                      phy_interface_t interface)
--{
--      struct ocelot *ocelot = ds->priv;
--
--      ocelot_phylink_mac_link_down(ocelot, port, link_an_mode, interface);
--}
--
--static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
--                                    unsigned int link_an_mode,
--                                    phy_interface_t interface,
--                                    struct phy_device *phydev)
-+static void felix_port_disable(struct dsa_switch *ds, int port)
- {
-       struct ocelot *ocelot = ds->priv;
--      ocelot_phylink_mac_link_up(ocelot, port, link_an_mode, interface,
--                                 phydev);
-+      return ocelot_port_disable(ocelot, port);
- }
- static void felix_get_strings(struct dsa_switch *ds, int port,
-@@ -447,12 +417,9 @@ static const struct dsa_switch_ops felix
-       .get_ethtool_stats      = felix_get_ethtool_stats,
-       .get_sset_count         = felix_get_sset_count,
-       .get_ts_info            = felix_get_ts_info,
--      .phylink_validate       = felix_phylink_validate,
--      .phylink_mac_link_state = felix_phylink_mac_pcs_get_state,
--      .phylink_mac_config     = felix_phylink_mac_config,
--      .phylink_mac_an_restart = felix_phylink_mac_an_restart,
--      .phylink_mac_link_down  = felix_phylink_mac_link_down,
--      .phylink_mac_link_up    = felix_phylink_mac_link_up,
-+      .adjust_link            = felix_adjust_link,
-+      .port_enable            = felix_port_enable,
-+      .port_disable           = felix_port_disable,
-       .port_fdb_dump          = felix_fdb_dump,
-       .port_fdb_add           = felix_fdb_add,
-       .port_fdb_del           = felix_fdb_del,
---- a/drivers/net/ethernet/mscc/Kconfig
-+++ b/drivers/net/ethernet/mscc/Kconfig
-@@ -15,7 +15,7 @@ config MSCC_OCELOT_SWITCH
-       tristate "Ocelot switch driver"
-       depends on NET_SWITCHDEV
-       depends on HAS_IOMEM
--      select PHYLINK
-+      select PHYLIB
-       select REGMAP_MMIO
-       help
-         This driver supports the Ocelot network switch device.
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -13,7 +13,7 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/netdevice.h>
--#include <linux/phylink.h>
-+#include <linux/phy.h>
- #include <linux/ptp_clock_kernel.h>
- #include <linux/skbuff.h>
- #include <linux/iopoll.h>
-@@ -406,66 +406,18 @@ static u16 ocelot_wm_enc(u16 value)
-       return value;
- }
--void ocelot_phylink_validate(struct ocelot *ocelot, int port,
--                           unsigned long *supported,
--                           struct phylink_link_state *state)
--{
--      __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
--
--      if (state->interface != PHY_INTERFACE_MODE_NA &&
--          state->interface != PHY_INTERFACE_MODE_GMII &&
--          state->interface != PHY_INTERFACE_MODE_SGMII &&
--          state->interface != PHY_INTERFACE_MODE_QSGMII) {
--              bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
--              return;
--      }
--
--      /* No half-duplex. */
--      phylink_set_port_modes(mask);
--      phylink_set(mask, Autoneg);
--      phylink_set(mask, Pause);
--      phylink_set(mask, Asym_Pause);
--      phylink_set(mask, 10baseT_Full);
--      phylink_set(mask, 100baseT_Full);
--      phylink_set(mask, 1000baseT_Full);
--      phylink_set(mask, 2500baseT_Full);
--
--      bitmap_and(supported, supported, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--      bitmap_and(state->advertising, state->advertising, mask,
--                 __ETHTOOL_LINK_MODE_MASK_NBITS);
--}
--EXPORT_SYMBOL(ocelot_phylink_validate);
--
--void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
--                                    struct phylink_link_state *state)
--{
--      state->link = 1;
--}
--EXPORT_SYMBOL(ocelot_phylink_mac_pcs_get_state);
--
--void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port)
--{
--      /* Not supported */
--}
--EXPORT_SYMBOL(ocelot_phylink_mac_an_restart);
--
--void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
--                             unsigned int link_an_mode,
--                             const struct phylink_link_state *state)
-+void ocelot_adjust_link(struct ocelot *ocelot, int port,
-+                      struct phy_device *phydev)
- {
-       int speed, mac_speed, mac_mode = DEV_MAC_MODE_CFG_FDX_ENA;
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
--      u32 mac_fc_cfg;
-       if (ocelot->quirks & OCELOT_PCS_PERFORMS_RATE_ADAPTATION)
-               speed = SPEED_1000;
-       else
--              speed = state->speed;
-+              speed = phydev->speed;
-       switch (speed) {
--      case SPEED_UNKNOWN:
--              return;
-       case SPEED_10:
-               mac_speed = OCELOT_SPEED_10;
-               break;
-@@ -481,11 +433,16 @@ void ocelot_phylink_mac_config(struct oc
-               mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       default:
--              dev_err(ocelot->dev, "Unsupported speed on port %d: %d\n",
-+              dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
-                       port, speed);
-               return;
-       }
-+      phy_print_status(phydev);
-+
-+      if (!phydev->link)
-+              return;
-+
-       /* Only full duplex supported for now */
-       ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-@@ -512,36 +469,27 @@ void ocelot_phylink_mac_config(struct oc
-                        QSYS_SWITCH_PORT_MODE, port);
-       /* Flow control */
--      mac_fc_cfg = SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed);
--      if (state->pause & MLO_PAUSE_RX)
--              mac_fc_cfg |= SYS_MAC_FC_CFG_RX_FC_ENA;
--      if (state->pause & MLO_PAUSE_TX)
--              mac_fc_cfg |= SYS_MAC_FC_CFG_TX_FC_ENA |
--                            SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
--                            SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
--                            SYS_MAC_FC_CFG_ZERO_PAUSE_ENA;
--      ocelot_write_rix(ocelot, mac_fc_cfg, SYS_MAC_FC_CFG, port);
--
-+      ocelot_write_rix(ocelot, SYS_MAC_FC_CFG_PAUSE_VAL_CFG(0xffff) |
-+                       SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
-+                       SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
-+                       SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
-+                       SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed),
-+                       SYS_MAC_FC_CFG, port);
-       ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
- }
--EXPORT_SYMBOL(ocelot_phylink_mac_config);
-+EXPORT_SYMBOL(ocelot_adjust_link);
--void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
--                                unsigned int link_an_mode,
--                                phy_interface_t interface)
-+static void ocelot_port_adjust_link(struct net_device *dev)
- {
--      struct ocelot_port *ocelot_port = ocelot->ports[port];
-+      struct ocelot_port_private *priv = netdev_priv(dev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
--      ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
--      ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
--                     QSYS_SWITCH_PORT_MODE, port);
-+      ocelot_adjust_link(ocelot, port, dev->phydev);
- }
--EXPORT_SYMBOL(ocelot_phylink_mac_link_down);
--void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
--                              unsigned int link_an_mode,
--                              phy_interface_t interface,
--                              struct phy_device *phy)
-+void ocelot_port_enable(struct ocelot *ocelot, int port,
-+                      struct phy_device *phy)
- {
-       /* Enable receiving frames on the port, and activate auto-learning of
-        * MAC addresses.
-@@ -551,22 +499,62 @@ void ocelot_phylink_mac_link_up(struct o
-                        ANA_PORT_PORT_CFG_PORTID_VAL(port),
-                        ANA_PORT_PORT_CFG, port);
- }
--EXPORT_SYMBOL(ocelot_phylink_mac_link_up);
-+EXPORT_SYMBOL(ocelot_port_enable);
- static int ocelot_port_open(struct net_device *dev)
- {
-       struct ocelot_port_private *priv = netdev_priv(dev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+      int err;
-+
-+      if (priv->serdes) {
-+              err = phy_set_mode_ext(priv->serdes, PHY_MODE_ETHERNET,
-+                                     priv->phy_mode);
-+              if (err) {
-+                      netdev_err(dev, "Could not set mode of SerDes\n");
-+                      return err;
-+              }
-+      }
-+
-+      err = phy_connect_direct(dev, priv->phy, &ocelot_port_adjust_link,
-+                               priv->phy_mode);
-+      if (err) {
-+              netdev_err(dev, "Could not attach to PHY\n");
-+              return err;
-+      }
--      phylink_start(priv->phylink);
-+      dev->phydev = priv->phy;
-+
-+      phy_attached_info(priv->phy);
-+      phy_start(priv->phy);
-+
-+      ocelot_port_enable(ocelot, port, priv->phy);
-       return 0;
- }
-+void ocelot_port_disable(struct ocelot *ocelot, int port)
-+{
-+      struct ocelot_port *ocelot_port = ocelot->ports[port];
-+
-+      ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
-+      ocelot_rmw_rix(ocelot, 0, QSYS_SWITCH_PORT_MODE_PORT_ENA,
-+                     QSYS_SWITCH_PORT_MODE, port);
-+}
-+EXPORT_SYMBOL(ocelot_port_disable);
-+
- static int ocelot_port_stop(struct net_device *dev)
- {
-       struct ocelot_port_private *priv = netdev_priv(dev);
-+      struct ocelot *ocelot = priv->port.ocelot;
-+      int port = priv->chip_port;
-+
-+      phy_disconnect(priv->phy);
-+
-+      dev->phydev = NULL;
--      phylink_stop(priv->phylink);
-+      ocelot_port_disable(ocelot, port);
-       return 0;
- }
-@@ -2263,7 +2251,8 @@ void ocelot_init_port(struct ocelot *oce
- EXPORT_SYMBOL(ocelot_init_port);
- int ocelot_probe_port(struct ocelot *ocelot, u8 port,
--                    void __iomem *regs)
-+                    void __iomem *regs,
-+                    struct phy_device *phy)
- {
-       struct ocelot_port_private *priv;
-       struct ocelot_port *ocelot_port;
-@@ -2276,6 +2265,7 @@ int ocelot_probe_port(struct ocelot *oce
-       SET_NETDEV_DEV(dev, ocelot->dev);
-       priv = netdev_priv(dev);
-       priv->dev = dev;
-+      priv->phy = phy;
-       priv->chip_port = port;
-       ocelot_port = &priv->port;
-       ocelot_port->ocelot = ocelot;
---- a/drivers/net/ethernet/mscc/ocelot.h
-+++ b/drivers/net/ethernet/mscc/ocelot.h
-@@ -12,7 +12,8 @@
- #include <linux/etherdevice.h>
- #include <linux/if_vlan.h>
- #include <linux/net_tstamp.h>
--#include <linux/phylink.h>
-+#include <linux/phy.h>
-+#include <linux/phy/phy.h>
- #include <linux/platform_device.h>
- #include <linux/ptp_clock_kernel.h>
- #include <linux/regmap.h>
-@@ -64,12 +65,14 @@ struct ocelot_multicast {
- struct ocelot_port_private {
-       struct ocelot_port port;
-       struct net_device *dev;
--      struct phylink *phylink;
--      struct phylink_config phylink_config;
-+      struct phy_device *phy;
-       u8 chip_port;
-       u8 vlan_aware;
-+      phy_interface_t phy_mode;
-+      struct phy *serdes;
-+
-       struct ocelot_port_tc tc;
- };
-@@ -80,7 +83,9 @@ void ocelot_port_writel(struct ocelot_po
- #define ocelot_field_read(ocelot, reg, val) regmap_field_read((ocelot)->regfields[(reg)], (val))
- int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops);
--int ocelot_probe_port(struct ocelot *ocelot, u8 port, void __iomem *regs);
-+int ocelot_probe_port(struct ocelot *ocelot, u8 port,
-+                    void __iomem *regs,
-+                    struct phy_device *phy);
- void ocelot_set_cpu_port(struct ocelot *ocelot, int cpu,
-                        enum ocelot_tag_prefix injection,
---- a/drivers/net/ethernet/mscc/ocelot_board.c
-+++ b/drivers/net/ethernet/mscc/ocelot_board.c
-@@ -13,7 +13,6 @@
- #include <linux/mfd/syscon.h>
- #include <linux/skbuff.h>
- #include <net/switchdev.h>
--#include <linux/phy/phy.h>
- #include "ocelot.h"
-@@ -263,91 +262,6 @@ static const struct ocelot_ops ocelot_op
-       .reset                  = ocelot_reset,
- };
--static void ocelot_port_phylink_validate(struct phylink_config *config,
--                                       unsigned long *supported,
--                                       struct phylink_link_state *state)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      ocelot_phylink_validate(ocelot, port, supported, state);
--}
--
--static int
--ocelot_port_phylink_mac_pcs_get_state(struct phylink_config *config,
--                                    struct phylink_link_state *state)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      ocelot_phylink_mac_pcs_get_state(ocelot, port, state);
--
--      return 0;
--}
--
--static void ocelot_port_phylink_mac_an_restart(struct phylink_config *config)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      ocelot_phylink_mac_an_restart(ocelot, port);
--}
--
--static void
--ocelot_port_phylink_mac_config(struct phylink_config *config,
--                             unsigned int link_an_mode,
--                             const struct phylink_link_state *state)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
--}
--
--static void ocelot_port_phylink_mac_link_down(struct phylink_config *config,
--                                            unsigned int link_an_mode,
--                                            phy_interface_t interface)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      return ocelot_phylink_mac_link_down(ocelot, port, link_an_mode,
--                                          interface);
--}
--
--static void ocelot_port_phylink_mac_link_up(struct phylink_config *config,
--                                          unsigned int link_an_mode,
--                                          phy_interface_t interface,
--                                          struct phy_device *phy)
--{
--      struct net_device *ndev = to_net_dev(config->dev);
--      struct ocelot_port_private *priv = netdev_priv(ndev);
--      struct ocelot *ocelot = priv->port.ocelot;
--      int port = priv->chip_port;
--
--      return ocelot_phylink_mac_link_up(ocelot, port, link_an_mode,
--                                        interface, phy);
--}
--
--static const struct phylink_mac_ops ocelot_phylink_ops = {
--      .validate               = ocelot_port_phylink_validate,
--      .mac_link_state         = ocelot_port_phylink_mac_pcs_get_state,
--      .mac_an_restart         = ocelot_port_phylink_mac_an_restart,
--      .mac_config             = ocelot_port_phylink_mac_config,
--      .mac_link_down          = ocelot_port_phylink_mac_link_down,
--      .mac_link_up            = ocelot_port_phylink_mac_link_up,
--};
--
- static int mscc_ocelot_probe(struct platform_device *pdev)
- {
-       struct device_node *np = pdev->dev.of_node;
-@@ -455,6 +369,8 @@ static int mscc_ocelot_probe(struct plat
-       for_each_available_child_of_node(ports, portnp) {
-               struct ocelot_port_private *priv;
-               struct ocelot_port *ocelot_port;
-+              struct device_node *phy_node;
-+              struct phy_device *phy;
-               struct resource *res;
-               struct phy *serdes;
-               void __iomem *regs;
-@@ -473,7 +389,16 @@ static int mscc_ocelot_probe(struct plat
-               if (IS_ERR(regs))
-                       continue;
--              err = ocelot_probe_port(ocelot, port, regs);
-+              phy_node = of_parse_phandle(portnp, "phy-handle", 0);
-+              if (!phy_node)
-+                      continue;
-+
-+              phy = of_phy_find_device(phy_node);
-+              of_node_put(phy_node);
-+              if (!phy)
-+                      continue;
-+
-+              err = ocelot_probe_port(ocelot, port, regs, phy);
-               if (err) {
-                       of_node_put(portnp);
-                       goto out_put_ports;
-@@ -487,7 +412,9 @@ static int mscc_ocelot_probe(struct plat
-               if (phy_mode < 0)
-                       phy_mode = PHY_INTERFACE_MODE_NA;
--              switch (phy_mode) {
-+              priv->phy_mode = phy_mode;
-+
-+              switch (priv->phy_mode) {
-               case PHY_INTERFACE_MODE_NA:
-                       continue;
-               case PHY_INTERFACE_MODE_SGMII:
-@@ -524,41 +451,7 @@ static int mscc_ocelot_probe(struct plat
-                       goto out_put_ports;
-               }
--              if (serdes) {
--                      err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET,
--                                             phy_mode);
--                      if (err) {
--                              dev_err(ocelot->dev,
--                                      "Could not set mode of SerDes\n");
--                              of_node_put(portnp);
--                              goto out_put_ports;
--                      }
--              }
--
--              priv->phylink_config.dev = &priv->dev->dev;
--              priv->phylink_config.type = PHYLINK_NETDEV;
--
--              priv->phylink = phylink_create(&priv->phylink_config,
--                                             of_fwnode_handle(portnp),
--                                             phy_mode, &ocelot_phylink_ops);
--              if (IS_ERR(priv->phylink)) {
--                      dev_err(ocelot->dev,
--                              "Could not create a phylink instance (%ld)\n",
--                              PTR_ERR(priv->phylink));
--                      err = PTR_ERR(priv->phylink);
--                      priv->phylink = NULL;
--                      of_node_put(portnp);
--                      goto out_put_ports;
--              }
--
--              err = phylink_of_phy_connect(priv->phylink, portnp, 0);
--              if (err) {
--                      dev_err(ocelot->dev, "Could not connect to PHY: %d\n",
--                              err);
--                      phylink_destroy(priv->phylink);
--                      of_node_put(portnp);
--                      goto out_put_ports;
--              }
-+              priv->serdes = serdes;
-       }
-       register_netdevice_notifier(&ocelot_netdevice_nb);
-@@ -575,27 +468,12 @@ out_put_ports:
- static int mscc_ocelot_remove(struct platform_device *pdev)
- {
-       struct ocelot *ocelot = platform_get_drvdata(pdev);
--      int port;
-       ocelot_deinit(ocelot);
-       unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
-       unregister_switchdev_notifier(&ocelot_switchdev_nb);
-       unregister_netdevice_notifier(&ocelot_netdevice_nb);
--      for (port = 0; port < ocelot->num_phys_ports; port++) {
--              struct ocelot_port_private *priv;
--
--              priv = container_of(ocelot->ports[port],
--                                  struct ocelot_port_private,
--                                  port);
--
--              if (priv->phylink) {
--                      rtnl_lock();
--                      phylink_destroy(priv->phylink);
--                      rtnl_unlock();
--              }
--      }
--
-       return 0;
- }
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -518,12 +518,17 @@ void ocelot_deinit(struct ocelot *ocelot
- void ocelot_init_port(struct ocelot *ocelot, int port);
- /* DSA callbacks */
-+void ocelot_port_enable(struct ocelot *ocelot, int port,
-+                      struct phy_device *phy);
-+void ocelot_port_disable(struct ocelot *ocelot, int port);
- void ocelot_get_strings(struct ocelot *ocelot, int port, u32 sset, u8 *data);
- void ocelot_get_ethtool_stats(struct ocelot *ocelot, int port, u64 *data);
- int ocelot_get_sset_count(struct ocelot *ocelot, int port, int sset);
- int ocelot_get_ts_info(struct ocelot *ocelot, int port,
-                      struct ethtool_ts_info *info);
- void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs);
-+void ocelot_adjust_link(struct ocelot *ocelot, int port,
-+                      struct phy_device *phydev);
- void ocelot_port_vlan_filtering(struct ocelot *ocelot, int port,
-                               bool vlan_aware);
- void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state);
-@@ -592,21 +597,4 @@ int ocelot_rtag_parse_enable(struct ocel
- int ocelot_dscp_set(struct ocelot *ocelot, int port,
-                   bool enable, const u8 dscp_ix,
-                   struct tsn_qos_switch_dscp_conf *c);
--void ocelot_phylink_validate(struct ocelot *ocelot, int port,
--                           unsigned long *supported,
--                           struct phylink_link_state *state);
--void ocelot_phylink_mac_pcs_get_state(struct ocelot *ocelot, int port,
--                                    struct phylink_link_state *state);
--void ocelot_phylink_mac_an_restart(struct ocelot *ocelot, int port);
--void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
--                             unsigned int link_an_mode,
--                             const struct phylink_link_state *state);
--void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
--                                unsigned int link_an_mode,
--                                phy_interface_t interface);
--void ocelot_phylink_mac_link_up(struct ocelot *ocelot, int port,
--                              unsigned int link_an_mode,
--                              phy_interface_t interface,
--                              struct phy_device *phy);
--
- #endif
diff --git a/target/linux/layerscape/patches-5.4/701-net-0371-Revert-net-mscc-ocelot-do-not-force-Felix-MACs-at-lo.patch b/target/linux/layerscape/patches-5.4/701-net-0371-Revert-net-mscc-ocelot-do-not-force-Felix-MACs-at-lo.patch
deleted file mode 100644 (file)
index 4859d17..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-From 6864e50946bf92f96b8452d1e47765230a276bb0 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:30:58 +0200
-Subject: [PATCH] Revert "net: mscc: ocelot: do not force Felix MACs at lower
- speeds than gigabit"
-
-This reverts commit f3ebad1269aad8a04710e84dc1cd5de485e5fec4.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/dsa/ocelot/felix.c         |  1 -
- drivers/net/dsa/ocelot/felix.h         |  1 -
- drivers/net/dsa/ocelot/felix_vsc9959.c |  1 -
- drivers/net/ethernet/mscc/ocelot.c     | 32 ++++++++++++++------------------
- include/soc/mscc/ocelot.h              |  7 -------
- 5 files changed, 14 insertions(+), 28 deletions(-)
-
---- a/drivers/net/dsa/ocelot/felix.c
-+++ b/drivers/net/dsa/ocelot/felix.c
-@@ -249,7 +249,6 @@ static int felix_init_structs(struct fel
-       ocelot->num_stats       = felix->info->num_stats;
-       ocelot->shared_queue_sz = felix->info->shared_queue_sz;
-       ocelot->ops             = felix->info->ops;
--      ocelot->quirks          = felix->info->quirks;
-       base = pci_resource_start(felix->pdev, felix->info->pci_bar);
---- a/drivers/net/dsa/ocelot/felix.h
-+++ b/drivers/net/dsa/ocelot/felix.h
-@@ -18,7 +18,6 @@ struct felix_info {
-       unsigned int                    num_stats;
-       int                             num_ports;
-       int                             pci_bar;
--      unsigned long                   quirks;
- };
- extern struct felix_info              felix_info_vsc9959;
---- a/drivers/net/dsa/ocelot/felix_vsc9959.c
-+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
-@@ -584,5 +584,4 @@ struct felix_info felix_info_vsc9959 = {
-       .shared_queue_sz        = 128 * 1024,
-       .num_ports              = 6,
-       .pci_bar                = 4,
--      .quirks                 = OCELOT_PCS_PERFORMS_RATE_ADAPTATION,
- };
---- a/drivers/net/ethernet/mscc/ocelot.c
-+++ b/drivers/net/ethernet/mscc/ocelot.c
-@@ -409,32 +409,27 @@ static u16 ocelot_wm_enc(u16 value)
- void ocelot_adjust_link(struct ocelot *ocelot, int port,
-                       struct phy_device *phydev)
- {
--      int speed, mac_speed, mac_mode = DEV_MAC_MODE_CFG_FDX_ENA;
-       struct ocelot_port *ocelot_port = ocelot->ports[port];
-+      int speed, mode = 0;
--      if (ocelot->quirks & OCELOT_PCS_PERFORMS_RATE_ADAPTATION)
--              speed = SPEED_1000;
--      else
--              speed = phydev->speed;
--
--      switch (speed) {
-+      switch (phydev->speed) {
-       case SPEED_10:
--              mac_speed = OCELOT_SPEED_10;
-+              speed = OCELOT_SPEED_10;
-               break;
-       case SPEED_100:
--              mac_speed = OCELOT_SPEED_100;
-+              speed = OCELOT_SPEED_100;
-               break;
-       case SPEED_1000:
--              mac_speed = OCELOT_SPEED_1000;
--              mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-+              speed = OCELOT_SPEED_1000;
-+              mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       case SPEED_2500:
--              mac_speed = OCELOT_SPEED_2500;
--              mac_mode |= DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-+              speed = OCELOT_SPEED_2500;
-+              mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA;
-               break;
-       default:
-               dev_err(ocelot->dev, "Unsupported PHY speed on port %d: %d\n",
--                      port, speed);
-+                      port, phydev->speed);
-               return;
-       }
-@@ -444,7 +439,8 @@ void ocelot_adjust_link(struct ocelot *o
-               return;
-       /* Only full duplex supported for now */
--      ocelot_port_writel(ocelot_port, mac_mode, DEV_MAC_MODE_CFG);
-+      ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA |
-+                         mode, DEV_MAC_MODE_CFG);
-       if (ocelot->ops->pcs_init)
-               ocelot->ops->pcs_init(ocelot, port);
-@@ -455,11 +451,11 @@ void ocelot_adjust_link(struct ocelot *o
-       /* Take MAC, Port, Phy (intern) and PCS (SGMII/Serdes) clock out of
-        * reset */
--      ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(mac_speed),
-+      ocelot_port_writel(ocelot_port, DEV_CLOCK_CFG_LINK_SPEED(speed),
-                          DEV_CLOCK_CFG);
-       /* No PFC */
--      ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(mac_speed),
-+      ocelot_write_gix(ocelot, ANA_PFC_PFC_CFG_FC_LINK_SPEED(speed),
-                        ANA_PFC_PFC_CFG, port);
-       /* Core: Enable port for frame transfer */
-@@ -473,7 +469,7 @@ void ocelot_adjust_link(struct ocelot *o
-                        SYS_MAC_FC_CFG_RX_FC_ENA | SYS_MAC_FC_CFG_TX_FC_ENA |
-                        SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
-                        SYS_MAC_FC_CFG_FC_LATENCY_CFG(0x7) |
--                       SYS_MAC_FC_CFG_FC_LINK_SPEED(mac_speed),
-+                       SYS_MAC_FC_CFG_FC_LINK_SPEED(speed),
-                        SYS_MAC_FC_CFG, port);
-       ocelot_write_rix(ocelot, 0, ANA_POL_FLOWC, port);
- }
---- a/include/soc/mscc/ocelot.h
-+++ b/include/soc/mscc/ocelot.h
-@@ -404,11 +404,6 @@ enum ocelot_tag_prefix {
-       OCELOT_TAG_PREFIX_LONG,
- };
--/* Hardware quirks (differences between switch instantiations) */
--enum {
--      OCELOT_PCS_PERFORMS_RATE_ADAPTATION     = BIT(0),
--};
--
- struct ocelot;
- struct ocelot_ops {
-@@ -469,8 +464,6 @@ struct ocelot {
-       struct delayed_work             stats_work;
-       struct workqueue_struct         *stats_queue;
--      unsigned long                   quirks;
--
-       u8                              ptp:1;
-       struct ptp_clock                *ptp_clock;
-       struct ptp_clock_info           ptp_info;
diff --git a/target/linux/layerscape/patches-5.4/701-net-0372-Revert-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-va.patch b/target/linux/layerscape/patches-5.4/701-net-0372-Revert-enetc-Set-MDIO_CFG_HOLD-to-the-recommended-va.patch
deleted file mode 100644 (file)
index fda777b..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From d93ca8d9c8365cf533f88582c57c83cb50fe598a Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:31:13 +0200
-Subject: [PATCH] Revert "enetc: Set MDIO_CFG_HOLD to the recommended value of
- 2"
-
-This reverts commit 3f643e4af035886cd2ca4bf79967098cfe55b40b.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 12 ++++--------
- 1 file changed, 4 insertions(+), 8 deletions(-)
-
---- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-@@ -31,19 +31,15 @@ static inline void _enetc_mdio_wr(struct
-       _enetc_mdio_wr(mdio_priv, ENETC_##off, val)
- #define enetc_mdio_rd_reg(off)        enetc_mdio_rd(mdio_priv, off)
-+#define ENETC_MDC_DIV         258
-+
- #define MDIO_CFG_CLKDIV(x)    ((((x) >> 1) & 0xff) << 8)
- #define MDIO_CFG_BSY          BIT(0)
- #define MDIO_CFG_RD_ER                BIT(1)
--#define MDIO_CFG_HOLD(x)      (((x) << 2) & GENMASK(4, 2))
- #define MDIO_CFG_ENC45                BIT(6)
-  /* external MDIO only - driven on neg MDC edge */
- #define MDIO_CFG_NEG          BIT(23)
--#define ENETC_EMDIO_CFG \
--      (MDIO_CFG_HOLD(2) | \
--       MDIO_CFG_CLKDIV(258) | \
--       MDIO_CFG_NEG)
--
- #define MDIO_CTL_DEV_ADDR(x)  ((x) & 0x1f)
- #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
- #define MDIO_CTL_READ         BIT(15)
-@@ -65,7 +61,7 @@ int enetc_mdio_write(struct mii_bus *bus
-       u16 dev_addr;
-       int ret;
--      mdio_cfg = ENETC_EMDIO_CFG;
-+      mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
-       if (regnum & MII_ADDR_C45) {
-               dev_addr = (regnum >> 16) & 0x1f;
-               mdio_cfg |= MDIO_CFG_ENC45;
-@@ -112,7 +108,7 @@ int enetc_mdio_read(struct mii_bus *bus,
-       u16 dev_addr, value;
-       int ret;
--      mdio_cfg = ENETC_EMDIO_CFG;
-+      mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG;
-       if (regnum & MII_ADDR_C45) {
-               dev_addr = (regnum >> 16) & 0x1f;
-               mdio_cfg |= MDIO_CFG_ENC45;
diff --git a/target/linux/layerscape/patches-5.4/701-net-0373-Revert-enetc-export-enetc_mdio-definitionns-to-inclu.patch b/target/linux/layerscape/patches-5.4/701-net-0373-Revert-enetc-export-enetc_mdio-definitionns-to-inclu.patch
deleted file mode 100644 (file)
index 5e934c6..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-From 78378454e7978ea3b4128822880677e6efa9ddef Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:31:22 +0200
-Subject: [PATCH] Revert "enetc: export enetc_mdio definitionns to
- include/linux/fsl"
-
-This reverts commit f8d80c003b76f397696bf887ebbd37a78781c050.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/ethernet/freescale/enetc/enetc_mdio.c  | 18 +---------
- drivers/net/ethernet/freescale/enetc/enetc_mdio.h  | 12 +++++++
- .../net/ethernet/freescale/enetc/enetc_pci_mdio.c  | 41 +++++++++-------------
- include/linux/fsl/enetc_mdio.h                     | 21 -----------
- 4 files changed, 30 insertions(+), 62 deletions(-)
- create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_mdio.h
- delete mode 100644 include/linux/fsl/enetc_mdio.h
-
---- a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c
-@@ -1,13 +1,13 @@
- // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
- /* Copyright 2019 NXP */
--#include <linux/fsl/enetc_mdio.h>
- #include <linux/mdio.h>
- #include <linux/of_mdio.h>
- #include <linux/iopoll.h>
- #include <linux/of.h>
- #include "enetc_pf.h"
-+#include "enetc_mdio.h"
- #define       ENETC_MDIO_CFG  0x0     /* MDIO configuration and status */
- #define       ENETC_MDIO_CTL  0x4     /* MDIO control */
-@@ -99,7 +99,6 @@ int enetc_mdio_write(struct mii_bus *bus
-       return 0;
- }
--EXPORT_SYMBOL_GPL(enetc_mdio_write);
- int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
- {
-@@ -155,21 +154,6 @@ int enetc_mdio_read(struct mii_bus *bus,
-       return value;
- }
--EXPORT_SYMBOL_GPL(enetc_mdio_read);
--
--struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
--{
--      struct enetc_hw *hw;
--
--      hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
--      if (!hw)
--              return ERR_PTR(-ENOMEM);
--
--      hw->port = port_regs;
--
--      return hw;
--}
--EXPORT_SYMBOL_GPL(enetc_hw_alloc);
- int enetc_mdio_probe(struct enetc_pf *pf)
- {
---- /dev/null
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.h
-@@ -0,0 +1,12 @@
-+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-+/* Copyright 2019 NXP */
-+
-+#include <linux/phy.h>
-+
-+struct enetc_mdio_priv {
-+      struct enetc_hw *hw;
-+      int mdio_base;
-+};
-+
-+int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
-+int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
---- a/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
-+++ b/drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c
-@@ -1,8 +1,8 @@
- // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
- /* Copyright 2019 NXP */
--#include <linux/fsl/enetc_mdio.h>
- #include <linux/of_mdio.h>
- #include "enetc_pf.h"
-+#include "enetc_mdio.h"
- #define ENETC_MDIO_DEV_ID     0xee01
- #define ENETC_MDIO_DEV_NAME   "FSL PCIe IE Central MDIO"
-@@ -14,29 +14,17 @@ static int enetc_pci_mdio_probe(struct p
- {
-       struct enetc_mdio_priv *mdio_priv;
-       struct device *dev = &pdev->dev;
--      void __iomem *port_regs;
-       struct enetc_hw *hw;
-       struct mii_bus *bus;
-       int err;
--      port_regs = pci_iomap(pdev, 0, 0);
--      if (!port_regs) {
--              dev_err(dev, "iomap failed\n");
--              err = -ENXIO;
--              goto err_ioremap;
--      }
--
--      hw = enetc_hw_alloc(dev, port_regs);
--      if (IS_ERR(enetc_hw_alloc)) {
--              err = PTR_ERR(hw);
--              goto err_hw_alloc;
--      }
-+      hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
-+      if (!hw)
-+              return -ENOMEM;
-       bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
--      if (!bus) {
--              err = -ENOMEM;
--              goto err_mdiobus_alloc;
--      }
-+      if (!bus)
-+              return -ENOMEM;
-       bus->name = ENETC_MDIO_BUS_NAME;
-       bus->read = enetc_mdio_read;
-@@ -51,7 +39,7 @@ static int enetc_pci_mdio_probe(struct p
-       err = pci_enable_device_mem(pdev);
-       if (err) {
-               dev_err(dev, "device enable failed\n");
--              goto err_pci_enable;
-+              return err;
-       }
-       err = pci_request_region(pdev, 0, KBUILD_MODNAME);
-@@ -60,6 +48,13 @@ static int enetc_pci_mdio_probe(struct p
-               goto err_pci_mem_reg;
-       }
-+      hw->port = pci_iomap(pdev, 0, 0);
-+      if (!hw->port) {
-+              err = -ENXIO;
-+              dev_err(dev, "iomap failed\n");
-+              goto err_ioremap;
-+      }
-+
-       err = of_mdiobus_register(bus, dev->of_node);
-       if (err)
-               goto err_mdiobus_reg;
-@@ -69,14 +64,12 @@ static int enetc_pci_mdio_probe(struct p
-       return 0;
- err_mdiobus_reg:
-+      iounmap(mdio_priv->hw->port);
-+err_ioremap:
-       pci_release_mem_regions(pdev);
- err_pci_mem_reg:
-       pci_disable_device(pdev);
--err_pci_enable:
--err_mdiobus_alloc:
--      iounmap(port_regs);
--err_hw_alloc:
--err_ioremap:
-+
-       return err;
- }
---- a/include/linux/fsl/enetc_mdio.h
-+++ /dev/null
-@@ -1,21 +0,0 @@
--/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
--/* Copyright 2019 NXP */
--
--#include <linux/phy.h>
--
--/* PCS registers */
--#define ENETC_PCS_LINK_TIMER1         0x12
--#define ENETC_PCS_LINK_TIMER1_VAL     0x06a0
--#define ENETC_PCS_LINK_TIMER2         0x13
--#define ENETC_PCS_LINK_TIMER2_VAL     0x0003
--#define ENETC_PCS_IF_MODE             0x14
--#define ENETC_PCS_IF_MODE_SGMII_AN    0x0003
--
--struct enetc_mdio_priv {
--      struct enetc_hw *hw;
--      int mdio_base;
--};
--
--int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value);
--int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum);
--struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs);
diff --git a/target/linux/layerscape/patches-5.4/701-net-0374-Revert-net-phylink-call-mac_an_restart-for-SGMII-QSG.patch b/target/linux/layerscape/patches-5.4/701-net-0374-Revert-net-phylink-call-mac_an_restart-for-SGMII-QSG.patch
deleted file mode 100644 (file)
index 4b2cee6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From d3a532021976d98bfc9e3dac18a17abccf6eb567 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:31:42 +0200
-Subject: [PATCH] Revert "net: phylink: call mac_an_restart for SGMII/QSGMII
- inband interfaces too"
-
-This reverts commit 57fe15baac62dad00817e3359cefc123e24f10a2.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/phy/phylink.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/net/phy/phylink.c
-+++ b/drivers/net/phy/phylink.c
-@@ -360,9 +360,7 @@ static void phylink_mac_config_up(struct
- static void phylink_mac_an_restart(struct phylink *pl)
- {
-       if (pl->link_config.an_enabled &&
--          (phy_interface_mode_is_8023z(pl->link_config.interface) ||
--           pl->link_config.interface == PHY_INTERFACE_MODE_SGMII ||
--           pl->link_config.interface == PHY_INTERFACE_MODE_QSGMII))
-+          phy_interface_mode_is_8023z(pl->link_config.interface))
-               pl->ops->mac_an_restart(pl->config);
- }
diff --git a/target/linux/layerscape/patches-5.4/701-net-0375-Revert-net-phylink-make-QSGMII-a-valid-PHY-mode-for-.patch b/target/linux/layerscape/patches-5.4/701-net-0375-Revert-net-phylink-make-QSGMII-a-valid-PHY-mode-for-.patch
deleted file mode 100644 (file)
index e2bce2f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From e53b64cab45ea4d01226840efd963a6bec8ad2f9 Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:31:58 +0200
-Subject: [PATCH] Revert "net: phylink: make QSGMII a valid PHY mode for
- in-band AN"
-
-This reverts commit fe7fd9f6afce50c0fc09fd3d56cd59eda44d8dd0.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- drivers/net/phy/phylink.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/net/phy/phylink.c
-+++ b/drivers/net/phy/phylink.c
-@@ -283,7 +283,6 @@ static int phylink_parse_mode(struct phy
-               switch (pl->link_config.interface) {
-               case PHY_INTERFACE_MODE_SGMII:
--              case PHY_INTERFACE_MODE_QSGMII:
-                       phylink_set(pl->supported, 10baseT_Half);
-                       phylink_set(pl->supported, 10baseT_Full);
-                       phylink_set(pl->supported, 100baseT_Half);
diff --git a/target/linux/layerscape/patches-5.4/701-net-0376-Revert-mii-Add-helpers-for-parsing-SGMII-auto-negoti.patch b/target/linux/layerscape/patches-5.4/701-net-0376-Revert-mii-Add-helpers-for-parsing-SGMII-auto-negoti.patch
deleted file mode 100644 (file)
index 3831cac..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-From c6f9fb78b7534392d3be307e566d10c8525c7c9a Mon Sep 17 00:00:00 2001
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Mon, 6 Jan 2020 14:32:06 +0200
-Subject: [PATCH] Revert "mii: Add helpers for parsing SGMII auto-negotiation"
-
-This reverts commit de81e3c1ccbf27eda7584e23c713705a221a57da.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
----
- include/linux/mii.h      | 50 ------------------------------------------------
- include/uapi/linux/mii.h | 10 ----------
- 2 files changed, 60 deletions(-)
-
---- a/include/linux/mii.h
-+++ b/include/linux/mii.h
-@@ -373,56 +373,6 @@ static inline u32 mii_lpa_to_ethtool_lpa
- }
- /**
-- * mii_lpa_mod_linkmode_adv_sgmii
-- * @lp_advertising: pointer to destination link mode.
-- * @lpa: value of the MII_LPA register
-- *
-- * A small helper function that translates MII_LPA bits to
-- * linkmode advertisement settings for SGMII.
-- * Leaves other bits unchanged.
-- */
--static inline void
--mii_lpa_mod_linkmode_lpa_sgmii(unsigned long *lp_advertising, u32 lpa)
--{
--      u32 speed_duplex = lpa & LPA_SGMII_DPX_SPD_MASK;
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_1000HALF);
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_1000FULL);
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_100HALF);
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_100FULL);
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_10HALF);
--
--      linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, lp_advertising,
--                       speed_duplex == LPA_SGMII_10FULL);
--}
--
--/**
-- * mii_lpa_to_linkmode_adv_sgmii
-- * @advertising: pointer to destination link mode.
-- * @lpa: value of the MII_LPA register
-- *
-- * A small helper function that translates MII_ADVERTISE bits
-- * to linkmode advertisement settings when in SGMII mode.
-- * Clears the old value of advertising.
-- */
--static inline void mii_lpa_to_linkmode_lpa_sgmii(unsigned long *lp_advertising,
--                                               u32 lpa)
--{
--      linkmode_zero(lp_advertising);
--
--      mii_lpa_mod_linkmode_lpa_sgmii(lp_advertising, lpa);
--}
--
--/**
-  * mii_adv_mod_linkmode_adv_t
-  * @advertising:pointer to destination link mode.
-  * @adv: value of the MII_ADVERTISE register
---- a/include/uapi/linux/mii.h
-+++ b/include/uapi/linux/mii.h
-@@ -71,7 +71,6 @@
- /* Advertisement control register. */
- #define ADVERTISE_SLCT                0x001f  /* Selector bits               */
- #define ADVERTISE_CSMA                0x0001  /* Only selector supported     */
--#define ADVERTISE_SGMII               0x0001  /* Can do SGMII                */
- #define ADVERTISE_10HALF      0x0020  /* Try for 10mbps half-duplex  */
- #define ADVERTISE_1000XFULL   0x0020  /* Try for 1000BASE-X full-duplex */
- #define ADVERTISE_10FULL      0x0040  /* Try for 10mbps full-duplex  */
-@@ -95,7 +94,6 @@
- /* Link partner ability register. */
- #define LPA_SLCT              0x001f  /* Same as advertise selector  */
--#define LPA_SGMII             0x0001  /* Can do SGMII                */
- #define LPA_10HALF            0x0020  /* Can do 10mbps half-duplex   */
- #define LPA_1000XFULL         0x0020  /* Can do 1000BASE-X full-duplex */
- #define LPA_10FULL            0x0040  /* Can do 10mbps full-duplex   */
-@@ -106,19 +104,11 @@
- #define LPA_1000XPAUSE_ASYM   0x0100  /* Can do 1000BASE-X pause asym*/
- #define LPA_100BASE4          0x0200  /* Can do 100mbps 4k packets   */
- #define LPA_PAUSE_CAP         0x0400  /* Can pause                   */
--#define LPA_SGMII_DPX_SPD_MASK        0x1C00  /* SGMII duplex and speed bits */
--#define LPA_SGMII_10HALF      0x0000  /* Can do SGMII 10mbps half-duplex */
--#define LPA_SGMII_10FULL      0x1000  /* Can do SGMII 10mbps full-duplex */
--#define LPA_SGMII_100HALF     0x0400  /* Can do SGMII 100mbps half-duplex */
--#define LPA_SGMII_100FULL     0x1400  /* Can do SGMII 100mbps full-duplex */
- #define LPA_PAUSE_ASYM                0x0800  /* Can pause asymetrically     */
--#define LPA_SGMII_1000HALF    0x0800  /* Can do SGMII 1000mbps half-duplex */
--#define LPA_SGMII_1000FULL    0x1800  /* Can do SGMII 1000mbps full-duplex */
- #define LPA_RESV              0x1000  /* Unused...                   */
- #define LPA_RFAULT            0x2000  /* Link partner faulted        */
- #define LPA_LPACK             0x4000  /* Link partner acked us       */
- #define LPA_NPAGE             0x8000  /* Next page bit               */
--#define LPA_SGMII_LINK                0x8000  /* Link partner has link       */
- #define LPA_DUPLEX            (LPA_10FULL | LPA_100FULL)
- #define LPA_100                       (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
diff --git a/target/linux/layerscape/patches-5.4/801-audio-0023-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-part-2.patch b/target/linux/layerscape/patches-5.4/801-audio-0023-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-part-2.patch
deleted file mode 100644 (file)
index d09dd9b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 5d816f1a5cac458a7fff9ecf896c85eb351a7352 Mon Sep 17 00:00:00 2001
-From: Viorel Suman <viorel.suman@nxp.com>
-Date: Mon, 30 Mar 2020 16:24:59 +0800
-Subject: [PATCH] ASoC: fsl: add imx-pcm-dma v2 platform driver (part 2)
-
-which don't request the dma channel in the probe, but request
-dma channel when needed. for the dma channel of cpu dai in BE
-can be reused by the FE.
-
-Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
-[ Aisheng: split PCM changes ]
-Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
-[rebase]
-Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
----
- sound/soc/fsl/fsl_sai.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/sound/soc/fsl/fsl_sai.c
-+++ b/sound/soc/fsl/fsl_sai.c
-@@ -1046,6 +1046,8 @@ static int fsl_sai_probe(struct platform
-                                  MCLK_DIR(index));
-       }
-+      sai->dma_params_rx.filter_data = "rx";
-+      sai->dma_params_tx.filter_data = "tx";
-       sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
-       sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
-       sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
-@@ -1061,7 +1063,7 @@ static int fsl_sai_probe(struct platform
-               goto err_pm_disable;
-       if (sai->soc->imx)
--              ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
-+              ret = imx_pcm_platform_register(&pdev->dev);
-               if (ret)
-                       goto err_pm_disable;
-       } else {
index 38d3041bae7894a49061d1ada0dd87af5fea0a49..7f234a27cc9bae63120f7964b692340f8677f4c3 100644 (file)
@@ -590,7 +590,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
        if (ret) {
                dev_err(&pdev->dev, "failed to claim irq %u\n", irq);
                return ret;
-@@ -1090,6 +1134,7 @@ static int fsl_sai_runtime_suspend(struc
+@@ -1088,6 +1132,7 @@ static int fsl_sai_runtime_suspend(struc
  static int fsl_sai_runtime_resume(struct device *dev)
  {
        struct fsl_sai *sai = dev_get_drvdata(dev);
@@ -598,7 +598,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
        int ret;
  
        ret = clk_prepare_enable(sai->bus_clk);
-@@ -1115,11 +1160,11 @@ static int fsl_sai_runtime_resume(struct
+@@ -1113,11 +1158,11 @@ static int fsl_sai_runtime_resume(struct
                                PM_QOS_CPU_DMA_LATENCY, 0);
  
        regcache_cache_only(sai->regmap, false);
index 5232a6989442d4d2b083d0d39e9a9d5b29223d2c..9f9db86f648ef24fcabefb4bb788abb90c7224cb 100644 (file)
@@ -16,7 +16,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
 
 --- a/sound/soc/fsl/fsl_sai.c
 +++ b/sound/soc/fsl/fsl_sai.c
-@@ -1096,6 +1096,8 @@ static int fsl_sai_probe(struct platform
+@@ -1094,6 +1094,8 @@ static int fsl_sai_probe(struct platform
  
        pm_runtime_enable(&pdev->dev);
  
@@ -25,7 +25,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
                        &fsl_sai_dai, 1);
        if (ret)
-@@ -1139,6 +1141,8 @@ static int fsl_sai_runtime_suspend(struc
+@@ -1137,6 +1139,8 @@ static int fsl_sai_runtime_suspend(struc
  {
        struct fsl_sai *sai = dev_get_drvdata(dev);
  
diff --git a/target/linux/layerscape/patches-5.4/801-audio-0036-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_data-pa.patch b/target/linux/layerscape/patches-5.4/801-audio-0036-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_data-pa.patch
deleted file mode 100644 (file)
index 5cc4274..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 8d4837f146cd14cf7041050ddec77b2a5c3f2f27 Mon Sep 17 00:00:00 2001
-From: Shengjiu Wang <shengjiu.wang@nxp.com>
-Date: Tue, 23 Jan 2018 13:25:40 +0800
-Subject: [PATCH] MLK-17442: ASoC: fsl: fix wrong usage of filter_data (part 1)
-
-The filter_data should be used for dma_filter_fn function,
-but we used the filter_data wrongly for dma channel name.
-This patch is to fix the issue.
-
-Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
-Reviwed-by: Daniel Baluta <daniel.baluta@nxp.com>
-[ Aisheng: split out esai and pcm changes ]
-Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
----
- sound/soc/fsl/fsl_sai.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/sound/soc/fsl/fsl_sai.c
-+++ b/sound/soc/fsl/fsl_sai.c
-@@ -1136,8 +1136,8 @@ static int fsl_sai_probe(struct platform
-                                  MCLK_DIR(index));
-       }
--      sai->dma_params_rx.filter_data = "rx";
--      sai->dma_params_tx.filter_data = "tx";
-+      sai->dma_params_rx.chan_name = "rx";
-+      sai->dma_params_tx.chan_name = "tx";
-       sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
-       sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
-       sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
index 033ab0d06b0314267344fca12a64750f3e5f326f..b5802d3250ea73b69878c0e82545ef9f9346a631 100644 (file)
@@ -274,7 +274,7 @@ Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
        if ((of_find_property(np, "fsl,i2s-xtor", NULL) != NULL) ||
            (of_find_property(np, "fsl,txm-rxs", NULL) != NULL))
        {
-@@ -1143,6 +1282,11 @@ static int fsl_sai_probe(struct platform
+@@ -1141,6 +1280,11 @@ static int fsl_sai_probe(struct platform
        sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
        sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
  
index ffd74f81d1f1625dd14fd7b231581e5a4ce554bc..856f2bb6d72a550f671ca254c5d6b80dc5ce88cc 100644 (file)
@@ -73,7 +73,7 @@ Reviewed-by: Shengjiu Wang <shengjiu.wang@nxp.com
                if (ret) {
                        dev_err(cpu_dai->dev,
                                "failed to set proper pins state: %d\n", ret);
-@@ -1356,9 +1347,6 @@ static int fsl_sai_probe(struct platform
+@@ -1354,9 +1345,6 @@ static int fsl_sai_probe(struct platform
  
        sai->pinctrl  = devm_pinctrl_get(&pdev->dev);
  
index 5f69c1daae298d590e6a86a1e9c8fd91e05dccb1..ebd71672b2442470a2a407583b5a58efea5a09b7 100644 (file)
@@ -49,7 +49,7 @@ Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
                ret = pinctrl_select_state(sai->pinctrl, sai->pins_state);
                if (ret) {
                        dev_err(cpu_dai->dev,
-@@ -1345,7 +1348,7 @@ static int fsl_sai_probe(struct platform
+@@ -1343,7 +1346,7 @@ static int fsl_sai_probe(struct platform
        sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
        sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
  
index 7cce9d45a0083f75eb644c6adade631495a1a18d..3f92c2185c622d8c6686c314de3e29269363b694 100644 (file)
@@ -25,7 +25,7 @@ Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
-@@ -1574,14 +1572,6 @@ static int fsl_sai_remove(struct platfor
+@@ -1572,14 +1570,6 @@ static int fsl_sai_remove(struct platfor
        return 0;
  }
  
index 1f74ff235aba964cc8630ccfabeb482570e99799..3fd35549851951230861f459ee3c0258b3b32f73 100644 (file)
@@ -17,7 +17,7 @@ Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
 
 --- a/sound/soc/fsl/fsl_sai.c
 +++ b/sound/soc/fsl/fsl_sai.c
-@@ -1616,6 +1616,8 @@ static int fsl_sai_runtime_resume(struct
+@@ -1614,6 +1614,8 @@ static int fsl_sai_runtime_resume(struct
                                PM_QOS_CPU_DMA_LATENCY, 0);
  
        regcache_cache_only(sai->regmap, false);
index 25c65f17dd1ef1c6be140e0c9296336caa15748e..ed0afdbac83e7c159f356e26041909361b766a55 100644 (file)
@@ -20,7 +20,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
  
  #include "fsl_dsd.h"
  #include "fsl_sai.h"
-@@ -1570,6 +1571,8 @@ static int fsl_sai_runtime_suspend(struc
+@@ -1568,6 +1569,8 @@ static int fsl_sai_runtime_suspend(struc
  
        regcache_cache_only(sai->regmap, true);
  
@@ -29,7 +29,7 @@ Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
        if (sai->mclk_streams & BIT(SNDRV_PCM_STREAM_CAPTURE))
                clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[0]]);
  
-@@ -1611,6 +1614,8 @@ static int fsl_sai_runtime_resume(struct
+@@ -1609,6 +1612,8 @@ static int fsl_sai_runtime_resume(struct
                        goto disable_tx_clk;
        }
  
diff --git a/target/linux/layerscape/patches-5.4/801-audio-0067-Revert-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_.patch b/target/linux/layerscape/patches-5.4/801-audio-0067-Revert-MLK-17442-ASoC-fsl-fix-wrong-usage-of-filter_.patch
deleted file mode 100644 (file)
index d36101e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 912323e5d1290cbee651270f65de338663012c9b Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 30 Mar 2020 16:30:03 +0800
-Subject: [PATCH] Revert "MLK-17442: ASoC: fsl: fix wrong usage of filter_data
- (part 1)"
-
-This reverts commit 8d4837f146cd14cf7041050ddec77b2a5c3f2f27.
----
- sound/soc/fsl/fsl_sai.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/sound/soc/fsl/fsl_sai.c
-+++ b/sound/soc/fsl/fsl_sai.c
-@@ -1519,8 +1519,8 @@ static int fsl_sai_probe(struct platform
-                                  MCLK_DIR(index));
-       }
--      sai->dma_params_rx.chan_name = "rx";
--      sai->dma_params_tx.chan_name = "tx";
-+      sai->dma_params_rx.filter_data = "rx";
-+      sai->dma_params_tx.filter_data = "tx";
-       sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
-       sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
-       sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
diff --git a/target/linux/layerscape/patches-5.4/801-audio-0068-Revert-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-p.patch b/target/linux/layerscape/patches-5.4/801-audio-0068-Revert-ASoC-fsl-add-imx-pcm-dma-v2-platform-driver-p.patch
deleted file mode 100644 (file)
index 1045b90..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From d8715f02b84c1a210b6fd84badc41eced6272424 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 30 Mar 2020 16:30:26 +0800
-Subject: [PATCH] Revert "ASoC: fsl: add imx-pcm-dma v2 platform driver (part
- 2)"
-
-This reverts commit 5d816f1a5cac458a7fff9ecf896c85eb351a7352.
----
- sound/soc/fsl/fsl_sai.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/sound/soc/fsl/fsl_sai.c
-+++ b/sound/soc/fsl/fsl_sai.c
-@@ -1519,8 +1519,6 @@ static int fsl_sai_probe(struct platform
-                                  MCLK_DIR(index));
-       }
--      sai->dma_params_rx.filter_data = "rx";
--      sai->dma_params_tx.filter_data = "tx";
-       sai->dma_params_rx.addr = res->start + FSL_SAI_RDR0;
-       sai->dma_params_tx.addr = res->start + FSL_SAI_TDR0;
-       sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
-@@ -1540,7 +1538,7 @@ static int fsl_sai_probe(struct platform
-               goto err_pm_disable;
-       if (sai->soc->imx)
--              ret = imx_pcm_platform_register(&pdev->dev);
-+              ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
-               if (ret)
-                       goto err_pm_disable;
-       } else {
diff --git a/target/linux/layerscape/patches-5.4/805-display-0030-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sinks.patch b/target/linux/layerscape/patches-5.4/805-display-0030-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sinks.patch
deleted file mode 100644 (file)
index be72d1f..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From d9440f7cb8fa5853b9dcc6e2b165725ac3e8b70c Mon Sep 17 00:00:00 2001
-From: Laurentiu Palcu <laurentiu.palcu@nxp.com>
-Date: Wed, 27 Nov 2019 13:34:51 +0200
-Subject: [PATCH] drm/imx/hdp: fix issue with non-SCDC HDMI sinks
-
-Currently, if sink does not support SCDC, even if the sink is HDMI 1.4 or 2.0,
-the hdmi_type is left to default value (MODE_DVI). Hence the HDMI controler is
-not properly initialized when cdns_hdmi_ctrl_init() is called.
-
-Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
-Reported-by: Jared Hu <jared.hu@nxp.com>
-Reviewed-by: Sandor Yu <sandor.yu@nxp.com>
----
- drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 20 ++++++++++----------
- 1 file changed, 10 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-@@ -29,11 +29,17 @@
- static void hdmi_sink_config(struct cdns_mhdp_device *mhdp)
- {
-       struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc;
--      u8 buff;
-+      struct drm_display_info *di = &mhdp->connector.base.display_info;
-+      u8 buff = 0;
-+
-+      if (scdc->supported || di->color_formats & DRM_COLOR_FORMAT_YCRCB420)
-+              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
-+      else
-+              mhdp->hdmi.hdmi_type = MODE_HDMI_1_4;
-       /* check sink support SCDC or not */
--      if (scdc->supported != true) {
--              DRM_INFO("Sink Not Support SCDC\n");
-+      if (!scdc->supported) {
-+              DRM_INFO("Sink does not support SCDC\n");
-               return;
-       }
-@@ -43,19 +49,13 @@ static void hdmi_sink_config(struct cdns
-                * Enable scrambling and TMDS_Bit_Clock_Ratio
-                */
-               buff = SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE;
--              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
-       } else  if (scdc->scrambling.low_rates) {
-               /*
-                * Enable scrambling and HDMI2.0 when scrambling capability of sink
-                * be indicated in the HF-VSDB LTE_340Mcsc_scramble bit
-                */
-               buff = SCDC_SCRAMBLING_ENABLE;
--              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
--      } else {
--              /* Default work in HDMI1.4 */
--              buff = 0;
--              mhdp->hdmi.hdmi_type = MODE_HDMI_1_4;
--       }
-+      }
-       /* TMDS config */
-       cdns_hdmi_scdc_write(mhdp, 0x20, buff);
diff --git a/target/linux/layerscape/patches-5.4/805-display-0031-Revert-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sink.patch b/target/linux/layerscape/patches-5.4/805-display-0031-Revert-drm-imx-hdp-fix-issue-with-non-SCDC-HDMI-sink.patch
deleted file mode 100644 (file)
index e906be4..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 575fc16e92287349f0ffd8399dd9d7e408954cd4 Mon Sep 17 00:00:00 2001
-From: Sandor Yu <Sandor.yu@nxp.com>
-Date: Fri, 29 Nov 2019 15:05:03 +0800
-Subject: [PATCH] Revert "drm/imx/hdp: fix issue with non-SCDC HDMI sinks"
-
-For HDMI sinks that support HDMI2.0, those video modes have
-listed in hdmi1.4 specification should work in hdmi 1.4.
-Remove the patch, make sure all video modes can work well
-in HDMI2.0 sinks.
-For non-SCDC HDMI sinks issue,
-it will be fixed with another patch.
-
-This reverts commit 4b6617643f9e3a6f61d42eae39034ddc8d4825af.
-
-Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
----
- drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c | 20 ++++++++++----------
- 1 file changed, 10 insertions(+), 10 deletions(-)
-
---- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
-@@ -29,17 +29,11 @@
- static void hdmi_sink_config(struct cdns_mhdp_device *mhdp)
- {
-       struct drm_scdc *scdc = &mhdp->connector.base.display_info.hdmi.scdc;
--      struct drm_display_info *di = &mhdp->connector.base.display_info;
--      u8 buff = 0;
--
--      if (scdc->supported || di->color_formats & DRM_COLOR_FORMAT_YCRCB420)
--              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
--      else
--              mhdp->hdmi.hdmi_type = MODE_HDMI_1_4;
-+      u8 buff;
-       /* check sink support SCDC or not */
--      if (!scdc->supported) {
--              DRM_INFO("Sink does not support SCDC\n");
-+      if (scdc->supported != true) {
-+              DRM_INFO("Sink Not Support SCDC\n");
-               return;
-       }
-@@ -49,13 +43,19 @@ static void hdmi_sink_config(struct cdns
-                * Enable scrambling and TMDS_Bit_Clock_Ratio
-                */
-               buff = SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE;
-+              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
-       } else  if (scdc->scrambling.low_rates) {
-               /*
-                * Enable scrambling and HDMI2.0 when scrambling capability of sink
-                * be indicated in the HF-VSDB LTE_340Mcsc_scramble bit
-                */
-               buff = SCDC_SCRAMBLING_ENABLE;
--      }
-+              mhdp->hdmi.hdmi_type = MODE_HDMI_2_0;
-+      } else {
-+              /* Default work in HDMI1.4 */
-+              buff = 0;
-+              mhdp->hdmi.hdmi_type = MODE_HDMI_1_4;
-+       }
-       /* TMDS config */
-       cdns_hdmi_scdc_write(mhdp, 0x20, buff);
diff --git a/target/linux/layerscape/patches-5.4/805-display-0042-drm-imx-Revert-a-patch-which-merges-imx-drm-core-and.patch b/target/linux/layerscape/patches-5.4/805-display-0042-drm-imx-Revert-a-patch-which-merges-imx-drm-core-and.patch
deleted file mode 100644 (file)
index 017f0e3..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-From d27d7c25c946776c015a39f1a9eb0c6d4e724a70 Mon Sep 17 00:00:00 2001
-From: Liu Ying <victor.liu@nxp.com>
-Date: Fri, 25 Jan 2019 11:23:39 +0800
-Subject: [PATCH] drm/imx: Revert a patch which merges imx-drm-core and
- ipuv3-crtc in one module
-
-DPU CRTC found in i.MX8qm/qxp SoCs can be hooked into imx-drm.
-Thus, move ipuv3-crtc out of imx-drm-core.
-
-Revert "drm/imx: merge imx-drm-core and ipuv3-crtc in one module"
-
-This reverts commit 3d1df96ad46856ce850be5ac112eab919cbe1cab.
-
-Signed-off-by: Liu Ying <victor.liu@nxp.com>
-[ Aisheng: fix conflicts ]
-Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
----
- drivers/gpu/drm/imx/Kconfig        |  7 +++++++
- drivers/gpu/drm/imx/Makefile       |  4 +++-
- drivers/gpu/drm/imx/imx-drm-core.c | 18 +-----------------
- drivers/gpu/drm/imx/imx-drm.h      |  2 --
- drivers/gpu/drm/imx/ipuv3-crtc.c   |  8 +++++++-
- 5 files changed, 18 insertions(+), 21 deletions(-)
-
---- a/drivers/gpu/drm/imx/Kconfig
-+++ b/drivers/gpu/drm/imx/Kconfig
-@@ -33,6 +33,13 @@ config DRM_IMX_LDB
-         Choose this to enable the internal LVDS Display Bridge (LDB)
-         found on i.MX53 and i.MX6 processors.
-+config DRM_IMX_IPUV3
-+      tristate
-+      depends on DRM_IMX
-+      depends on IMX_IPUV3_CORE
-+      default y if DRM_IMX=y
-+      default m if DRM_IMX=m
-+
- config DRM_IMX_HDMI
-       tristate "Freescale i.MX DRM HDMI"
-       select DRM_DW_HDMI
---- a/drivers/gpu/drm/imx/Makefile
-+++ b/drivers/gpu/drm/imx/Makefile
-@@ -1,6 +1,6 @@
- # SPDX-License-Identifier: GPL-2.0
--imxdrm-objs := imx-drm-core.o ipuv3-crtc.o ipuv3-plane.o
-+imxdrm-objs := imx-drm-core.o
- obj-$(CONFIG_DRM_IMX) += imxdrm.o
-@@ -8,5 +8,7 @@ obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) +
- obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
- obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-+imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
-+obj-$(CONFIG_DRM_IMX_IPUV3)   += imx-ipuv3-crtc.o
- obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o
- obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += cdn-mhdp-imxdrv.o cdn-mhdp-dp-phy.o cdn-mhdp-hdmi-phy.o cdn-mhdp-imx8qm.o cdn-mhdp-ls1028a.o
---- a/drivers/gpu/drm/imx/imx-drm-core.c
-+++ b/drivers/gpu/drm/imx/imx-drm-core.c
-@@ -343,23 +343,7 @@ static struct platform_driver imx_drm_pd
-               .of_match_table = imx_drm_dt_ids,
-       },
- };
--
--static struct platform_driver * const drivers[] = {
--      &imx_drm_pdrv,
--      &ipu_drm_driver,
--};
--
--static int __init imx_drm_init(void)
--{
--      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_init(imx_drm_init);
--
--static void __exit imx_drm_exit(void)
--{
--      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_exit(imx_drm_exit);
-+module_platform_driver(imx_drm_pdrv);
- MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
- MODULE_DESCRIPTION("i.MX drm driver core");
---- a/drivers/gpu/drm/imx/imx-drm.h
-+++ b/drivers/gpu/drm/imx/imx-drm.h
-@@ -28,8 +28,6 @@ int imx_drm_init_drm(struct platform_dev
-               int preferred_bpp);
- int imx_drm_exit_drm(void);
--extern struct platform_driver ipu_drm_driver;
--
- void imx_drm_mode_config_init(struct drm_device *drm);
- struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
---- a/drivers/gpu/drm/imx/ipuv3-crtc.c
-+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
-@@ -492,10 +492,16 @@ static int ipu_drm_remove(struct platfor
-       return 0;
- }
--struct platform_driver ipu_drm_driver = {
-+static struct platform_driver ipu_drm_driver = {
-       .driver = {
-               .name = "imx-ipuv3-crtc",
-       },
-       .probe = ipu_drm_probe,
-       .remove = ipu_drm_remove,
- };
-+module_platform_driver(ipu_drm_driver);
-+
-+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:imx-ipuv3-crtc");
diff --git a/target/linux/layerscape/patches-5.4/805-display-0043-gpu-Move-ipu-v3-to-imx-folder.patch b/target/linux/layerscape/patches-5.4/805-display-0043-gpu-Move-ipu-v3-to-imx-folder.patch
deleted file mode 100644 (file)
index 6deb30f..0000000
+++ /dev/null
@@ -1,19995 +0,0 @@
-From a7782c6e5e37b2b406221827b177c2bfcc8825cd Mon Sep 17 00:00:00 2001
-From: Liu Ying <victor.liu@nxp.com>
-Date: Tue, 22 Jan 2019 17:08:01 +0800
-Subject: [PATCH] gpu: Move ipu-v3 to imx folder
-
-The new imx folder may contain ipu-v3 and dpu common drivers.
-
-Signed-off-by: Liu Ying <victor.liu@nxp.com>
-[ Aisheng: fix source path ]
-Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
----
- drivers/gpu/Makefile                       |    2 +-
- drivers/gpu/imx/Kconfig                    |    1 +
- drivers/gpu/imx/Makefile                   |    1 +
- drivers/gpu/imx/ipu-v3/Kconfig             |   11 +
- drivers/gpu/imx/ipu-v3/Makefile            |   10 +
- drivers/gpu/imx/ipu-v3/ipu-common.c        | 1565 ++++++++++++++++++
- drivers/gpu/imx/ipu-v3/ipu-cpmem.c         |  976 +++++++++++
- drivers/gpu/imx/ipu-v3/ipu-csi.c           |  821 +++++++++
- drivers/gpu/imx/ipu-v3/ipu-dc.c            |  420 +++++
- drivers/gpu/imx/ipu-v3/ipu-di.c            |  745 +++++++++
- drivers/gpu/imx/ipu-v3/ipu-dmfc.c          |  214 +++
- drivers/gpu/imx/ipu-v3/ipu-dp.c            |  357 ++++
- drivers/gpu/imx/ipu-v3/ipu-ic.c            |  761 +++++++++
- drivers/gpu/imx/ipu-v3/ipu-image-convert.c | 2475 ++++++++++++++++++++++++++++
- drivers/gpu/imx/ipu-v3/ipu-pre.c           |  346 ++++
- drivers/gpu/imx/ipu-v3/ipu-prg.c           |  483 ++++++
- drivers/gpu/imx/ipu-v3/ipu-prv.h           |  274 +++
- drivers/gpu/imx/ipu-v3/ipu-smfc.c          |  202 +++
- drivers/gpu/imx/ipu-v3/ipu-vdi.c           |  234 +++
- drivers/gpu/ipu-v3/Kconfig                 |   11 -
- drivers/gpu/ipu-v3/Makefile                |   10 -
- drivers/gpu/ipu-v3/ipu-common.c            | 1565 ------------------
- drivers/gpu/ipu-v3/ipu-cpmem.c             |  976 -----------
- drivers/gpu/ipu-v3/ipu-csi.c               |  821 ---------
- drivers/gpu/ipu-v3/ipu-dc.c                |  420 -----
- drivers/gpu/ipu-v3/ipu-di.c                |  745 ---------
- drivers/gpu/ipu-v3/ipu-dmfc.c              |  214 ---
- drivers/gpu/ipu-v3/ipu-dp.c                |  357 ----
- drivers/gpu/ipu-v3/ipu-ic.c                |  761 ---------
- drivers/gpu/ipu-v3/ipu-image-convert.c     | 2475 ----------------------------
- drivers/gpu/ipu-v3/ipu-pre.c               |  346 ----
- drivers/gpu/ipu-v3/ipu-prg.c               |  483 ------
- drivers/gpu/ipu-v3/ipu-prv.h               |  274 ---
- drivers/gpu/ipu-v3/ipu-smfc.c              |  202 ---
- drivers/gpu/ipu-v3/ipu-vdi.c               |  234 ---
- drivers/video/Kconfig                      |    2 +-
- 36 files changed, 9898 insertions(+), 9896 deletions(-)
- create mode 100644 drivers/gpu/imx/Kconfig
- create mode 100644 drivers/gpu/imx/Makefile
- create mode 100644 drivers/gpu/imx/ipu-v3/Kconfig
- create mode 100644 drivers/gpu/imx/ipu-v3/Makefile
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-common.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-cpmem.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-csi.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dc.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-di.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dmfc.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-dp.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-ic.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-image-convert.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-pre.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-prg.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-prv.h
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-smfc.c
- create mode 100644 drivers/gpu/imx/ipu-v3/ipu-vdi.c
- delete mode 100644 drivers/gpu/ipu-v3/Kconfig
- delete mode 100644 drivers/gpu/ipu-v3/Makefile
- delete mode 100644 drivers/gpu/ipu-v3/ipu-common.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-cpmem.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-csi.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-dc.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-di.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-dmfc.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-dp.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-ic.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-image-convert.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-pre.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-prg.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-prv.h
- delete mode 100644 drivers/gpu/ipu-v3/ipu-smfc.c
- delete mode 100644 drivers/gpu/ipu-v3/ipu-vdi.c
-
---- a/drivers/gpu/Makefile
-+++ b/drivers/gpu/Makefile
-@@ -3,5 +3,5 @@
- # taken to initialize them in the correct order. Link order is the only way
- # to ensure this currently.
- obj-$(CONFIG_TEGRA_HOST1X)    += host1x/
-+obj-y                 += imx/
- obj-y                 += drm/ vga/
--obj-$(CONFIG_IMX_IPUV3_CORE)  += ipu-v3/
---- /dev/null
-+++ b/drivers/gpu/imx/Kconfig
-@@ -0,0 +1 @@
-+source "drivers/gpu/imx/ipu-v3/Kconfig"
---- /dev/null
-+++ b/drivers/gpu/imx/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_IMX_IPUV3_CORE)  += ipu-v3/
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/Kconfig
-@@ -0,0 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+config IMX_IPUV3_CORE
-+      tristate "IPUv3 core support"
-+      depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
-+      depends on DRM || !DRM # if DRM=m, this can't be 'y'
-+      select BITREVERSE
-+      select GENERIC_ALLOCATOR if DRM
-+      select GENERIC_IRQ_CHIP
-+      help
-+        Choose this if you have a i.MX5/6 system and want to use the Image
-+        Processing Unit. This option only enables IPU base support.
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/Makefile
-@@ -0,0 +1,10 @@
-+# SPDX-License-Identifier: GPL-2.0
-+obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
-+
-+imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
-+              ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
-+              ipu-image-convert.o ipu-smfc.o ipu-vdi.o
-+
-+ifdef CONFIG_DRM
-+      imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
-+endif
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-common.c
-@@ -0,0 +1,1565 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/module.h>
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/reset.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/list.h>
-+#include <linux/irq.h>
-+#include <linux/irqchip/chained_irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/of_device.h>
-+#include <linux/of_graph.h>
-+
-+#include <drm/drm_fourcc.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
-+{
-+      return readl(ipu->cm_reg + offset);
-+}
-+
-+static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
-+{
-+      writel(value, ipu->cm_reg + offset);
-+}
-+
-+int ipu_get_num(struct ipu_soc *ipu)
-+{
-+      return ipu->id;
-+}
-+EXPORT_SYMBOL_GPL(ipu_get_num);
-+
-+void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
-+{
-+      u32 val;
-+
-+      val = ipu_cm_read(ipu, IPU_SRM_PRI2);
-+      val &= ~DP_S_SRM_MODE_MASK;
-+      val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
-+                    DP_S_SRM_MODE_NOW;
-+      ipu_cm_write(ipu, val, IPU_SRM_PRI2);
-+}
-+EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
-+
-+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
-+{
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_ARGB1555:
-+      case DRM_FORMAT_ABGR1555:
-+      case DRM_FORMAT_RGBA5551:
-+      case DRM_FORMAT_BGRA5551:
-+      case DRM_FORMAT_RGB565:
-+      case DRM_FORMAT_BGR565:
-+      case DRM_FORMAT_RGB888:
-+      case DRM_FORMAT_BGR888:
-+      case DRM_FORMAT_ARGB4444:
-+      case DRM_FORMAT_XRGB8888:
-+      case DRM_FORMAT_XBGR8888:
-+      case DRM_FORMAT_RGBX8888:
-+      case DRM_FORMAT_BGRX8888:
-+      case DRM_FORMAT_ARGB8888:
-+      case DRM_FORMAT_ABGR8888:
-+      case DRM_FORMAT_RGBA8888:
-+      case DRM_FORMAT_BGRA8888:
-+      case DRM_FORMAT_RGB565_A8:
-+      case DRM_FORMAT_BGR565_A8:
-+      case DRM_FORMAT_RGB888_A8:
-+      case DRM_FORMAT_BGR888_A8:
-+      case DRM_FORMAT_RGBX8888_A8:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              return IPUV3_COLORSPACE_RGB;
-+      case DRM_FORMAT_YUYV:
-+      case DRM_FORMAT_UYVY:
-+      case DRM_FORMAT_YUV420:
-+      case DRM_FORMAT_YVU420:
-+      case DRM_FORMAT_YUV422:
-+      case DRM_FORMAT_YVU422:
-+      case DRM_FORMAT_YUV444:
-+      case DRM_FORMAT_YVU444:
-+      case DRM_FORMAT_NV12:
-+      case DRM_FORMAT_NV21:
-+      case DRM_FORMAT_NV16:
-+      case DRM_FORMAT_NV61:
-+              return IPUV3_COLORSPACE_YUV;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
-+
-+enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_UYVY:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              return IPUV3_COLORSPACE_YUV;
-+      case V4L2_PIX_FMT_RGB565:
-+      case V4L2_PIX_FMT_BGR24:
-+      case V4L2_PIX_FMT_RGB24:
-+      case V4L2_PIX_FMT_ABGR32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_BGRA32:
-+      case V4L2_PIX_FMT_BGRX32:
-+      case V4L2_PIX_FMT_RGBA32:
-+      case V4L2_PIX_FMT_RGBX32:
-+      case V4L2_PIX_FMT_ARGB32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              return IPUV3_COLORSPACE_RGB;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
-+
-+bool ipu_pixelformat_is_planar(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              return true;
-+      }
-+
-+      return false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
-+
-+enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
-+{
-+      switch (mbus_code & 0xf000) {
-+      case 0x1000:
-+              return IPUV3_COLORSPACE_RGB;
-+      case 0x2000:
-+              return IPUV3_COLORSPACE_YUV;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
-+
-+int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              /*
-+               * for the planar YUV formats, the stride passed to
-+               * cpmem must be the stride in bytes of the Y plane.
-+               * And all the planar YUV formats have an 8-bit
-+               * Y component.
-+               */
-+              return (8 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_RGB565:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_UYVY:
-+              return (16 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_BGR24:
-+      case V4L2_PIX_FMT_RGB24:
-+              return (24 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_BGR32:
-+      case V4L2_PIX_FMT_RGB32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              return (32 * pixel_stride) >> 3;
-+      default:
-+              break;
-+      }
-+
-+      return -EINVAL;
-+}
-+EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
-+
-+int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
-+                          bool hflip, bool vflip)
-+{
-+      u32 r90, vf, hf;
-+
-+      switch (degrees) {
-+      case 0:
-+              vf = hf = r90 = 0;
-+              break;
-+      case 90:
-+              vf = hf = 0;
-+              r90 = 1;
-+              break;
-+      case 180:
-+              vf = hf = 1;
-+              r90 = 0;
-+              break;
-+      case 270:
-+              vf = hf = r90 = 1;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      hf ^= (u32)hflip;
-+      vf ^= (u32)vflip;
-+
-+      *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
-+
-+int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
-+                          bool hflip, bool vflip)
-+{
-+      u32 r90, vf, hf;
-+
-+      r90 = ((u32)mode >> 2) & 0x1;
-+      hf = ((u32)mode >> 1) & 0x1;
-+      vf = ((u32)mode >> 0) & 0x1;
-+      hf ^= (u32)hflip;
-+      vf ^= (u32)vflip;
-+
-+      switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
-+      case IPU_ROTATE_NONE:
-+              *degrees = 0;
-+              break;
-+      case IPU_ROTATE_90_RIGHT:
-+              *degrees = 90;
-+              break;
-+      case IPU_ROTATE_180:
-+              *degrees = 180;
-+              break;
-+      case IPU_ROTATE_90_LEFT:
-+              *degrees = 270;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
-+
-+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
-+{
-+      struct ipuv3_channel *channel;
-+
-+      dev_dbg(ipu->dev, "%s %d\n", __func__, num);
-+
-+      if (num > 63)
-+              return ERR_PTR(-ENODEV);
-+
-+      mutex_lock(&ipu->channel_lock);
-+
-+      list_for_each_entry(channel, &ipu->channels, list) {
-+              if (channel->num == num) {
-+                      channel = ERR_PTR(-EBUSY);
-+                      goto out;
-+              }
-+      }
-+
-+      channel = kzalloc(sizeof(*channel), GFP_KERNEL);
-+      if (!channel) {
-+              channel = ERR_PTR(-ENOMEM);
-+              goto out;
-+      }
-+
-+      channel->num = num;
-+      channel->ipu = ipu;
-+      list_add(&channel->list, &ipu->channels);
-+
-+out:
-+      mutex_unlock(&ipu->channel_lock);
-+
-+      return channel;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_get);
-+
-+void ipu_idmac_put(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+
-+      dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
-+
-+      mutex_lock(&ipu->channel_lock);
-+
-+      list_del(&channel->list);
-+      kfree(channel);
-+
-+      mutex_unlock(&ipu->channel_lock);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_put);
-+
-+#define idma_mask(ch)                 (1 << ((ch) & 0x1f))
-+
-+/*
-+ * This is an undocumented feature, a write one to a channel bit in
-+ * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
-+ * internal current buffer pointer so that transfers start from buffer
-+ * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
-+ * only says these are read-only registers). This operation is required
-+ * for channel linking to work correctly, for instance video capture
-+ * pipelines that carry out image rotations will fail after the first
-+ * streaming unless this function is called for each channel before
-+ * re-enabling the channels.
-+ */
-+static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+
-+      ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
-+}
-+
-+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
-+              bool doublebuffer)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-+      if (doublebuffer)
-+              reg |= idma_mask(channel->num);
-+      else
-+              reg &= ~idma_mask(channel->num);
-+      ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
-+
-+      __ipu_idmac_reset_current_buffer(channel);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
-+
-+static const struct {
-+      int chnum;
-+      u32 reg;
-+      int shift;
-+} idmac_lock_en_info[] = {
-+      { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
-+      { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
-+      { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
-+      { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
-+      { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
-+      { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
-+      { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
-+      { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
-+      { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
-+      { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
-+      { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
-+      { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
-+      { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
-+      { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
-+      { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
-+      { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
-+      { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
-+};
-+
-+int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 bursts, regval;
-+      int i;
-+
-+      switch (num_bursts) {
-+      case 0:
-+      case 1:
-+              bursts = 0x00; /* locking disabled */
-+              break;
-+      case 2:
-+              bursts = 0x01;
-+              break;
-+      case 4:
-+              bursts = 0x02;
-+              break;
-+      case 8:
-+              bursts = 0x03;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      /*
-+       * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
-+       * i.MX53 channel arbitration locking doesn't seem to work properly.
-+       * Allow enabling the lock feature on IPUv3H / i.MX6 only.
-+       */
-+      if (bursts && ipu->ipu_type != IPUV3H)
-+              return -EINVAL;
-+
-+      for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
-+              if (channel->num == idmac_lock_en_info[i].chnum)
-+                      break;
-+      }
-+      if (i >= ARRAY_SIZE(idmac_lock_en_info))
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
-+      regval &= ~(0x03 << idmac_lock_en_info[i].shift);
-+      regval |= (bursts << idmac_lock_en_info[i].shift);
-+      ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
-+
-+int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
-+{
-+      unsigned long lock_flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, lock_flags);
-+
-+      val = ipu_cm_read(ipu, IPU_DISP_GEN);
-+
-+      if (mask & IPU_CONF_DI0_EN)
-+              val |= IPU_DI0_COUNTER_RELEASE;
-+      if (mask & IPU_CONF_DI1_EN)
-+              val |= IPU_DI1_COUNTER_RELEASE;
-+
-+      ipu_cm_write(ipu, val, IPU_DISP_GEN);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      val |= mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, lock_flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_module_enable);
-+
-+int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
-+{
-+      unsigned long lock_flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, lock_flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      val &= ~mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      val = ipu_cm_read(ipu, IPU_DISP_GEN);
-+
-+      if (mask & IPU_CONF_DI0_EN)
-+              val &= ~IPU_DI0_COUNTER_RELEASE;
-+      if (mask & IPU_CONF_DI1_EN)
-+              val &= ~IPU_DI1_COUNTER_RELEASE;
-+
-+      ipu_cm_write(ipu, val, IPU_DISP_GEN);
-+
-+      spin_unlock_irqrestore(&ipu->lock, lock_flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_module_disable);
-+
-+int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+
-+      return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
-+
-+bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 reg = 0;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+      switch (buf_num) {
-+      case 0:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
-+              break;
-+      case 1:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
-+              break;
-+      case 2:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
-+              break;
-+      }
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return ((reg & idma_mask(channel->num)) != 0);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
-+
-+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      /* Mark buffer as ready. */
-+      if (buf_num == 0)
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
-+      else
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
-+
-+void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
-+      switch (buf_num) {
-+      case 0:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
-+              break;
-+      case 1:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
-+              break;
-+      case 2:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
-+              break;
-+      default:
-+              break;
-+      }
-+      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
-+
-+int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      u32 val;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-+      val |= idma_mask(channel->num);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
-+
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
-+{
-+      return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
-+
-+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long timeout;
-+
-+      timeout = jiffies + msecs_to_jiffies(ms);
-+      while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              if (time_after(jiffies, timeout))
-+                      return -ETIMEDOUT;
-+              cpu_relax();
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
-+
-+int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      u32 val;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      /* Disable DMA channel(s) */
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-+      val &= ~idma_mask(channel->num);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-+
-+      __ipu_idmac_reset_current_buffer(channel);
-+
-+      /* Set channel buffers NOT to be ready */
-+      ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
-+
-+      if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              ipu_cm_write(ipu, idma_mask(channel->num),
-+                           IPU_CHA_BUF0_RDY(channel->num));
-+      }
-+
-+      if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              ipu_cm_write(ipu, idma_mask(channel->num),
-+                           IPU_CHA_BUF1_RDY(channel->num));
-+      }
-+
-+      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-+
-+      /* Reset the double buffer */
-+      val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-+      val &= ~idma_mask(channel->num);
-+      ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
-+
-+/*
-+ * The imx6 rev. D TRM says that enabling the WM feature will increase
-+ * a channel's priority. Refer to Table 36-8 Calculated priority value.
-+ * The sub-module that is the sink or source for the channel must enable
-+ * watermark signal for this to take effect (SMFC_WM for instance).
-+ */
-+void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
-+      if (enable)
-+              val |= 1 << (channel->num % 32);
-+      else
-+              val &= ~(1 << (channel->num % 32));
-+      ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
-+
-+static int ipu_memory_reset(struct ipu_soc *ipu)
-+{
-+      unsigned long timeout;
-+
-+      ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
-+
-+      timeout = jiffies + msecs_to_jiffies(1000);
-+      while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
-+              if (time_after(jiffies, timeout))
-+                      return -ETIME;
-+              cpu_relax();
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Set the source mux for the given CSI. Selects either parallel or
-+ * MIPI CSI2 sources.
-+ */
-+void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
-+{
-+      unsigned long flags;
-+      u32 val, mask;
-+
-+      mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
-+              IPU_CONF_CSI0_DATA_SOURCE;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      if (mipi_csi2)
-+              val |= mask;
-+      else
-+              val &= ~mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
-+
-+/*
-+ * Set the source mux for the IC. Selects either CSI[01] or the VDI.
-+ */
-+void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
-+{
-+      unsigned long flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      if (vdi)
-+              val |= IPU_CONF_IC_INPUT;
-+      else
-+              val &= ~IPU_CONF_IC_INPUT;
-+
-+      if (csi_id == 1)
-+              val |= IPU_CONF_CSI_SEL;
-+      else
-+              val &= ~IPU_CONF_CSI_SEL;
-+
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
-+
-+
-+/* Frame Synchronization Unit Channel Linking */
-+
-+struct fsu_link_reg_info {
-+      int chno;
-+      u32 reg;
-+      u32 mask;
-+      u32 val;
-+};
-+
-+struct fsu_link_info {
-+      struct fsu_link_reg_info src;
-+      struct fsu_link_reg_info sink;
-+};
-+
-+static const struct fsu_link_info fsu_link_info[] = {
-+      {
-+              .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
-+                        FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
-+                        FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
-+                        FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
-+              .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
-+                        FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
-+      },
-+};
-+
-+static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
-+              if (src == fsu_link_info[i].src.chno &&
-+                  sink == fsu_link_info[i].sink.chno)
-+                      return &fsu_link_info[i];
-+      }
-+
-+      return NULL;
-+}
-+
-+/*
-+ * Links a source channel to a sink channel in the FSU.
-+ */
-+int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
-+{
-+      const struct fsu_link_info *link;
-+      u32 src_reg, sink_reg;
-+      unsigned long flags;
-+
-+      link = find_fsu_link_info(src_ch, sink_ch);
-+      if (!link)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      if (link->src.mask) {
-+              src_reg = ipu_cm_read(ipu, link->src.reg);
-+              src_reg &= ~link->src.mask;
-+              src_reg |= link->src.val;
-+              ipu_cm_write(ipu, src_reg, link->src.reg);
-+      }
-+
-+      if (link->sink.mask) {
-+              sink_reg = ipu_cm_read(ipu, link->sink.reg);
-+              sink_reg &= ~link->sink.mask;
-+              sink_reg |= link->sink.val;
-+              ipu_cm_write(ipu, sink_reg, link->sink.reg);
-+      }
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_fsu_link);
-+
-+/*
-+ * Unlinks source and sink channels in the FSU.
-+ */
-+int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
-+{
-+      const struct fsu_link_info *link;
-+      u32 src_reg, sink_reg;
-+      unsigned long flags;
-+
-+      link = find_fsu_link_info(src_ch, sink_ch);
-+      if (!link)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      if (link->src.mask) {
-+              src_reg = ipu_cm_read(ipu, link->src.reg);
-+              src_reg &= ~link->src.mask;
-+              ipu_cm_write(ipu, src_reg, link->src.reg);
-+      }
-+
-+      if (link->sink.mask) {
-+              sink_reg = ipu_cm_read(ipu, link->sink.reg);
-+              sink_reg &= ~link->sink.mask;
-+              ipu_cm_write(ipu, sink_reg, link->sink.reg);
-+      }
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
-+
-+/* Link IDMAC channels in the FSU */
-+int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
-+{
-+      return ipu_fsu_link(src->ipu, src->num, sink->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_link);
-+
-+/* Unlink IDMAC channels in the FSU */
-+int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
-+{
-+      return ipu_fsu_unlink(src->ipu, src->num, sink->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
-+
-+struct ipu_devtype {
-+      const char *name;
-+      unsigned long cm_ofs;
-+      unsigned long cpmem_ofs;
-+      unsigned long srm_ofs;
-+      unsigned long tpm_ofs;
-+      unsigned long csi0_ofs;
-+      unsigned long csi1_ofs;
-+      unsigned long ic_ofs;
-+      unsigned long disp0_ofs;
-+      unsigned long disp1_ofs;
-+      unsigned long dc_tmpl_ofs;
-+      unsigned long vdi_ofs;
-+      enum ipuv3_type type;
-+};
-+
-+static struct ipu_devtype ipu_type_imx51 = {
-+      .name = "IPUv3EX",
-+      .cm_ofs = 0x1e000000,
-+      .cpmem_ofs = 0x1f000000,
-+      .srm_ofs = 0x1f040000,
-+      .tpm_ofs = 0x1f060000,
-+      .csi0_ofs = 0x1e030000,
-+      .csi1_ofs = 0x1e038000,
-+      .ic_ofs = 0x1e020000,
-+      .disp0_ofs = 0x1e040000,
-+      .disp1_ofs = 0x1e048000,
-+      .dc_tmpl_ofs = 0x1f080000,
-+      .vdi_ofs = 0x1e068000,
-+      .type = IPUV3EX,
-+};
-+
-+static struct ipu_devtype ipu_type_imx53 = {
-+      .name = "IPUv3M",
-+      .cm_ofs = 0x06000000,
-+      .cpmem_ofs = 0x07000000,
-+      .srm_ofs = 0x07040000,
-+      .tpm_ofs = 0x07060000,
-+      .csi0_ofs = 0x06030000,
-+      .csi1_ofs = 0x06038000,
-+      .ic_ofs = 0x06020000,
-+      .disp0_ofs = 0x06040000,
-+      .disp1_ofs = 0x06048000,
-+      .dc_tmpl_ofs = 0x07080000,
-+      .vdi_ofs = 0x06068000,
-+      .type = IPUV3M,
-+};
-+
-+static struct ipu_devtype ipu_type_imx6q = {
-+      .name = "IPUv3H",
-+      .cm_ofs = 0x00200000,
-+      .cpmem_ofs = 0x00300000,
-+      .srm_ofs = 0x00340000,
-+      .tpm_ofs = 0x00360000,
-+      .csi0_ofs = 0x00230000,
-+      .csi1_ofs = 0x00238000,
-+      .ic_ofs = 0x00220000,
-+      .disp0_ofs = 0x00240000,
-+      .disp1_ofs = 0x00248000,
-+      .dc_tmpl_ofs = 0x00380000,
-+      .vdi_ofs = 0x00268000,
-+      .type = IPUV3H,
-+};
-+
-+static const struct of_device_id imx_ipu_dt_ids[] = {
-+      { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
-+      { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
-+      { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
-+      { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
-+
-+static int ipu_submodules_init(struct ipu_soc *ipu,
-+              struct platform_device *pdev, unsigned long ipu_base,
-+              struct clk *ipu_clk)
-+{
-+      char *unit;
-+      int ret;
-+      struct device *dev = &pdev->dev;
-+      const struct ipu_devtype *devtype = ipu->devtype;
-+
-+      ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
-+      if (ret) {
-+              unit = "cpmem";
-+              goto err_cpmem;
-+      }
-+
-+      ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
-+                         IPU_CONF_CSI0_EN, ipu_clk);
-+      if (ret) {
-+              unit = "csi0";
-+              goto err_csi_0;
-+      }
-+
-+      ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
-+                         IPU_CONF_CSI1_EN, ipu_clk);
-+      if (ret) {
-+              unit = "csi1";
-+              goto err_csi_1;
-+      }
-+
-+      ret = ipu_ic_init(ipu, dev,
-+                        ipu_base + devtype->ic_ofs,
-+                        ipu_base + devtype->tpm_ofs);
-+      if (ret) {
-+              unit = "ic";
-+              goto err_ic;
-+      }
-+
-+      ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
-+                         IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
-+                         IPU_CONF_IC_INPUT);
-+      if (ret) {
-+              unit = "vdi";
-+              goto err_vdi;
-+      }
-+
-+      ret = ipu_image_convert_init(ipu, dev);
-+      if (ret) {
-+              unit = "image_convert";
-+              goto err_image_convert;
-+      }
-+
-+      ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
-+                        IPU_CONF_DI0_EN, ipu_clk);
-+      if (ret) {
-+              unit = "di0";
-+              goto err_di_0;
-+      }
-+
-+      ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
-+                      IPU_CONF_DI1_EN, ipu_clk);
-+      if (ret) {
-+              unit = "di1";
-+              goto err_di_1;
-+      }
-+
-+      ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
-+                      IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
-+      if (ret) {
-+              unit = "dc_template";
-+              goto err_dc;
-+      }
-+
-+      ret = ipu_dmfc_init(ipu, dev, ipu_base +
-+                      devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
-+      if (ret) {
-+              unit = "dmfc";
-+              goto err_dmfc;
-+      }
-+
-+      ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
-+      if (ret) {
-+              unit = "dp";
-+              goto err_dp;
-+      }
-+
-+      ret = ipu_smfc_init(ipu, dev, ipu_base +
-+                      devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
-+      if (ret) {
-+              unit = "smfc";
-+              goto err_smfc;
-+      }
-+
-+      return 0;
-+
-+err_smfc:
-+      ipu_dp_exit(ipu);
-+err_dp:
-+      ipu_dmfc_exit(ipu);
-+err_dmfc:
-+      ipu_dc_exit(ipu);
-+err_dc:
-+      ipu_di_exit(ipu, 1);
-+err_di_1:
-+      ipu_di_exit(ipu, 0);
-+err_di_0:
-+      ipu_image_convert_exit(ipu);
-+err_image_convert:
-+      ipu_vdi_exit(ipu);
-+err_vdi:
-+      ipu_ic_exit(ipu);
-+err_ic:
-+      ipu_csi_exit(ipu, 1);
-+err_csi_1:
-+      ipu_csi_exit(ipu, 0);
-+err_csi_0:
-+      ipu_cpmem_exit(ipu);
-+err_cpmem:
-+      dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
-+      return ret;
-+}
-+
-+static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
-+{
-+      unsigned long status;
-+      int i, bit, irq;
-+
-+      for (i = 0; i < num_regs; i++) {
-+
-+              status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
-+              status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
-+
-+              for_each_set_bit(bit, &status, 32) {
-+                      irq = irq_linear_revmap(ipu->domain,
-+                                              regs[i] * 32 + bit);
-+                      if (irq)
-+                              generic_handle_irq(irq);
-+              }
-+      }
-+}
-+
-+static void ipu_irq_handler(struct irq_desc *desc)
-+{
-+      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
-+
-+      chained_irq_enter(chip, desc);
-+
-+      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void ipu_err_irq_handler(struct irq_desc *desc)
-+{
-+      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      static const int int_reg[] = { 4, 5, 8, 9};
-+
-+      chained_irq_enter(chip, desc);
-+
-+      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+int ipu_map_irq(struct ipu_soc *ipu, int irq)
-+{
-+      int virq;
-+
-+      virq = irq_linear_revmap(ipu->domain, irq);
-+      if (!virq)
-+              virq = irq_create_mapping(ipu->domain, irq);
-+
-+      return virq;
-+}
-+EXPORT_SYMBOL_GPL(ipu_map_irq);
-+
-+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-+              enum ipu_channel_irq irq_type)
-+{
-+      return ipu_map_irq(ipu, irq_type + channel->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
-+
-+static void ipu_submodules_exit(struct ipu_soc *ipu)
-+{
-+      ipu_smfc_exit(ipu);
-+      ipu_dp_exit(ipu);
-+      ipu_dmfc_exit(ipu);
-+      ipu_dc_exit(ipu);
-+      ipu_di_exit(ipu, 1);
-+      ipu_di_exit(ipu, 0);
-+      ipu_image_convert_exit(ipu);
-+      ipu_vdi_exit(ipu);
-+      ipu_ic_exit(ipu);
-+      ipu_csi_exit(ipu, 1);
-+      ipu_csi_exit(ipu, 0);
-+      ipu_cpmem_exit(ipu);
-+}
-+
-+static int platform_remove_devices_fn(struct device *dev, void *unused)
-+{
-+      struct platform_device *pdev = to_platform_device(dev);
-+
-+      platform_device_unregister(pdev);
-+
-+      return 0;
-+}
-+
-+static void platform_device_unregister_children(struct platform_device *pdev)
-+{
-+      device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
-+}
-+
-+struct ipu_platform_reg {
-+      struct ipu_client_platformdata pdata;
-+      const char *name;
-+};
-+
-+/* These must be in the order of the corresponding device tree port nodes */
-+static struct ipu_platform_reg client_reg[] = {
-+      {
-+              .pdata = {
-+                      .csi = 0,
-+                      .dma[0] = IPUV3_CHANNEL_CSI0,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-csi",
-+      }, {
-+              .pdata = {
-+                      .csi = 1,
-+                      .dma[0] = IPUV3_CHANNEL_CSI1,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-csi",
-+      }, {
-+              .pdata = {
-+                      .di = 0,
-+                      .dc = 5,
-+                      .dp = IPU_DP_FLOW_SYNC_BG,
-+                      .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-+                      .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
-+              },
-+              .name = "imx-ipuv3-crtc",
-+      }, {
-+              .pdata = {
-+                      .di = 1,
-+                      .dc = 1,
-+                      .dp = -EINVAL,
-+                      .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-crtc",
-+      },
-+};
-+
-+static DEFINE_MUTEX(ipu_client_id_mutex);
-+static int ipu_client_id;
-+
-+static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
-+{
-+      struct device *dev = ipu->dev;
-+      unsigned i;
-+      int id, ret;
-+
-+      mutex_lock(&ipu_client_id_mutex);
-+      id = ipu_client_id;
-+      ipu_client_id += ARRAY_SIZE(client_reg);
-+      mutex_unlock(&ipu_client_id_mutex);
-+
-+      for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-+              struct ipu_platform_reg *reg = &client_reg[i];
-+              struct platform_device *pdev;
-+              struct device_node *of_node;
-+
-+              /* Associate subdevice with the corresponding port node */
-+              of_node = of_graph_get_port_by_id(dev->of_node, i);
-+              if (!of_node) {
-+                      dev_info(dev,
-+                               "no port@%d node in %pOF, not using %s%d\n",
-+                               i, dev->of_node,
-+                               (i / 2) ? "DI" : "CSI", i % 2);
-+                      continue;
-+              }
-+
-+              pdev = platform_device_alloc(reg->name, id++);
-+              if (!pdev) {
-+                      ret = -ENOMEM;
-+                      goto err_register;
-+              }
-+
-+              pdev->dev.parent = dev;
-+
-+              reg->pdata.of_node = of_node;
-+              ret = platform_device_add_data(pdev, &reg->pdata,
-+                                             sizeof(reg->pdata));
-+              if (!ret)
-+                      ret = platform_device_add(pdev);
-+              if (ret) {
-+                      platform_device_put(pdev);
-+                      goto err_register;
-+              }
-+      }
-+
-+      return 0;
-+
-+err_register:
-+      platform_device_unregister_children(to_platform_device(dev));
-+
-+      return ret;
-+}
-+
-+
-+static int ipu_irq_init(struct ipu_soc *ipu)
-+{
-+      struct irq_chip_generic *gc;
-+      struct irq_chip_type *ct;
-+      unsigned long unused[IPU_NUM_IRQS / 32] = {
-+              0x400100d0, 0xffe000fd,
-+              0x400100d0, 0xffe000fd,
-+              0x400100d0, 0xffe000fd,
-+              0x4077ffff, 0xffe7e1fd,
-+              0x23fffffe, 0x8880fff0,
-+              0xf98fe7d0, 0xfff81fff,
-+              0x400100d0, 0xffe000fd,
-+              0x00000000,
-+      };
-+      int ret, i;
-+
-+      ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
-+                                          &irq_generic_chip_ops, ipu);
-+      if (!ipu->domain) {
-+              dev_err(ipu->dev, "failed to add irq domain\n");
-+              return -ENODEV;
-+      }
-+
-+      ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
-+                                           handle_level_irq, 0, 0, 0);
-+      if (ret < 0) {
-+              dev_err(ipu->dev, "failed to alloc generic irq chips\n");
-+              irq_domain_remove(ipu->domain);
-+              return ret;
-+      }
-+
-+      /* Mask and clear all interrupts */
-+      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
-+              ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
-+              ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
-+      }
-+
-+      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
-+              gc = irq_get_domain_generic_chip(ipu->domain, i);
-+              gc->reg_base = ipu->cm_reg;
-+              gc->unused = unused[i / 32];
-+              ct = gc->chip_types;
-+              ct->chip.irq_ack = irq_gc_ack_set_bit;
-+              ct->chip.irq_mask = irq_gc_mask_clr_bit;
-+              ct->chip.irq_unmask = irq_gc_mask_set_bit;
-+              ct->regs.ack = IPU_INT_STAT(i / 32);
-+              ct->regs.mask = IPU_INT_CTRL(i / 32);
-+      }
-+
-+      irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
-+      irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
-+                                       ipu);
-+
-+      return 0;
-+}
-+
-+static void ipu_irq_exit(struct ipu_soc *ipu)
-+{
-+      int i, irq;
-+
-+      irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
-+      irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
-+
-+      /* TODO: remove irq_domain_generic_chips */
-+
-+      for (i = 0; i < IPU_NUM_IRQS; i++) {
-+              irq = irq_linear_revmap(ipu->domain, i);
-+              if (irq)
-+                      irq_dispose_mapping(irq);
-+      }
-+
-+      irq_domain_remove(ipu->domain);
-+}
-+
-+void ipu_dump(struct ipu_soc *ipu)
-+{
-+      int i;
-+
-+      dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CONF));
-+      dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CONF));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
-+      dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
-+      dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
-+      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
-+      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
-+      dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
-+      for (i = 0; i < 15; i++)
-+              dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
-+                      ipu_cm_read(ipu, IPU_INT_CTRL(i)));
-+}
-+EXPORT_SYMBOL_GPL(ipu_dump);
-+
-+static int ipu_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      struct ipu_soc *ipu;
-+      struct resource *res;
-+      unsigned long ipu_base;
-+      int ret, irq_sync, irq_err;
-+      const struct ipu_devtype *devtype;
-+
-+      devtype = of_device_get_match_data(&pdev->dev);
-+      if (!devtype)
-+              return -EINVAL;
-+
-+      irq_sync = platform_get_irq(pdev, 0);
-+      irq_err = platform_get_irq(pdev, 1);
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+      dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
-+                      irq_sync, irq_err);
-+
-+      if (!res || irq_sync < 0 || irq_err < 0)
-+              return -ENODEV;
-+
-+      ipu_base = res->start;
-+
-+      ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
-+      if (!ipu)
-+              return -ENODEV;
-+
-+      ipu->id = of_alias_get_id(np, "ipu");
-+      if (ipu->id < 0)
-+              ipu->id = 0;
-+
-+      if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
-+          IS_ENABLED(CONFIG_DRM)) {
-+              ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
-+                                                        "fsl,prg", ipu->id);
-+              if (!ipu->prg_priv)
-+                      return -EPROBE_DEFER;
-+      }
-+
-+      ipu->devtype = devtype;
-+      ipu->ipu_type = devtype->type;
-+
-+      spin_lock_init(&ipu->lock);
-+      mutex_init(&ipu->channel_lock);
-+      INIT_LIST_HEAD(&ipu->channels);
-+
-+      dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs);
-+      dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
-+      dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
-+                      ipu_base + devtype->cpmem_ofs);
-+      dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
-+                      ipu_base + devtype->csi0_ofs);
-+      dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
-+                      ipu_base + devtype->csi1_ofs);
-+      dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
-+                      ipu_base + devtype->ic_ofs);
-+      dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
-+                      ipu_base + devtype->disp0_ofs);
-+      dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
-+                      ipu_base + devtype->disp1_ofs);
-+      dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
-+                      ipu_base + devtype->srm_ofs);
-+      dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
-+                      ipu_base + devtype->tpm_ofs);
-+      dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
-+      dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
-+      dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
-+      dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
-+                      ipu_base + devtype->vdi_ofs);
-+
-+      ipu->cm_reg = devm_ioremap(&pdev->dev,
-+                      ipu_base + devtype->cm_ofs, PAGE_SIZE);
-+      ipu->idmac_reg = devm_ioremap(&pdev->dev,
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
-+                      PAGE_SIZE);
-+
-+      if (!ipu->cm_reg || !ipu->idmac_reg)
-+              return -ENOMEM;
-+
-+      ipu->clk = devm_clk_get(&pdev->dev, "bus");
-+      if (IS_ERR(ipu->clk)) {
-+              ret = PTR_ERR(ipu->clk);
-+              dev_err(&pdev->dev, "clk_get failed with %d", ret);
-+              return ret;
-+      }
-+
-+      platform_set_drvdata(pdev, ipu);
-+
-+      ret = clk_prepare_enable(ipu->clk);
-+      if (ret) {
-+              dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ipu->dev = &pdev->dev;
-+      ipu->irq_sync = irq_sync;
-+      ipu->irq_err = irq_err;
-+
-+      ret = device_reset(&pdev->dev);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to reset: %d\n", ret);
-+              goto out_failed_reset;
-+      }
-+      ret = ipu_memory_reset(ipu);
-+      if (ret)
-+              goto out_failed_reset;
-+
-+      ret = ipu_irq_init(ipu);
-+      if (ret)
-+              goto out_failed_irq;
-+
-+      /* Set MCU_T to divide MCU access window into 2 */
-+      ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
-+                      IPU_DISP_GEN);
-+
-+      ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
-+      if (ret)
-+              goto failed_submodules_init;
-+
-+      ret = ipu_add_client_devices(ipu, ipu_base);
-+      if (ret) {
-+              dev_err(&pdev->dev, "adding client devices failed with %d\n",
-+                              ret);
-+              goto failed_add_clients;
-+      }
-+
-+      dev_info(&pdev->dev, "%s probed\n", devtype->name);
-+
-+      return 0;
-+
-+failed_add_clients:
-+      ipu_submodules_exit(ipu);
-+failed_submodules_init:
-+      ipu_irq_exit(ipu);
-+out_failed_irq:
-+out_failed_reset:
-+      clk_disable_unprepare(ipu->clk);
-+      return ret;
-+}
-+
-+static int ipu_remove(struct platform_device *pdev)
-+{
-+      struct ipu_soc *ipu = platform_get_drvdata(pdev);
-+
-+      platform_device_unregister_children(pdev);
-+      ipu_submodules_exit(ipu);
-+      ipu_irq_exit(ipu);
-+
-+      clk_disable_unprepare(ipu->clk);
-+
-+      return 0;
-+}
-+
-+static struct platform_driver imx_ipu_driver = {
-+      .driver = {
-+              .name = "imx-ipuv3",
-+              .of_match_table = imx_ipu_dt_ids,
-+      },
-+      .probe = ipu_probe,
-+      .remove = ipu_remove,
-+};
-+
-+static struct platform_driver * const drivers[] = {
-+#if IS_ENABLED(CONFIG_DRM)
-+      &ipu_pre_drv,
-+      &ipu_prg_drv,
-+#endif
-+      &imx_ipu_driver,
-+};
-+
-+static int __init imx_ipu_init(void)
-+{
-+      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_init(imx_ipu_init);
-+
-+static void __exit imx_ipu_exit(void)
-+{
-+      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_exit(imx_ipu_exit);
-+
-+MODULE_ALIAS("platform:imx-ipuv3");
-+MODULE_DESCRIPTION("i.MX IPU v3 driver");
-+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-cpmem.c
-@@ -0,0 +1,976 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012 Mentor Graphics Inc.
-+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+#include <linux/types.h>
-+#include <linux/bitrev.h>
-+#include <linux/io.h>
-+#include <linux/sizes.h>
-+#include <drm/drm_fourcc.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_cpmem_word {
-+      u32 data[5];
-+      u32 res[3];
-+};
-+
-+struct ipu_ch_param {
-+      struct ipu_cpmem_word word[2];
-+};
-+
-+struct ipu_cpmem {
-+      struct ipu_ch_param __iomem *base;
-+      u32 module;
-+      spinlock_t lock;
-+      int use_count;
-+      struct ipu_soc *ipu;
-+};
-+
-+#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
-+
-+#define IPU_FIELD_UBO         IPU_CPMEM_WORD(0, 46, 22)
-+#define IPU_FIELD_VBO         IPU_CPMEM_WORD(0, 68, 22)
-+#define IPU_FIELD_IOX         IPU_CPMEM_WORD(0, 90, 4)
-+#define IPU_FIELD_RDRW                IPU_CPMEM_WORD(0, 94, 1)
-+#define IPU_FIELD_SO          IPU_CPMEM_WORD(0, 113, 1)
-+#define IPU_FIELD_SLY         IPU_CPMEM_WORD(1, 102, 14)
-+#define IPU_FIELD_SLUV                IPU_CPMEM_WORD(1, 128, 14)
-+
-+#define IPU_FIELD_XV          IPU_CPMEM_WORD(0, 0, 10)
-+#define IPU_FIELD_YV          IPU_CPMEM_WORD(0, 10, 9)
-+#define IPU_FIELD_XB          IPU_CPMEM_WORD(0, 19, 13)
-+#define IPU_FIELD_YB          IPU_CPMEM_WORD(0, 32, 12)
-+#define IPU_FIELD_NSB_B               IPU_CPMEM_WORD(0, 44, 1)
-+#define IPU_FIELD_CF          IPU_CPMEM_WORD(0, 45, 1)
-+#define IPU_FIELD_SX          IPU_CPMEM_WORD(0, 46, 12)
-+#define IPU_FIELD_SY          IPU_CPMEM_WORD(0, 58, 11)
-+#define IPU_FIELD_NS          IPU_CPMEM_WORD(0, 69, 10)
-+#define IPU_FIELD_SDX         IPU_CPMEM_WORD(0, 79, 7)
-+#define IPU_FIELD_SM          IPU_CPMEM_WORD(0, 86, 10)
-+#define IPU_FIELD_SCC         IPU_CPMEM_WORD(0, 96, 1)
-+#define IPU_FIELD_SCE         IPU_CPMEM_WORD(0, 97, 1)
-+#define IPU_FIELD_SDY         IPU_CPMEM_WORD(0, 98, 7)
-+#define IPU_FIELD_SDRX                IPU_CPMEM_WORD(0, 105, 1)
-+#define IPU_FIELD_SDRY                IPU_CPMEM_WORD(0, 106, 1)
-+#define IPU_FIELD_BPP         IPU_CPMEM_WORD(0, 107, 3)
-+#define IPU_FIELD_DEC_SEL     IPU_CPMEM_WORD(0, 110, 2)
-+#define IPU_FIELD_DIM         IPU_CPMEM_WORD(0, 112, 1)
-+#define IPU_FIELD_BNDM                IPU_CPMEM_WORD(0, 114, 3)
-+#define IPU_FIELD_BM          IPU_CPMEM_WORD(0, 117, 2)
-+#define IPU_FIELD_ROT         IPU_CPMEM_WORD(0, 119, 1)
-+#define IPU_FIELD_ROT_HF_VF   IPU_CPMEM_WORD(0, 119, 3)
-+#define IPU_FIELD_HF          IPU_CPMEM_WORD(0, 120, 1)
-+#define IPU_FIELD_VF          IPU_CPMEM_WORD(0, 121, 1)
-+#define IPU_FIELD_THE         IPU_CPMEM_WORD(0, 122, 1)
-+#define IPU_FIELD_CAP         IPU_CPMEM_WORD(0, 123, 1)
-+#define IPU_FIELD_CAE         IPU_CPMEM_WORD(0, 124, 1)
-+#define IPU_FIELD_FW          IPU_CPMEM_WORD(0, 125, 13)
-+#define IPU_FIELD_FH          IPU_CPMEM_WORD(0, 138, 12)
-+#define IPU_FIELD_EBA0                IPU_CPMEM_WORD(1, 0, 29)
-+#define IPU_FIELD_EBA1                IPU_CPMEM_WORD(1, 29, 29)
-+#define IPU_FIELD_ILO         IPU_CPMEM_WORD(1, 58, 20)
-+#define IPU_FIELD_NPB         IPU_CPMEM_WORD(1, 78, 7)
-+#define IPU_FIELD_PFS         IPU_CPMEM_WORD(1, 85, 4)
-+#define IPU_FIELD_ALU         IPU_CPMEM_WORD(1, 89, 1)
-+#define IPU_FIELD_ALBM                IPU_CPMEM_WORD(1, 90, 3)
-+#define IPU_FIELD_ID          IPU_CPMEM_WORD(1, 93, 2)
-+#define IPU_FIELD_TH          IPU_CPMEM_WORD(1, 95, 7)
-+#define IPU_FIELD_SL          IPU_CPMEM_WORD(1, 102, 14)
-+#define IPU_FIELD_WID0                IPU_CPMEM_WORD(1, 116, 3)
-+#define IPU_FIELD_WID1                IPU_CPMEM_WORD(1, 119, 3)
-+#define IPU_FIELD_WID2                IPU_CPMEM_WORD(1, 122, 3)
-+#define IPU_FIELD_WID3                IPU_CPMEM_WORD(1, 125, 3)
-+#define IPU_FIELD_OFS0                IPU_CPMEM_WORD(1, 128, 5)
-+#define IPU_FIELD_OFS1                IPU_CPMEM_WORD(1, 133, 5)
-+#define IPU_FIELD_OFS2                IPU_CPMEM_WORD(1, 138, 5)
-+#define IPU_FIELD_OFS3                IPU_CPMEM_WORD(1, 143, 5)
-+#define IPU_FIELD_SXYS                IPU_CPMEM_WORD(1, 148, 1)
-+#define IPU_FIELD_CRE         IPU_CPMEM_WORD(1, 149, 1)
-+#define IPU_FIELD_DEC_SEL2    IPU_CPMEM_WORD(1, 150, 1)
-+
-+static inline struct ipu_ch_param __iomem *
-+ipu_get_cpmem(struct ipuv3_channel *ch)
-+{
-+      struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
-+
-+      return cpmem->base + ch->num;
-+}
-+
-+static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
-+{
-+      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
-+      u32 bit = (wbs >> 8) % 160;
-+      u32 size = wbs & 0xff;
-+      u32 word = (wbs >> 8) / 160;
-+      u32 i = bit / 32;
-+      u32 ofs = bit % 32;
-+      u32 mask = (1 << size) - 1;
-+      u32 val;
-+
-+      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-+
-+      val = readl(&base->word[word].data[i]);
-+      val &= ~(mask << ofs);
-+      val |= v << ofs;
-+      writel(val, &base->word[word].data[i]);
-+
-+      if ((bit + size - 1) / 32 > i) {
-+              val = readl(&base->word[word].data[i + 1]);
-+              val &= ~(mask >> (ofs ? (32 - ofs) : 0));
-+              val |= v >> (ofs ? (32 - ofs) : 0);
-+              writel(val, &base->word[word].data[i + 1]);
-+      }
-+}
-+
-+static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
-+{
-+      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
-+      u32 bit = (wbs >> 8) % 160;
-+      u32 size = wbs & 0xff;
-+      u32 word = (wbs >> 8) / 160;
-+      u32 i = bit / 32;
-+      u32 ofs = bit % 32;
-+      u32 mask = (1 << size) - 1;
-+      u32 val = 0;
-+
-+      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-+
-+      val = (readl(&base->word[word].data[i]) >> ofs) & mask;
-+
-+      if ((bit + size - 1) / 32 > i) {
-+              u32 tmp;
-+
-+              tmp = readl(&base->word[word].data[i + 1]);
-+              tmp &= mask >> (ofs ? (32 - ofs) : 0);
-+              val |= tmp << (ofs ? (32 - ofs) : 0);
-+      }
-+
-+      return val;
-+}
-+
-+/*
-+ * The V4L2 spec defines packed RGB formats in memory byte order, which from
-+ * point of view of the IPU corresponds to little-endian words with the first
-+ * component in the least significant bits.
-+ * The DRM pixel formats and IPU internal representation are ordered the other
-+ * way around, with the first named component ordered at the most significant
-+ * bits. Further, V4L2 formats are not well defined:
-+ *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
-+ * We choose the interpretation which matches GStreamer behavior.
-+ */
-+static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_RGB565:
-+              /*
-+               * Here we choose the 'corrected' interpretation of RGBP, a
-+               * little-endian 16-bit word with the red component at the most
-+               * significant bits:
-+               * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
-+               */
-+              return DRM_FORMAT_RGB565;
-+      case V4L2_PIX_FMT_BGR24:
-+              /* B G R <=> [24:0] R:G:B */
-+              return DRM_FORMAT_RGB888;
-+      case V4L2_PIX_FMT_RGB24:
-+              /* R G B <=> [24:0] B:G:R */
-+              return DRM_FORMAT_BGR888;
-+      case V4L2_PIX_FMT_BGR32:
-+              /* B G R A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_XRGB8888;
-+      case V4L2_PIX_FMT_RGB32:
-+              /* R G B A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_XBGR8888;
-+      case V4L2_PIX_FMT_ABGR32:
-+              /* B G R A <=> [32:0] A:R:G:B */
-+              return DRM_FORMAT_ARGB8888;
-+      case V4L2_PIX_FMT_XBGR32:
-+              /* B G R X <=> [32:0] X:R:G:B */
-+              return DRM_FORMAT_XRGB8888;
-+      case V4L2_PIX_FMT_BGRA32:
-+              /* A B G R <=> [32:0] R:G:B:A */
-+              return DRM_FORMAT_RGBA8888;
-+      case V4L2_PIX_FMT_BGRX32:
-+              /* X B G R <=> [32:0] R:G:B:X */
-+              return DRM_FORMAT_RGBX8888;
-+      case V4L2_PIX_FMT_RGBA32:
-+              /* R G B A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_ABGR8888;
-+      case V4L2_PIX_FMT_RGBX32:
-+              /* R G B X <=> [32:0] X:B:G:R */
-+              return DRM_FORMAT_XBGR8888;
-+      case V4L2_PIX_FMT_ARGB32:
-+              /* A R G B <=> [32:0] B:G:R:A */
-+              return DRM_FORMAT_BGRA8888;
-+      case V4L2_PIX_FMT_XRGB32:
-+              /* X R G B <=> [32:0] B:G:R:X */
-+              return DRM_FORMAT_BGRX8888;
-+      case V4L2_PIX_FMT_UYVY:
-+              return DRM_FORMAT_UYVY;
-+      case V4L2_PIX_FMT_YUYV:
-+              return DRM_FORMAT_YUYV;
-+      case V4L2_PIX_FMT_YUV420:
-+              return DRM_FORMAT_YUV420;
-+      case V4L2_PIX_FMT_YUV422P:
-+              return DRM_FORMAT_YUV422;
-+      case V4L2_PIX_FMT_YVU420:
-+              return DRM_FORMAT_YVU420;
-+      case V4L2_PIX_FMT_NV12:
-+              return DRM_FORMAT_NV12;
-+      case V4L2_PIX_FMT_NV16:
-+              return DRM_FORMAT_NV16;
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+void ipu_cpmem_zero(struct ipuv3_channel *ch)
-+{
-+      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
-+      void __iomem *base = p;
-+      int i;
-+
-+      for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
-+              writel(0, base + i * sizeof(u32));
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
-+
-+void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
-+
-+void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
-+
-+void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
-+
-+void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
-+{
-+      struct ipu_soc *ipu = ch->ipu;
-+      u32 val;
-+
-+      if (ipu->ipu_type == IPUV3EX)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
-+      val |= 1 << (ch->num % 32);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
-+
-+void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
-+{
-+      WARN_ON_ONCE(buf & 0x7);
-+
-+      if (bufnum)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
-+      else
-+              ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
-+
-+void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
-+{
-+      WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
-+
-+void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
-+                             u32 pixelformat)
-+{
-+      u32 ilo, sly, sluv;
-+
-+      if (stride < 0) {
-+              stride = -stride;
-+              ilo = 0x100000 - (stride / 8);
-+      } else {
-+              ilo = stride / 8;
-+      }
-+
-+      sly = (stride * 2) - 1;
-+
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+              sluv = stride / 2 - 1;
-+              break;
-+      case V4L2_PIX_FMT_NV12:
-+              sluv = stride - 1;
-+              break;
-+      case V4L2_PIX_FMT_YUV422P:
-+              sluv = stride - 1;
-+              break;
-+      case V4L2_PIX_FMT_NV16:
-+              sluv = stride * 2 - 1;
-+              break;
-+      default:
-+              sluv = 0;
-+              break;
-+      }
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
-+      if (sluv)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
-+
-+void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
-+{
-+      id &= 0x3;
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
-+
-+int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
-+{
-+      return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
-+
-+void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
-+
-+void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
-+
-+void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
-+                          enum ipu_rotate_mode rot)
-+{
-+      u32 temp_rot = bitrev8(rot) >> 5;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
-+
-+int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
-+                           const struct ipu_rgb *rgb)
-+{
-+      int bpp = 0, npb = 0, ro, go, bo, to;
-+
-+      ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
-+      go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
-+      bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
-+      to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
-+
-+      if (rgb->transp.length) {
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
-+                              rgb->transp.length - 1);
-+              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
-+      } else {
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
-+              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
-+                              rgb->bits_per_pixel);
-+      }
-+
-+      switch (rgb->bits_per_pixel) {
-+      case 32:
-+              bpp = 0;
-+              npb = 15;
-+              break;
-+      case 24:
-+              bpp = 1;
-+              npb = 19;
-+              break;
-+      case 16:
-+              bpp = 3;
-+              npb = 31;
-+              break;
-+      case 8:
-+              bpp = 5;
-+              npb = 63;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
-+
-+int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
-+{
-+      int bpp = 0, npb = 0;
-+
-+      switch (width) {
-+      case 32:
-+              bpp = 0;
-+              npb = 15;
-+              break;
-+      case 24:
-+              bpp = 1;
-+              npb = 19;
-+              break;
-+      case 16:
-+              bpp = 3;
-+              npb = 31;
-+              break;
-+      case 8:
-+              bpp = 5;
-+              npb = 63;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
-+
-+void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
-+{
-+      switch (pixel_format) {
-+      case V4L2_PIX_FMT_UYVY:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
-+              break;
-+      case V4L2_PIX_FMT_YUYV:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
-+              break;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
-+
-+void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
-+                                 unsigned int uv_stride,
-+                                 unsigned int u_offset, unsigned int v_offset)
-+{
-+      WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
-+
-+static const struct ipu_rgb def_xrgb_32 = {
-+      .red    = { .offset = 16, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset =  0, .length = 8, },
-+      .transp = { .offset = 24, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_xbgr_32 = {
-+      .red    = { .offset =  0, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset = 16, .length = 8, },
-+      .transp = { .offset = 24, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_rgbx_32 = {
-+      .red    = { .offset = 24, .length = 8, },
-+      .green  = { .offset = 16, .length = 8, },
-+      .blue   = { .offset =  8, .length = 8, },
-+      .transp = { .offset =  0, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_bgrx_32 = {
-+      .red    = { .offset =  8, .length = 8, },
-+      .green  = { .offset = 16, .length = 8, },
-+      .blue   = { .offset = 24, .length = 8, },
-+      .transp = { .offset =  0, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_rgb_24 = {
-+      .red    = { .offset = 16, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset =  0, .length = 8, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 24,
-+};
-+
-+static const struct ipu_rgb def_bgr_24 = {
-+      .red    = { .offset =  0, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset = 16, .length = 8, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 24,
-+};
-+
-+static const struct ipu_rgb def_rgb_16 = {
-+      .red    = { .offset = 11, .length = 5, },
-+      .green  = { .offset =  5, .length = 6, },
-+      .blue   = { .offset =  0, .length = 5, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_bgr_16 = {
-+      .red    = { .offset =  0, .length = 5, },
-+      .green  = { .offset =  5, .length = 6, },
-+      .blue   = { .offset = 11, .length = 5, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_argb_16 = {
-+      .red    = { .offset = 10, .length = 5, },
-+      .green  = { .offset =  5, .length = 5, },
-+      .blue   = { .offset =  0, .length = 5, },
-+      .transp = { .offset = 15, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_argb_16_4444 = {
-+      .red    = { .offset =  8, .length = 4, },
-+      .green  = { .offset =  4, .length = 4, },
-+      .blue   = { .offset =  0, .length = 4, },
-+      .transp = { .offset = 12, .length = 4, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_abgr_16 = {
-+      .red    = { .offset =  0, .length = 5, },
-+      .green  = { .offset =  5, .length = 5, },
-+      .blue   = { .offset = 10, .length = 5, },
-+      .transp = { .offset = 15, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_rgba_16 = {
-+      .red    = { .offset = 11, .length = 5, },
-+      .green  = { .offset =  6, .length = 5, },
-+      .blue   = { .offset =  1, .length = 5, },
-+      .transp = { .offset =  0, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_bgra_16 = {
-+      .red    = { .offset =  1, .length = 5, },
-+      .green  = { .offset =  6, .length = 5, },
-+      .blue   = { .offset = 11, .length = 5, },
-+      .transp = { .offset =  0, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+#define Y_OFFSET(pix, x, y)   ((x) + pix->width * (y))
-+#define U_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-+                               (pix->width * ((y) / 2) / 2) + (x) / 2)
-+#define V_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-+                               (pix->width * pix->height / 4) +       \
-+                               (pix->width * ((y) / 2) / 2) + (x) / 2)
-+#define U2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
-+                               (pix->width * (y) / 2) + (x) / 2)
-+#define V2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
-+                               (pix->width * pix->height / 2) +       \
-+                               (pix->width * (y) / 2) + (x) / 2)
-+#define UV_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
-+                               (pix->width * ((y) / 2)) + (x))
-+#define UV2_OFFSET(pix, x, y) ((pix->width * pix->height) +   \
-+                               (pix->width * y) + (x))
-+
-+#define NUM_ALPHA_CHANNELS    7
-+
-+/* See Table 37-12. Alpha channels mapping. */
-+static int ipu_channel_albm(int ch_num)
-+{
-+      switch (ch_num) {
-+      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
-+      case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
-+      case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
-+      case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
-+      case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
-+      case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
-+      case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
-+{
-+      struct ipu_soc *ipu = ch->ipu;
-+      int albm;
-+      u32 val;
-+
-+      albm = ipu_channel_albm(ch->num);
-+      if (albm < 0)
-+              return;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
-+      val |= BIT(ch->num);
-+      ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
-+}
-+
-+int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
-+{
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_YUV420:
-+      case DRM_FORMAT_YVU420:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUV422:
-+      case DRM_FORMAT_YVU422:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUV444:
-+      case DRM_FORMAT_YVU444:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_NV12:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_NV16:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_UYVY:
-+              /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUYV:
-+              /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_ABGR8888:
-+      case DRM_FORMAT_XBGR8888:
-+              ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
-+              break;
-+      case DRM_FORMAT_ARGB8888:
-+      case DRM_FORMAT_XRGB8888:
-+              ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
-+              break;
-+      case DRM_FORMAT_RGBA8888:
-+      case DRM_FORMAT_RGBX8888:
-+      case DRM_FORMAT_RGBX8888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
-+              break;
-+      case DRM_FORMAT_BGRA8888:
-+      case DRM_FORMAT_BGRX8888:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
-+              break;
-+      case DRM_FORMAT_BGR888:
-+      case DRM_FORMAT_BGR888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
-+              break;
-+      case DRM_FORMAT_RGB888:
-+      case DRM_FORMAT_RGB888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
-+              break;
-+      case DRM_FORMAT_RGB565:
-+      case DRM_FORMAT_RGB565_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
-+              break;
-+      case DRM_FORMAT_BGR565:
-+      case DRM_FORMAT_BGR565_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
-+              break;
-+      case DRM_FORMAT_ARGB1555:
-+              ipu_cpmem_set_format_rgb(ch, &def_argb_16);
-+              break;
-+      case DRM_FORMAT_ABGR1555:
-+              ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
-+              break;
-+      case DRM_FORMAT_RGBA5551:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
-+              break;
-+      case DRM_FORMAT_BGRA5551:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
-+              break;
-+      case DRM_FORMAT_ARGB4444:
-+              ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_RGB565_A8:
-+      case DRM_FORMAT_BGR565_A8:
-+      case DRM_FORMAT_RGB888_A8:
-+      case DRM_FORMAT_BGR888_A8:
-+      case DRM_FORMAT_RGBX8888_A8:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
-+              ipu_cpmem_set_separate_alpha(ch);
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
-+
-+int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
-+{
-+      struct v4l2_pix_format *pix = &image->pix;
-+      int offset, u_offset, v_offset;
-+      int ret = 0;
-+
-+      pr_debug("%s: resolution: %dx%d stride: %d\n",
-+               __func__, pix->width, pix->height,
-+               pix->bytesperline);
-+
-+      ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
-+      ipu_cpmem_set_stride(ch, pix->bytesperline);
-+
-+      ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
-+
-+      switch (pix->pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : U_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : V_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_YVU420:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : V_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : U_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_YUV422P:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : U2_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : V2_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_NV12:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : UV_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+              v_offset = image->v_offset ? image->v_offset : 0;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_NV16:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : UV2_OFFSET(pix, image->rect.left,
-+                                                   image->rect.top) - offset;
-+              v_offset = image->v_offset ? image->v_offset : 0;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_UYVY:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_RGB565:
-+              offset = image->rect.left * 2 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_RGB32:
-+      case V4L2_PIX_FMT_BGR32:
-+      case V4L2_PIX_FMT_ABGR32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_BGRA32:
-+      case V4L2_PIX_FMT_BGRX32:
-+      case V4L2_PIX_FMT_RGBA32:
-+      case V4L2_PIX_FMT_RGBX32:
-+      case V4L2_PIX_FMT_ARGB32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              offset = image->rect.left * 4 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_RGB24:
-+      case V4L2_PIX_FMT_BGR24:
-+              offset = image->rect.left * 3 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_SBGGR8:
-+      case V4L2_PIX_FMT_SGBRG8:
-+      case V4L2_PIX_FMT_SGRBG8:
-+      case V4L2_PIX_FMT_SRGGB8:
-+      case V4L2_PIX_FMT_GREY:
-+              offset = image->rect.left + image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_SBGGR16:
-+      case V4L2_PIX_FMT_SGBRG16:
-+      case V4L2_PIX_FMT_SGRBG16:
-+      case V4L2_PIX_FMT_SRGGB16:
-+      case V4L2_PIX_FMT_Y16:
-+              offset = image->rect.left * 2 +
-+                       image->rect.top * pix->bytesperline;
-+              break;
-+      default:
-+              /* This should not happen */
-+              WARN_ON(1);
-+              offset = 0;
-+              ret = -EINVAL;
-+      }
-+
-+      ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
-+      ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
-+
-+void ipu_cpmem_dump(struct ipuv3_channel *ch)
-+{
-+      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
-+      struct ipu_soc *ipu = ch->ipu;
-+      int chno = ch->num;
-+
-+      dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
-+              readl(&p->word[0].data[0]),
-+              readl(&p->word[0].data[1]),
-+              readl(&p->word[0].data[2]),
-+              readl(&p->word[0].data[3]),
-+              readl(&p->word[0].data[4]));
-+      dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
-+              readl(&p->word[1].data[0]),
-+              readl(&p->word[1].data[1]),
-+              readl(&p->word[1].data[2]),
-+              readl(&p->word[1].data[3]),
-+              readl(&p->word[1].data[4]));
-+      dev_dbg(ipu->dev, "PFS 0x%x, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
-+      dev_dbg(ipu->dev, "BPP 0x%x, ",
-+              ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
-+      dev_dbg(ipu->dev, "NPB 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
-+
-+      dev_dbg(ipu->dev, "FW %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_FW));
-+      dev_dbg(ipu->dev, "FH %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_FH));
-+      dev_dbg(ipu->dev, "EBA0 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
-+      dev_dbg(ipu->dev, "EBA1 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
-+      dev_dbg(ipu->dev, "Stride %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SL));
-+      dev_dbg(ipu->dev, "scan_order %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SO));
-+      dev_dbg(ipu->dev, "uv_stride %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
-+      dev_dbg(ipu->dev, "u_offset 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
-+      dev_dbg(ipu->dev, "v_offset 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
-+
-+      dev_dbg(ipu->dev, "Width0 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
-+      dev_dbg(ipu->dev, "Width1 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
-+      dev_dbg(ipu->dev, "Width2 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
-+      dev_dbg(ipu->dev, "Width3 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
-+      dev_dbg(ipu->dev, "Offset0 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
-+      dev_dbg(ipu->dev, "Offset1 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
-+      dev_dbg(ipu->dev, "Offset2 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
-+      dev_dbg(ipu->dev, "Offset3 %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
-+
-+int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
-+{
-+      struct ipu_cpmem *cpmem;
-+
-+      cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
-+      if (!cpmem)
-+              return -ENOMEM;
-+
-+      ipu->cpmem_priv = cpmem;
-+
-+      spin_lock_init(&cpmem->lock);
-+      cpmem->base = devm_ioremap(dev, base, SZ_128K);
-+      if (!cpmem->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
-+              base, cpmem->base);
-+      cpmem->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_cpmem_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-csi.c
-@@ -0,0 +1,821 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2014 Mentor Graphics Inc.
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/platform_device.h>
-+#include <linux/videodev2.h>
-+#include <uapi/linux/v4l2-mediabus.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+
-+#include "ipu-prv.h"
-+
-+struct ipu_csi {
-+      void __iomem *base;
-+      int id;
-+      u32 module;
-+      struct clk *clk_ipu;    /* IPU bus clock */
-+      spinlock_t lock;
-+      bool inuse;
-+      struct ipu_soc *ipu;
-+};
-+
-+/* CSI Register Offsets */
-+#define CSI_SENS_CONF         0x0000
-+#define CSI_SENS_FRM_SIZE     0x0004
-+#define CSI_ACT_FRM_SIZE      0x0008
-+#define CSI_OUT_FRM_CTRL      0x000c
-+#define CSI_TST_CTRL          0x0010
-+#define CSI_CCIR_CODE_1               0x0014
-+#define CSI_CCIR_CODE_2               0x0018
-+#define CSI_CCIR_CODE_3               0x001c
-+#define CSI_MIPI_DI           0x0020
-+#define CSI_SKIP              0x0024
-+#define CSI_CPD_CTRL          0x0028
-+#define CSI_CPD_RC(n)         (0x002c + ((n)*4))
-+#define CSI_CPD_RS(n)         (0x004c + ((n)*4))
-+#define CSI_CPD_GRC(n)                (0x005c + ((n)*4))
-+#define CSI_CPD_GRS(n)                (0x007c + ((n)*4))
-+#define CSI_CPD_GBC(n)                (0x008c + ((n)*4))
-+#define CSI_CPD_GBS(n)                (0x00Ac + ((n)*4))
-+#define CSI_CPD_BC(n)         (0x00Bc + ((n)*4))
-+#define CSI_CPD_BS(n)         (0x00Dc + ((n)*4))
-+#define CSI_CPD_OFFSET1               0x00ec
-+#define CSI_CPD_OFFSET2               0x00f0
-+
-+/* CSI Register Fields */
-+#define CSI_SENS_CONF_DATA_FMT_SHIFT          8
-+#define CSI_SENS_CONF_DATA_FMT_MASK           0x00000700
-+#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444     0L
-+#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV    1L
-+#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY    2L
-+#define CSI_SENS_CONF_DATA_FMT_BAYER          3L
-+#define CSI_SENS_CONF_DATA_FMT_RGB565         4L
-+#define CSI_SENS_CONF_DATA_FMT_RGB555         5L
-+#define CSI_SENS_CONF_DATA_FMT_RGB444         6L
-+#define CSI_SENS_CONF_DATA_FMT_JPEG           7L
-+
-+#define CSI_SENS_CONF_VSYNC_POL_SHIFT         0
-+#define CSI_SENS_CONF_HSYNC_POL_SHIFT         1
-+#define CSI_SENS_CONF_DATA_POL_SHIFT          2
-+#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT               3
-+#define CSI_SENS_CONF_SENS_PRTCL_MASK         0x00000070
-+#define CSI_SENS_CONF_SENS_PRTCL_SHIFT                4
-+#define CSI_SENS_CONF_PACK_TIGHT_SHIFT                7
-+#define CSI_SENS_CONF_DATA_WIDTH_SHIFT                11
-+#define CSI_SENS_CONF_EXT_VSYNC_SHIFT         15
-+#define CSI_SENS_CONF_DIVRATIO_SHIFT          16
-+
-+#define CSI_SENS_CONF_DIVRATIO_MASK           0x00ff0000
-+#define CSI_SENS_CONF_DATA_DEST_SHIFT         24
-+#define CSI_SENS_CONF_DATA_DEST_MASK          0x07000000
-+#define CSI_SENS_CONF_JPEG8_EN_SHIFT          27
-+#define CSI_SENS_CONF_JPEG_EN_SHIFT           28
-+#define CSI_SENS_CONF_FORCE_EOF_SHIFT         29
-+#define CSI_SENS_CONF_DATA_EN_POL_SHIFT               31
-+
-+#define CSI_DATA_DEST_IC                      2
-+#define CSI_DATA_DEST_IDMAC                   4
-+
-+#define CSI_CCIR_ERR_DET_EN                   0x01000000
-+#define CSI_HORI_DOWNSIZE_EN                  0x80000000
-+#define CSI_VERT_DOWNSIZE_EN                  0x40000000
-+#define CSI_TEST_GEN_MODE_EN                  0x01000000
-+
-+#define CSI_HSC_MASK                          0x1fff0000
-+#define CSI_HSC_SHIFT                         16
-+#define CSI_VSC_MASK                          0x00000fff
-+#define CSI_VSC_SHIFT                         0
-+
-+#define CSI_TEST_GEN_R_MASK                   0x000000ff
-+#define CSI_TEST_GEN_R_SHIFT                  0
-+#define CSI_TEST_GEN_G_MASK                   0x0000ff00
-+#define CSI_TEST_GEN_G_SHIFT                  8
-+#define CSI_TEST_GEN_B_MASK                   0x00ff0000
-+#define CSI_TEST_GEN_B_SHIFT                  16
-+
-+#define CSI_MAX_RATIO_SKIP_SMFC_MASK          0x00000007
-+#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT         0
-+#define CSI_SKIP_SMFC_MASK                    0x000000f8
-+#define CSI_SKIP_SMFC_SHIFT                   3
-+#define CSI_ID_2_SKIP_MASK                    0x00000300
-+#define CSI_ID_2_SKIP_SHIFT                   8
-+
-+#define CSI_COLOR_FIRST_ROW_MASK              0x00000002
-+#define CSI_COLOR_FIRST_COMP_MASK             0x00000001
-+
-+/* MIPI CSI-2 data types */
-+#define MIPI_DT_YUV420                0x18 /* YYY.../UYVY.... */
-+#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY...   */
-+#define MIPI_DT_YUV422                0x1e /* UYVY...         */
-+#define MIPI_DT_RGB444                0x20
-+#define MIPI_DT_RGB555                0x21
-+#define MIPI_DT_RGB565                0x22
-+#define MIPI_DT_RGB666                0x23
-+#define MIPI_DT_RGB888                0x24
-+#define MIPI_DT_RAW6          0x28
-+#define MIPI_DT_RAW7          0x29
-+#define MIPI_DT_RAW8          0x2a
-+#define MIPI_DT_RAW10         0x2b
-+#define MIPI_DT_RAW12         0x2c
-+#define MIPI_DT_RAW14         0x2d
-+
-+/*
-+ * Bitfield of CSI bus signal polarities and modes.
-+ */
-+struct ipu_csi_bus_config {
-+      unsigned data_width:4;
-+      unsigned clk_mode:3;
-+      unsigned ext_vsync:1;
-+      unsigned vsync_pol:1;
-+      unsigned hsync_pol:1;
-+      unsigned pixclk_pol:1;
-+      unsigned data_pol:1;
-+      unsigned sens_clksrc:1;
-+      unsigned pack_tight:1;
-+      unsigned force_eof:1;
-+      unsigned data_en_pol:1;
-+
-+      unsigned data_fmt;
-+      unsigned mipi_dt;
-+};
-+
-+/*
-+ * Enumeration of CSI data bus widths.
-+ */
-+enum ipu_csi_data_width {
-+      IPU_CSI_DATA_WIDTH_4   = 0,
-+      IPU_CSI_DATA_WIDTH_8   = 1,
-+      IPU_CSI_DATA_WIDTH_10  = 3,
-+      IPU_CSI_DATA_WIDTH_12  = 5,
-+      IPU_CSI_DATA_WIDTH_16  = 9,
-+};
-+
-+/*
-+ * Enumeration of CSI clock modes.
-+ */
-+enum ipu_csi_clk_mode {
-+      IPU_CSI_CLK_MODE_GATED_CLK,
-+      IPU_CSI_CLK_MODE_NONGATED_CLK,
-+      IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
-+      IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
-+      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
-+};
-+
-+static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
-+{
-+      return readl(csi->base + offset);
-+}
-+
-+static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
-+                               unsigned offset)
-+{
-+      writel(value, csi->base + offset);
-+}
-+
-+/*
-+ * Set mclk division ratio for generating test mode mclk. Only used
-+ * for test generator.
-+ */
-+static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
-+                                      u32 ipu_clk)
-+{
-+      u32 temp;
-+      int div_ratio;
-+
-+      div_ratio = (ipu_clk / pixel_clk) - 1;
-+
-+      if (div_ratio > 0xFF || div_ratio < 0) {
-+              dev_err(csi->ipu->dev,
-+                      "value of pixel_clk extends normal range\n");
-+              return -EINVAL;
-+      }
-+
-+      temp = ipu_csi_read(csi, CSI_SENS_CONF);
-+      temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
-+      ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
-+                        CSI_SENS_CONF);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Find the CSI data format and data width for the given V4L2 media
-+ * bus pixel format code.
-+ */
-+static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
-+                              enum v4l2_mbus_type mbus_type)
-+{
-+      switch (mbus_code) {
-+      case MEDIA_BUS_FMT_BGR565_2X8_BE:
-+      case MEDIA_BUS_FMT_BGR565_2X8_LE:
-+      case MEDIA_BUS_FMT_RGB565_2X8_BE:
-+      case MEDIA_BUS_FMT_RGB565_2X8_LE:
-+              if (mbus_type == V4L2_MBUS_CSI2_DPHY)
-+                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
-+              else
-+                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RGB565;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
-+              cfg->mipi_dt = MIPI_DT_RGB444;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
-+              cfg->mipi_dt = MIPI_DT_RGB555;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB888_1X24:
-+      case MEDIA_BUS_FMT_BGR888_1X24:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
-+              cfg->mipi_dt = MIPI_DT_RGB888;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_UYVY8_2X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_YUYV8_2X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_UYVY8_1X16:
-+      case MEDIA_BUS_FMT_YUYV8_1X16:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_16;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG8_1X8:
-+      case MEDIA_BUS_FMT_SRGGB8_1X8:
-+      case MEDIA_BUS_FMT_Y8_1X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW8;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW10;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR10_1X10:
-+      case MEDIA_BUS_FMT_SGBRG10_1X10:
-+      case MEDIA_BUS_FMT_SGRBG10_1X10:
-+      case MEDIA_BUS_FMT_SRGGB10_1X10:
-+      case MEDIA_BUS_FMT_Y10_1X10:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW10;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_10;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR12_1X12:
-+      case MEDIA_BUS_FMT_SGBRG12_1X12:
-+      case MEDIA_BUS_FMT_SGRBG12_1X12:
-+      case MEDIA_BUS_FMT_SRGGB12_1X12:
-+      case MEDIA_BUS_FMT_Y12_1X12:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW12;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_12;
-+              break;
-+      case MEDIA_BUS_FMT_JPEG_1X8:
-+              /* TODO */
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
-+              cfg->mipi_dt = MIPI_DT_RAW8;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+/* translate alternate field mode based on given standard */
-+static inline enum v4l2_field
-+ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
-+{
-+      return (field != V4L2_FIELD_ALTERNATE) ? field :
-+              ((std & V4L2_STD_525_60) ?
-+               V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
-+}
-+
-+/*
-+ * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
-+ */
-+static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
-+                          const struct v4l2_mbus_config *mbus_cfg,
-+                          const struct v4l2_mbus_framefmt *mbus_fmt)
-+{
-+      int ret;
-+
-+      memset(csicfg, 0, sizeof(*csicfg));
-+
-+      ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
-+      if (ret < 0)
-+              return ret;
-+
-+      switch (mbus_cfg->type) {
-+      case V4L2_MBUS_PARALLEL:
-+              csicfg->ext_vsync = 1;
-+              csicfg->vsync_pol = (mbus_cfg->flags &
-+                                   V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
-+              csicfg->hsync_pol = (mbus_cfg->flags &
-+                                   V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
-+              csicfg->pixclk_pol = (mbus_cfg->flags &
-+                                    V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
-+              csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
-+              break;
-+      case V4L2_MBUS_BT656:
-+              csicfg->ext_vsync = 0;
-+              if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
-+                  mbus_fmt->field == V4L2_FIELD_ALTERNATE)
-+                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
-+              else
-+                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
-+              break;
-+      case V4L2_MBUS_CSI2_DPHY:
-+              /*
-+               * MIPI CSI-2 requires non gated clock mode, all other
-+               * parameters are not applicable for MIPI CSI-2 bus.
-+               */
-+              csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
-+              break;
-+      default:
-+              /* will never get here, keep compiler quiet */
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int
-+ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
-+                              const struct v4l2_mbus_framefmt *infmt,
-+                              const struct v4l2_mbus_framefmt *outfmt,
-+                              v4l2_std_id std)
-+{
-+      enum v4l2_field infield, outfield;
-+      bool swap_fields;
-+
-+      /* get translated field type of input and output */
-+      infield = ipu_csi_translate_field(infmt->field, std);
-+      outfield = ipu_csi_translate_field(outfmt->field, std);
-+
-+      /*
-+       * Write the H-V-F codes the CSI will match against the
-+       * incoming data for start/end of active and blanking
-+       * field intervals. If input and output field types are
-+       * sequential but not the same (one is SEQ_BT and the other
-+       * is SEQ_TB), swap the F-bit so that the CSI will capture
-+       * field 1 lines before field 0 lines.
-+       */
-+      swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
-+                     V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
-+                     infield != outfield);
-+
-+      if (!swap_fields) {
-+              /*
-+               * Field0BlankEnd  = 110, Field0BlankStart  = 010
-+               * Field0ActiveEnd = 100, Field0ActiveStart = 000
-+               * Field1BlankEnd  = 111, Field1BlankStart  = 011
-+               * Field1ActiveEnd = 101, Field1ActiveStart = 001
-+               */
-+              ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
-+                            CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
-+      } else {
-+              dev_dbg(csi->ipu->dev, "capture field swap\n");
-+
-+              /* same as above but with F-bit inverted */
-+              ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
-+                            CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
-+      }
-+
-+      ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+
-+      return 0;
-+}
-+
-+
-+int ipu_csi_init_interface(struct ipu_csi *csi,
-+                         const struct v4l2_mbus_config *mbus_cfg,
-+                         const struct v4l2_mbus_framefmt *infmt,
-+                         const struct v4l2_mbus_framefmt *outfmt)
-+{
-+      struct ipu_csi_bus_config cfg;
-+      unsigned long flags;
-+      u32 width, height, data = 0;
-+      v4l2_std_id std;
-+      int ret;
-+
-+      ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* set default sensor frame width and height */
-+      width = infmt->width;
-+      height = infmt->height;
-+      if (infmt->field == V4L2_FIELD_ALTERNATE)
-+              height *= 2;
-+
-+      /* Set the CSI_SENS_CONF register remaining fields */
-+      data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
-+              cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
-+              cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
-+              cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
-+              cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
-+              cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
-+              cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
-+              cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
-+              cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
-+              cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
-+              cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      ipu_csi_write(csi, data, CSI_SENS_CONF);
-+
-+      /* Set CCIR registers */
-+
-+      switch (cfg.clk_mode) {
-+      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
-+              ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+              break;
-+      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
-+              if (width == 720 && height == 480) {
-+                      std = V4L2_STD_NTSC;
-+                      height = 525;
-+              } else if (width == 720 && height == 576) {
-+                      std = V4L2_STD_PAL;
-+                      height = 625;
-+              } else {
-+                      dev_err(csi->ipu->dev,
-+                              "Unsupported interlaced video mode\n");
-+                      ret = -EINVAL;
-+                      goto out_unlock;
-+              }
-+
-+              ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
-+              if (ret)
-+                      goto out_unlock;
-+              break;
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
-+              ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
-+                                 CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+              break;
-+      case IPU_CSI_CLK_MODE_GATED_CLK:
-+      case IPU_CSI_CLK_MODE_NONGATED_CLK:
-+              ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
-+              break;
-+      }
-+
-+      /* Setup sensor frame size */
-+      ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
-+                    CSI_SENS_FRM_SIZE);
-+
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
-+              ipu_csi_read(csi, CSI_SENS_CONF));
-+      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
-+              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
-+
-+out_unlock:
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
-+
-+bool ipu_csi_is_interlaced(struct ipu_csi *csi)
-+{
-+      unsigned long flags;
-+      u32 sensor_protocol;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+      sensor_protocol =
-+              (ipu_csi_read(csi, CSI_SENS_CONF) &
-+               CSI_SENS_CONF_SENS_PRTCL_MASK) >>
-+              CSI_SENS_CONF_SENS_PRTCL_SHIFT;
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      switch (sensor_protocol) {
-+      case IPU_CSI_CLK_MODE_GATED_CLK:
-+      case IPU_CSI_CLK_MODE_NONGATED_CLK:
-+      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
-+              return false;
-+      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
-+              return true;
-+      default:
-+              dev_err(csi->ipu->dev,
-+                      "CSI %d sensor protocol unsupported\n", csi->id);
-+              return false;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
-+
-+void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
-+      w->width = (reg & 0xFFFF) + 1;
-+      w->height = (reg >> 16 & 0xFFFF) + 1;
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
-+      w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_get_window);
-+
-+void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
-+                        CSI_ACT_FRM_SIZE);
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
-+      reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
-+      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_window);
-+
-+void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
-+      reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
-+             (vert ? CSI_VERT_DOWNSIZE_EN : 0);
-+      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
-+
-+void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
-+                              u32 r_value, u32 g_value, u32 b_value,
-+                              u32 pix_clk)
-+{
-+      unsigned long flags;
-+      u32 ipu_clk = clk_get_rate(csi->clk_ipu);
-+      u32 temp;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_TST_CTRL);
-+
-+      if (!active) {
-+              temp &= ~CSI_TEST_GEN_MODE_EN;
-+              ipu_csi_write(csi, temp, CSI_TST_CTRL);
-+      } else {
-+              /* Set sensb_mclk div_ratio */
-+              ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
-+
-+              temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
-+                        CSI_TEST_GEN_B_MASK);
-+              temp |= CSI_TEST_GEN_MODE_EN;
-+              temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
-+                      (g_value << CSI_TEST_GEN_G_SHIFT) |
-+                      (b_value << CSI_TEST_GEN_B_SHIFT);
-+              ipu_csi_write(csi, temp, CSI_TST_CTRL);
-+      }
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
-+
-+int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
-+                            struct v4l2_mbus_framefmt *mbus_fmt)
-+{
-+      struct ipu_csi_bus_config cfg;
-+      unsigned long flags;
-+      u32 temp;
-+      int ret;
-+
-+      if (vc > 3)
-+              return -EINVAL;
-+
-+      ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
-+      if (ret < 0)
-+              return ret;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_MIPI_DI);
-+      temp &= ~(0xff << (vc * 8));
-+      temp |= (cfg.mipi_dt << (vc * 8));
-+      ipu_csi_write(csi, temp, CSI_MIPI_DI);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
-+
-+int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
-+                        u32 max_ratio, u32 id)
-+{
-+      unsigned long flags;
-+      u32 temp;
-+
-+      if (max_ratio > 5 || id > 3)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_SKIP);
-+      temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
-+                CSI_SKIP_SMFC_MASK);
-+      temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
-+              (id << CSI_ID_2_SKIP_SHIFT) |
-+              (skip << CSI_SKIP_SMFC_SHIFT);
-+      ipu_csi_write(csi, temp, CSI_SKIP);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
-+
-+int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
-+{
-+      unsigned long flags;
-+      u32 csi_sens_conf, dest;
-+
-+      if (csi_dest == IPU_CSI_DEST_IDMAC)
-+              dest = CSI_DATA_DEST_IDMAC;
-+      else
-+              dest = CSI_DATA_DEST_IC; /* IC or VDIC */
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
-+      csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
-+      csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
-+      ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
-+
-+int ipu_csi_enable(struct ipu_csi *csi)
-+{
-+      ipu_module_enable(csi->ipu, csi->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_enable);
-+
-+int ipu_csi_disable(struct ipu_csi *csi)
-+{
-+      ipu_module_disable(csi->ipu, csi->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_disable);
-+
-+struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
-+{
-+      unsigned long flags;
-+      struct ipu_csi *csi, *ret;
-+
-+      if (id > 1)
-+              return ERR_PTR(-EINVAL);
-+
-+      csi = ipu->csi_priv[id];
-+      ret = csi;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      if (csi->inuse) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      csi->inuse = true;
-+unlock:
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_get);
-+
-+void ipu_csi_put(struct ipu_csi *csi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+      csi->inuse = false;
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_put);
-+
-+int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
-+               unsigned long base, u32 module, struct clk *clk_ipu)
-+{
-+      struct ipu_csi *csi;
-+
-+      if (id > 1)
-+              return -ENODEV;
-+
-+      csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
-+      if (!csi)
-+              return -ENOMEM;
-+
-+      ipu->csi_priv[id] = csi;
-+
-+      spin_lock_init(&csi->lock);
-+      csi->module = module;
-+      csi->id = id;
-+      csi->clk_ipu = clk_ipu;
-+      csi->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!csi->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
-+              id, base, csi->base);
-+      csi->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_csi_exit(struct ipu_soc *ipu, int id)
-+{
-+}
-+
-+void ipu_csi_dump(struct ipu_csi *csi)
-+{
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
-+              ipu_csi_read(csi, CSI_SENS_CONF));
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
-+              ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
-+      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
-+              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
-+      dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
-+              ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
-+      dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
-+              ipu_csi_read(csi, CSI_TST_CTRL));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_1));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_2));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_3));
-+      dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
-+              ipu_csi_read(csi, CSI_MIPI_DI));
-+      dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
-+              ipu_csi_read(csi, CSI_SKIP));
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_dump);
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-dc.c
-@@ -0,0 +1,420 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DC_MAP_CONF_PTR(n)    (0x108 + ((n) & ~0x1) * 2)
-+#define DC_MAP_CONF_VAL(n)    (0x144 + ((n) & ~0x1) * 2)
-+
-+#define DC_EVT_NF             0
-+#define DC_EVT_NL             1
-+#define DC_EVT_EOF            2
-+#define DC_EVT_NFIELD         3
-+#define DC_EVT_EOL            4
-+#define DC_EVT_EOFIELD                5
-+#define DC_EVT_NEW_ADDR               6
-+#define DC_EVT_NEW_CHAN               7
-+#define DC_EVT_NEW_DATA               8
-+
-+#define DC_EVT_NEW_ADDR_W_0   0
-+#define DC_EVT_NEW_ADDR_W_1   1
-+#define DC_EVT_NEW_CHAN_W_0   2
-+#define DC_EVT_NEW_CHAN_W_1   3
-+#define DC_EVT_NEW_DATA_W_0   4
-+#define DC_EVT_NEW_DATA_W_1   5
-+#define DC_EVT_NEW_ADDR_R_0   6
-+#define DC_EVT_NEW_ADDR_R_1   7
-+#define DC_EVT_NEW_CHAN_R_0   8
-+#define DC_EVT_NEW_CHAN_R_1   9
-+#define DC_EVT_NEW_DATA_R_0   10
-+#define DC_EVT_NEW_DATA_R_1   11
-+
-+#define DC_WR_CH_CONF         0x0
-+#define DC_WR_CH_ADDR         0x4
-+#define DC_RL_CH(evt)         (8 + ((evt) & ~0x1) * 2)
-+
-+#define DC_GEN                        0xd4
-+#define DC_DISP_CONF1(disp)   (0xd8 + (disp) * 4)
-+#define DC_DISP_CONF2(disp)   (0xe8 + (disp) * 4)
-+#define DC_STAT                       0x1c8
-+
-+#define WROD(lf)              (0x18 | ((lf) << 1))
-+#define WRG                   0x01
-+#define WCLK                  0xc9
-+
-+#define SYNC_WAVE 0
-+#define NULL_WAVE (-1)
-+
-+#define DC_GEN_SYNC_1_6_SYNC  (2 << 1)
-+#define DC_GEN_SYNC_PRIORITY_1        (1 << 7)
-+
-+#define DC_WR_CH_CONF_WORD_SIZE_8             (0 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_16            (1 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_24            (2 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_32            (3 << 0)
-+#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)     (((i) & 0x1) << 3)
-+#define DC_WR_CH_CONF_DISP_ID_SERIAL          (2 << 3)
-+#define DC_WR_CH_CONF_DISP_ID_ASYNC           (3 << 4)
-+#define DC_WR_CH_CONF_FIELD_MODE              (1 << 9)
-+#define DC_WR_CH_CONF_PROG_TYPE_NORMAL                (4 << 5)
-+#define DC_WR_CH_CONF_PROG_TYPE_MASK          (7 << 5)
-+#define DC_WR_CH_CONF_PROG_DI_ID              (1 << 2)
-+#define DC_WR_CH_CONF_PROG_DISP_ID(i)         (((i) & 0x1) << 3)
-+
-+#define IPU_DC_NUM_CHANNELS   10
-+
-+struct ipu_dc_priv;
-+
-+enum ipu_dc_map {
-+      IPU_DC_MAP_RGB24,
-+      IPU_DC_MAP_RGB565,
-+      IPU_DC_MAP_GBR24, /* TVEv2 */
-+      IPU_DC_MAP_BGR666,
-+      IPU_DC_MAP_LVDS666,
-+      IPU_DC_MAP_BGR24,
-+};
-+
-+struct ipu_dc {
-+      /* The display interface number assigned to this dc channel */
-+      unsigned int            di;
-+      void __iomem            *base;
-+      struct ipu_dc_priv      *priv;
-+      int                     chno;
-+      bool                    in_use;
-+};
-+
-+struct ipu_dc_priv {
-+      void __iomem            *dc_reg;
-+      void __iomem            *dc_tmpl_reg;
-+      struct ipu_soc          *ipu;
-+      struct device           *dev;
-+      struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
-+      struct mutex            mutex;
-+      struct completion       comp;
-+      int                     use_count;
-+};
-+
-+static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
-+{
-+      u32 reg;
-+
-+      reg = readl(dc->base + DC_RL_CH(event));
-+      reg &= ~(0xffff << (16 * (event & 0x1)));
-+      reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
-+      writel(reg, dc->base + DC_RL_CH(event));
-+}
-+
-+static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
-+              int map, int wave, int glue, int sync, int stop)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+      u32 reg1, reg2;
-+
-+      if (opcode == WCLK) {
-+              reg1 = (operand << 20) & 0xfff00000;
-+              reg2 = operand >> 12 | opcode << 1 | stop << 9;
-+      } else if (opcode == WRG) {
-+              reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
-+              reg2 = operand >> 17 | opcode << 7 | stop << 9;
-+      } else {
-+              reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
-+              reg2 = operand >> 12 | opcode << 4 | stop << 9;
-+      }
-+      writel(reg1, priv->dc_tmpl_reg + word * 8);
-+      writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
-+}
-+
-+static int ipu_bus_format_to_map(u32 fmt)
-+{
-+      switch (fmt) {
-+      default:
-+              WARN_ON(1);
-+              /* fall-through */
-+      case MEDIA_BUS_FMT_RGB888_1X24:
-+              return IPU_DC_MAP_RGB24;
-+      case MEDIA_BUS_FMT_RGB565_1X16:
-+              return IPU_DC_MAP_RGB565;
-+      case MEDIA_BUS_FMT_GBR888_1X24:
-+              return IPU_DC_MAP_GBR24;
-+      case MEDIA_BUS_FMT_RGB666_1X18:
-+              return IPU_DC_MAP_BGR666;
-+      case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
-+              return IPU_DC_MAP_LVDS666;
-+      case MEDIA_BUS_FMT_BGR888_1X24:
-+              return IPU_DC_MAP_BGR24;
-+      }
-+}
-+
-+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
-+              u32 bus_format, u32 width)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+      int addr, sync;
-+      u32 reg = 0;
-+      int map;
-+
-+      dc->di = ipu_di_get_num(di);
-+
-+      map = ipu_bus_format_to_map(bus_format);
-+
-+      /*
-+       * In interlaced mode we need more counters to create the asymmetric
-+       * per-field VSYNC signals. The pixel active signal synchronising DC
-+       * to DI moves to signal generator #6 (see ipu-di.c). In progressive
-+       * mode counter #5 is used.
-+       */
-+      sync = interlaced ? 6 : 5;
-+
-+      /* Reserve 5 microcode template words for each DI */
-+      if (dc->di)
-+              addr = 5;
-+      else
-+              addr = 0;
-+
-+      if (interlaced) {
-+              dc_link_event(dc, DC_EVT_NL, addr, 3);
-+              dc_link_event(dc, DC_EVT_EOL, addr, 2);
-+              dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
-+
-+              /* Init template microcode */
-+              dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
-+      } else {
-+              dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
-+              dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
-+              dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
-+
-+              /* Init template microcode */
-+              dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
-+              dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
-+              dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
-+              dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
-+      }
-+
-+      dc_link_event(dc, DC_EVT_NF, 0, 0);
-+      dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
-+      dc_link_event(dc, DC_EVT_EOF, 0, 0);
-+      dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
-+      dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
-+      dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
-+
-+      reg = readl(dc->base + DC_WR_CH_CONF);
-+      if (interlaced)
-+              reg |= DC_WR_CH_CONF_FIELD_MODE;
-+      else
-+              reg &= ~DC_WR_CH_CONF_FIELD_MODE;
-+      writel(reg, dc->base + DC_WR_CH_CONF);
-+
-+      writel(0x0, dc->base + DC_WR_CH_ADDR);
-+      writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
-+
-+void ipu_dc_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_enable);
-+
-+void ipu_dc_enable_channel(struct ipu_dc *dc)
-+{
-+      u32 reg;
-+
-+      reg = readl(dc->base + DC_WR_CH_CONF);
-+      reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
-+      writel(reg, dc->base + DC_WR_CH_CONF);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
-+
-+void ipu_dc_disable_channel(struct ipu_dc *dc)
-+{
-+      u32 val;
-+
-+      val = readl(dc->base + DC_WR_CH_CONF);
-+      val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-+      writel(val, dc->base + DC_WR_CH_CONF);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
-+
-+void ipu_dc_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_disable);
-+
-+static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
-+              int byte_num, int offset, int mask)
-+{
-+      int ptr = map * 3 + byte_num;
-+      u32 reg;
-+
-+      reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-+      reg &= ~(0xffff << (16 * (ptr & 0x1)));
-+      reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
-+      writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-+
-+      reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-+      reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
-+      reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
-+      writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
-+}
-+
-+static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
-+{
-+      u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-+
-+      writel(reg & ~(0xffff << (16 * (map & 0x1))),
-+                   priv->dc_reg + DC_MAP_CONF_PTR(map));
-+}
-+
-+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+      struct ipu_dc *dc;
-+
-+      if (channel >= IPU_DC_NUM_CHANNELS)
-+              return ERR_PTR(-ENODEV);
-+
-+      dc = &priv->channels[channel];
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (dc->in_use) {
-+              mutex_unlock(&priv->mutex);
-+              return ERR_PTR(-EBUSY);
-+      }
-+
-+      dc->in_use = true;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return dc;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_get);
-+
-+void ipu_dc_put(struct ipu_dc *dc)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+
-+      mutex_lock(&priv->mutex);
-+      dc->in_use = false;
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_put);
-+
-+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long template_base)
-+{
-+      struct ipu_dc_priv *priv;
-+      static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
-+              0x78, 0, 0x94, 0xb4};
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      mutex_init(&priv->mutex);
-+
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+      priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
-+      priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
-+      if (!priv->dc_reg || !priv->dc_tmpl_reg)
-+              return -ENOMEM;
-+
-+      for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
-+              priv->channels[i].chno = i;
-+              priv->channels[i].priv = priv;
-+              priv->channels[i].base = priv->dc_reg + channel_offsets[i];
-+      }
-+
-+      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
-+                      DC_WR_CH_CONF_PROG_DI_ID,
-+                      priv->channels[1].base + DC_WR_CH_CONF);
-+      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
-+                      priv->channels[5].base + DC_WR_CH_CONF);
-+
-+      writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
-+              priv->dc_reg + DC_GEN);
-+
-+      ipu->dc_priv = priv;
-+
-+      dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
-+                      base, template_base);
-+
-+      /* rgb24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
-+
-+      /* rgb565 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
-+
-+      /* gbr24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
-+
-+      /* bgr666 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
-+
-+      /* lvds666 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
-+
-+      /* bgr24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
-+
-+      return 0;
-+}
-+
-+void ipu_dc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-di.c
-@@ -0,0 +1,745 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/platform_device.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_di {
-+      void __iomem *base;
-+      int id;
-+      u32 module;
-+      struct clk *clk_di;     /* display input clock */
-+      struct clk *clk_ipu;    /* IPU bus clock */
-+      struct clk *clk_di_pixel; /* resulting pixel clock */
-+      bool inuse;
-+      struct ipu_soc *ipu;
-+};
-+
-+static DEFINE_MUTEX(di_mutex);
-+
-+struct di_sync_config {
-+      int run_count;
-+      int run_src;
-+      int offset_count;
-+      int offset_src;
-+      int repeat_count;
-+      int cnt_clr_src;
-+      int cnt_polarity_gen_en;
-+      int cnt_polarity_clr_src;
-+      int cnt_polarity_trigger_src;
-+      int cnt_up;
-+      int cnt_down;
-+};
-+
-+enum di_pins {
-+      DI_PIN11 = 0,
-+      DI_PIN12 = 1,
-+      DI_PIN13 = 2,
-+      DI_PIN14 = 3,
-+      DI_PIN15 = 4,
-+      DI_PIN16 = 5,
-+      DI_PIN17 = 6,
-+      DI_PIN_CS = 7,
-+
-+      DI_PIN_SER_CLK = 0,
-+      DI_PIN_SER_RS = 1,
-+};
-+
-+enum di_sync_wave {
-+      DI_SYNC_NONE = 0,
-+      DI_SYNC_CLK = 1,
-+      DI_SYNC_INT_HSYNC = 2,
-+      DI_SYNC_HSYNC = 3,
-+      DI_SYNC_VSYNC = 4,
-+      DI_SYNC_DE = 6,
-+
-+      DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
-+      DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
-+      DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
-+};
-+
-+#define SYNC_WAVE 0
-+
-+#define DI_GENERAL            0x0000
-+#define DI_BS_CLKGEN0         0x0004
-+#define DI_BS_CLKGEN1         0x0008
-+#define DI_SW_GEN0(gen)               (0x000c + 4 * ((gen) - 1))
-+#define DI_SW_GEN1(gen)               (0x0030 + 4 * ((gen) - 1))
-+#define DI_STP_REP(gen)               (0x0148 + 4 * (((gen) - 1)/2))
-+#define DI_SYNC_AS_GEN                0x0054
-+#define DI_DW_GEN(gen)                (0x0058 + 4 * (gen))
-+#define DI_DW_SET(gen, set)   (0x0088 + 4 * ((gen) + 0xc * (set)))
-+#define DI_SER_CONF           0x015c
-+#define DI_SSC                        0x0160
-+#define DI_POL                        0x0164
-+#define DI_AW0                        0x0168
-+#define DI_AW1                        0x016c
-+#define DI_SCR_CONF           0x0170
-+#define DI_STAT                       0x0174
-+
-+#define DI_SW_GEN0_RUN_COUNT(x)                       ((x) << 19)
-+#define DI_SW_GEN0_RUN_SRC(x)                 ((x) << 16)
-+#define DI_SW_GEN0_OFFSET_COUNT(x)            ((x) << 3)
-+#define DI_SW_GEN0_OFFSET_SRC(x)              ((x) << 0)
-+
-+#define DI_SW_GEN1_CNT_POL_GEN_EN(x)          ((x) << 29)
-+#define DI_SW_GEN1_CNT_CLR_SRC(x)             ((x) << 25)
-+#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)     ((x) << 12)
-+#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)         ((x) << 9)
-+#define DI_SW_GEN1_CNT_DOWN(x)                        ((x) << 16)
-+#define DI_SW_GEN1_CNT_UP(x)                  (x)
-+#define DI_SW_GEN1_AUTO_RELOAD                        (0x10000000)
-+
-+#define DI_DW_GEN_ACCESS_SIZE_OFFSET          24
-+#define DI_DW_GEN_COMPONENT_SIZE_OFFSET               16
-+
-+#define DI_GEN_POLARITY_1                     (1 << 0)
-+#define DI_GEN_POLARITY_2                     (1 << 1)
-+#define DI_GEN_POLARITY_3                     (1 << 2)
-+#define DI_GEN_POLARITY_4                     (1 << 3)
-+#define DI_GEN_POLARITY_5                     (1 << 4)
-+#define DI_GEN_POLARITY_6                     (1 << 5)
-+#define DI_GEN_POLARITY_7                     (1 << 6)
-+#define DI_GEN_POLARITY_8                     (1 << 7)
-+#define DI_GEN_POLARITY_DISP_CLK              (1 << 17)
-+#define DI_GEN_DI_CLK_EXT                     (1 << 20)
-+#define DI_GEN_DI_VSYNC_EXT                   (1 << 21)
-+
-+#define DI_POL_DRDY_DATA_POLARITY             (1 << 7)
-+#define DI_POL_DRDY_POLARITY_15                       (1 << 4)
-+
-+#define DI_VSYNC_SEL_OFFSET                   13
-+
-+static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
-+{
-+      return readl(di->base + offset);
-+}
-+
-+static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
-+{
-+      writel(value, di->base + offset);
-+}
-+
-+static void ipu_di_data_wave_config(struct ipu_di *di,
-+                                   int wave_gen,
-+                                   int access_size, int component_size)
-+{
-+      u32 reg;
-+      reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
-+          (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
-+      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-+}
-+
-+static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
-+              int set, int up, int down)
-+{
-+      u32 reg;
-+
-+      reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
-+      reg &= ~(0x3 << (di_pin * 2));
-+      reg |= set << (di_pin * 2);
-+      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-+
-+      ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
-+}
-+
-+static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
-+              int start, int count)
-+{
-+      u32 reg;
-+      int i;
-+
-+      for (i = 0; i < count; i++) {
-+              struct di_sync_config *c = &config[i];
-+              int wave_gen = start + i + 1;
-+
-+              if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
-+                              (c->repeat_count >= 0x1000) ||
-+                              (c->cnt_up >= 0x400) ||
-+                              (c->cnt_down >= 0x400)) {
-+                      dev_err(di->ipu->dev, "DI%d counters out of range.\n",
-+                                      di->id);
-+                      return;
-+              }
-+
-+              reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
-+                      DI_SW_GEN0_RUN_SRC(c->run_src) |
-+                      DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
-+                      DI_SW_GEN0_OFFSET_SRC(c->offset_src);
-+              ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
-+
-+              reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
-+                      DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
-+                      DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
-+                                      c->cnt_polarity_trigger_src) |
-+                      DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
-+                      DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
-+                      DI_SW_GEN1_CNT_UP(c->cnt_up);
-+
-+              /* Enable auto reload */
-+              if (c->repeat_count == 0)
-+                      reg |= DI_SW_GEN1_AUTO_RELOAD;
-+
-+              ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
-+
-+              reg = ipu_di_read(di, DI_STP_REP(wave_gen));
-+              reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
-+              reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
-+              ipu_di_write(di, reg, DI_STP_REP(wave_gen));
-+      }
-+}
-+
-+static void ipu_di_sync_config_interlaced(struct ipu_di *di,
-+              struct ipu_di_signal_cfg *sig)
-+{
-+      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
-+              sig->mode.hback_porch + sig->mode.hfront_porch;
-+      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
-+              sig->mode.vback_porch + sig->mode.vfront_porch;
-+      struct di_sync_config cfg[] = {
-+              {
-+                      /* 1: internal VSYNC for each frame */
-+                      .run_count = v_total * 2 - 1,
-+                      .run_src = 3,                   /* == counter 7 */
-+              }, {
-+                      /* PIN2: HSYNC waveform */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              }, {
-+                      /* PIN3: VSYNC waveform */
-+                      .run_count = v_total - 1,
-+                      .run_src = 4,                   /* == counter 7 */
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = 4,  /* == counter 7 */
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+                      .cnt_clr_src = DI_SYNC_CNT1,
-+              }, {
-+                      /* 4: Field */
-+                      .run_count = v_total / 2,
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = h_total / 2,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = 2,
-+                      .cnt_clr_src = DI_SYNC_CNT1,
-+              }, {
-+                      /* 5: Active lines */
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = (sig->mode.vsync_len +
-+                                       sig->mode.vback_porch) / 2,
-+                      .offset_src = DI_SYNC_HSYNC,
-+                      .repeat_count = sig->mode.vactive / 2,
-+                      .cnt_clr_src = DI_SYNC_CNT4,
-+              }, {
-+                      /* 6: Active pixel, referenced by DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = DI_SYNC_CNT5,
-+              }, {
-+                      /* 7: Half line HSYNC */
-+                      .run_count = h_total / 2 - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              }
-+      };
-+
-+      ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-+
-+      ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
-+}
-+
-+static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
-+              struct ipu_di_signal_cfg *sig, int div)
-+{
-+      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
-+              sig->mode.hback_porch + sig->mode.hfront_porch;
-+      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
-+              sig->mode.vback_porch + sig->mode.vfront_porch;
-+      struct di_sync_config cfg[] = {
-+              {
-+                      /* 1: INT_HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              } , {
-+                      /* PIN2: HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* PIN3: VSYNC */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* 4: Line Active */
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = sig->mode.vsync_len +
-+                                      sig->mode.vback_porch,
-+                      .offset_src = DI_SYNC_HSYNC,
-+                      .repeat_count = sig->mode.vactive,
-+                      .cnt_clr_src = DI_SYNC_VSYNC,
-+              } , {
-+                      /* 5: Pixel Active, referenced by DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = 5, /* Line Active */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              },
-+      };
-+      /* can't use #7 and #8 for line active and pixel active counters */
-+      struct di_sync_config cfg_vga[] = {
-+              {
-+                      /* 1: INT_HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              } , {
-+                      /* 2: VSYNC */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+              } , {
-+                      /* 3: Line Active */
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = sig->mode.vsync_len +
-+                                      sig->mode.vback_porch,
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .repeat_count = sig->mode.vactive,
-+                      .cnt_clr_src = 3 /* VSYNC */,
-+              } , {
-+                      /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* 5: Pixel Active signal to DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = 4, /* Line Active */
-+              } , {
-+                      /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = 1, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = 1, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* unused */
-+              },
-+      };
-+
-+      ipu_di_write(di, v_total - 1, DI_SCR_CONF);
-+      if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
-+              ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-+      else
-+              ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
-+}
-+
-+static void ipu_di_config_clock(struct ipu_di *di,
-+      const struct ipu_di_signal_cfg *sig)
-+{
-+      struct clk *clk;
-+      unsigned clkgen0;
-+      uint32_t val;
-+
-+      if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
-+              /*
-+               * CLKMODE_EXT means we must use the DI clock: this is
-+               * needed for things like LVDS which needs to feed the
-+               * DI and LDB with the same pixel clock.
-+               */
-+              clk = di->clk_di;
-+
-+              if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
-+                      /*
-+                       * CLKMODE_SYNC means that we want the DI to be
-+                       * clocked at the same rate as the parent clock.
-+                       * This is needed (eg) for LDB which needs to be
-+                       * fed with the same pixel clock.  We assume that
-+                       * the LDB clock has already been set correctly.
-+                       */
-+                      clkgen0 = 1 << 4;
-+              } else {
-+                      /*
-+                       * We can use the divider.  We should really have
-+                       * a flag here indicating whether the bridge can
-+                       * cope with a fractional divider or not.  For the
-+                       * time being, let's go for simplicitly and
-+                       * reliability.
-+                       */
-+                      unsigned long in_rate;
-+                      unsigned div;
-+
-+                      clk_set_rate(clk, sig->mode.pixelclock);
-+
-+                      in_rate = clk_get_rate(clk);
-+                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
-+                      div = clamp(div, 1U, 255U);
-+
-+                      clkgen0 = div << 4;
-+              }
-+      } else {
-+              /*
-+               * For other interfaces, we can arbitarily select between
-+               * the DI specific clock and the internal IPU clock.  See
-+               * DI_GENERAL bit 20.  We select the IPU clock if it can
-+               * give us a clock rate within 1% of the requested frequency,
-+               * otherwise we use the DI clock.
-+               */
-+              unsigned long rate, clkrate;
-+              unsigned div, error;
-+
-+              clkrate = clk_get_rate(di->clk_ipu);
-+              div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
-+              div = clamp(div, 1U, 255U);
-+              rate = clkrate / div;
-+
-+              error = rate / (sig->mode.pixelclock / 1000);
-+
-+              dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
-+                      rate, div, (signed)(error - 1000) / 10, error % 10);
-+
-+              /* Allow a 1% error */
-+              if (error < 1010 && error >= 990) {
-+                      clk = di->clk_ipu;
-+
-+                      clkgen0 = div << 4;
-+              } else {
-+                      unsigned long in_rate;
-+                      unsigned div;
-+
-+                      clk = di->clk_di;
-+
-+                      clk_set_rate(clk, sig->mode.pixelclock);
-+
-+                      in_rate = clk_get_rate(clk);
-+                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
-+                      div = clamp(div, 1U, 255U);
-+
-+                      clkgen0 = div << 4;
-+              }
-+      }
-+
-+      di->clk_di_pixel = clk;
-+
-+      /* Set the divider */
-+      ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
-+
-+      /*
-+       * Set the high/low periods.  Bits 24:16 give us the falling edge,
-+       * and bits 8:0 give the rising edge.  LSB is fraction, and is
-+       * based on the divider above.  We want a 50% duty cycle, so set
-+       * the falling edge to be half the divider.
-+       */
-+      ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
-+
-+      /* Finally select the input clock */
-+      val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
-+      if (clk == di->clk_di)
-+              val |= DI_GEN_DI_CLK_EXT;
-+      ipu_di_write(di, val, DI_GENERAL);
-+
-+      dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
-+              sig->mode.pixelclock,
-+              clk_get_rate(di->clk_ipu),
-+              clk_get_rate(di->clk_di),
-+              clk == di->clk_di ? "DI" : "IPU",
-+              clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
-+}
-+
-+/*
-+ * This function is called to adjust a video mode to IPU restrictions.
-+ * It is meant to be called from drm crtc mode_fixup() methods.
-+ */
-+int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
-+{
-+      u32 diff;
-+
-+      if (mode->vfront_porch >= 2)
-+              return 0;
-+
-+      diff = 2 - mode->vfront_porch;
-+
-+      if (mode->vback_porch >= diff) {
-+              mode->vfront_porch = 2;
-+              mode->vback_porch -= diff;
-+      } else if (mode->vsync_len > diff) {
-+              mode->vfront_porch = 2;
-+              mode->vsync_len = mode->vsync_len - diff;
-+      } else {
-+              dev_warn(di->ipu->dev, "failed to adjust videomode\n");
-+              return -EINVAL;
-+      }
-+
-+      dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
-+
-+static u32 ipu_di_gen_polarity(int pin)
-+{
-+      switch (pin) {
-+      case 1:
-+              return DI_GEN_POLARITY_1;
-+      case 2:
-+              return DI_GEN_POLARITY_2;
-+      case 3:
-+              return DI_GEN_POLARITY_3;
-+      case 4:
-+              return DI_GEN_POLARITY_4;
-+      case 5:
-+              return DI_GEN_POLARITY_5;
-+      case 6:
-+              return DI_GEN_POLARITY_6;
-+      case 7:
-+              return DI_GEN_POLARITY_7;
-+      case 8:
-+              return DI_GEN_POLARITY_8;
-+      }
-+      return 0;
-+}
-+
-+int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
-+{
-+      u32 reg;
-+      u32 di_gen, vsync_cnt;
-+      u32 div;
-+
-+      dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
-+              di->id, sig->mode.hactive, sig->mode.vactive);
-+
-+      dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
-+              clk_get_rate(di->clk_ipu),
-+              clk_get_rate(di->clk_di),
-+              sig->mode.pixelclock);
-+
-+      mutex_lock(&di_mutex);
-+
-+      ipu_di_config_clock(di, sig);
-+
-+      div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
-+      div = div / 16;         /* Now divider is integer portion */
-+
-+      /* Setup pixel clock timing */
-+      /* Down time is half of period */
-+      ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
-+
-+      ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
-+      ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
-+
-+      di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
-+      di_gen |= DI_GEN_DI_VSYNC_EXT;
-+
-+      if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
-+              ipu_di_sync_config_interlaced(di, sig);
-+
-+              /* set y_sel = 1 */
-+              di_gen |= 0x10000000;
-+
-+              vsync_cnt = 3;
-+      } else {
-+              ipu_di_sync_config_noninterlaced(di, sig, div);
-+
-+              vsync_cnt = 3;
-+              if (di->id == 1)
-+                      /*
-+                       * TODO: change only for TVEv2, parallel display
-+                       * uses pin 2 / 3
-+                       */
-+                      if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
-+                              vsync_cnt = 6;
-+      }
-+
-+      if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
-+              di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
-+      if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
-+              di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
-+
-+      if (sig->clk_pol)
-+              di_gen |= DI_GEN_POLARITY_DISP_CLK;
-+
-+      ipu_di_write(di, di_gen, DI_GENERAL);
-+
-+      ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
-+                   DI_SYNC_AS_GEN);
-+
-+      reg = ipu_di_read(di, DI_POL);
-+      reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
-+
-+      if (sig->enable_pol)
-+              reg |= DI_POL_DRDY_POLARITY_15;
-+      if (sig->data_pol)
-+              reg |= DI_POL_DRDY_DATA_POLARITY;
-+
-+      ipu_di_write(di, reg, DI_POL);
-+
-+      mutex_unlock(&di_mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
-+
-+int ipu_di_enable(struct ipu_di *di)
-+{
-+      int ret;
-+
-+      WARN_ON(IS_ERR(di->clk_di_pixel));
-+
-+      ret = clk_prepare_enable(di->clk_di_pixel);
-+      if (ret)
-+              return ret;
-+
-+      ipu_module_enable(di->ipu, di->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_enable);
-+
-+int ipu_di_disable(struct ipu_di *di)
-+{
-+      WARN_ON(IS_ERR(di->clk_di_pixel));
-+
-+      ipu_module_disable(di->ipu, di->module);
-+
-+      clk_disable_unprepare(di->clk_di_pixel);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_disable);
-+
-+int ipu_di_get_num(struct ipu_di *di)
-+{
-+      return di->id;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_get_num);
-+
-+static DEFINE_MUTEX(ipu_di_lock);
-+
-+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
-+{
-+      struct ipu_di *di;
-+
-+      if (disp > 1)
-+              return ERR_PTR(-EINVAL);
-+
-+      di = ipu->di_priv[disp];
-+
-+      mutex_lock(&ipu_di_lock);
-+
-+      if (di->inuse) {
-+              di = ERR_PTR(-EBUSY);
-+              goto out;
-+      }
-+
-+      di->inuse = true;
-+out:
-+      mutex_unlock(&ipu_di_lock);
-+
-+      return di;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_get);
-+
-+void ipu_di_put(struct ipu_di *di)
-+{
-+      mutex_lock(&ipu_di_lock);
-+
-+      di->inuse = false;
-+
-+      mutex_unlock(&ipu_di_lock);
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_put);
-+
-+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-+              unsigned long base,
-+              u32 module, struct clk *clk_ipu)
-+{
-+      struct ipu_di *di;
-+
-+      if (id > 1)
-+              return -ENODEV;
-+
-+      di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
-+      if (!di)
-+              return -ENOMEM;
-+
-+      ipu->di_priv[id] = di;
-+
-+      di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
-+      if (IS_ERR(di->clk_di))
-+              return PTR_ERR(di->clk_di);
-+
-+      di->module = module;
-+      di->id = id;
-+      di->clk_ipu = clk_ipu;
-+      di->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!di->base)
-+              return -ENOMEM;
-+
-+      ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
-+
-+      dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
-+                      id, base, di->base);
-+      di->inuse = false;
-+      di->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_di_exit(struct ipu_soc *ipu, int id)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-dmfc.c
-@@ -0,0 +1,214 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DMFC_RD_CHAN          0x0000
-+#define DMFC_WR_CHAN          0x0004
-+#define DMFC_WR_CHAN_DEF      0x0008
-+#define DMFC_DP_CHAN          0x000c
-+#define DMFC_DP_CHAN_DEF      0x0010
-+#define DMFC_GENERAL1         0x0014
-+#define DMFC_GENERAL2         0x0018
-+#define DMFC_IC_CTRL          0x001c
-+#define DMFC_WR_CHAN_ALT      0x0020
-+#define DMFC_WR_CHAN_DEF_ALT  0x0024
-+#define DMFC_DP_CHAN_ALT      0x0028
-+#define DMFC_DP_CHAN_DEF_ALT  0x002c
-+#define DMFC_GENERAL1_ALT     0x0030
-+#define DMFC_STAT             0x0034
-+
-+#define DMFC_WR_CHAN_1_28             0
-+#define DMFC_WR_CHAN_2_41             8
-+#define DMFC_WR_CHAN_1C_42            16
-+#define DMFC_WR_CHAN_2C_43            24
-+
-+#define DMFC_DP_CHAN_5B_23            0
-+#define DMFC_DP_CHAN_5F_27            8
-+#define DMFC_DP_CHAN_6B_24            16
-+#define DMFC_DP_CHAN_6F_29            24
-+
-+struct dmfc_channel_data {
-+      int             ipu_channel;
-+      unsigned long   channel_reg;
-+      unsigned long   shift;
-+      unsigned        eot_shift;
-+      unsigned        max_fifo_lines;
-+};
-+
-+static const struct dmfc_channel_data dmfcdata[] = {
-+      {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_5B_23,
-+              .eot_shift      = 20,
-+              .max_fifo_lines = 3,
-+      }, {
-+              .ipu_channel    = 24,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_6B_24,
-+              .eot_shift      = 22,
-+              .max_fifo_lines = 1,
-+      }, {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_5F_27,
-+              .eot_shift      = 21,
-+              .max_fifo_lines = 2,
-+      }, {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
-+              .channel_reg    = DMFC_WR_CHAN,
-+              .shift          = DMFC_WR_CHAN_1_28,
-+              .eot_shift      = 16,
-+              .max_fifo_lines = 2,
-+      }, {
-+              .ipu_channel    = 29,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_6F_29,
-+              .eot_shift      = 23,
-+              .max_fifo_lines = 1,
-+      },
-+};
-+
-+#define DMFC_NUM_CHANNELS     ARRAY_SIZE(dmfcdata)
-+
-+struct ipu_dmfc_priv;
-+
-+struct dmfc_channel {
-+      unsigned                        slots;
-+      struct ipu_soc                  *ipu;
-+      struct ipu_dmfc_priv            *priv;
-+      const struct dmfc_channel_data  *data;
-+};
-+
-+struct ipu_dmfc_priv {
-+      struct ipu_soc *ipu;
-+      struct device *dev;
-+      struct dmfc_channel channels[DMFC_NUM_CHANNELS];
-+      struct mutex mutex;
-+      void __iomem *base;
-+      int use_count;
-+};
-+
-+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
-+
-+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
-+
-+void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+      u32 dmfc_gen1;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
-+
-+      if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
-+              dmfc_gen1 |= 1 << dmfc->data->eot_shift;
-+      else
-+              dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
-+
-+      writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
-+
-+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
-+{
-+      struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
-+      int i;
-+
-+      for (i = 0; i < DMFC_NUM_CHANNELS; i++)
-+              if (dmfcdata[i].ipu_channel == ipu_channel)
-+                      return &priv->channels[i];
-+      return ERR_PTR(-ENODEV);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_get);
-+
-+void ipu_dmfc_put(struct dmfc_channel *dmfc)
-+{
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_put);
-+
-+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              struct clk *ipu_clk)
-+{
-+      struct ipu_dmfc_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+      mutex_init(&priv->mutex);
-+
-+      ipu->dmfc_priv = priv;
-+
-+      for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
-+              priv->channels[i].priv = priv;
-+              priv->channels[i].ipu = ipu;
-+              priv->channels[i].data = &dmfcdata[i];
-+
-+              if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
-+                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
-+                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
-+                      priv->channels[i].slots = 2;
-+      }
-+
-+      writel(0x00000050, priv->base + DMFC_WR_CHAN);
-+      writel(0x00005654, priv->base + DMFC_DP_CHAN);
-+      writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
-+      writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
-+      writel(0x00000003, priv->base + DMFC_GENERAL1);
-+
-+      return 0;
-+}
-+
-+void ipu_dmfc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-dp.c
-@@ -0,0 +1,357 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DP_SYNC 0
-+#define DP_ASYNC0 0x60
-+#define DP_ASYNC1 0xBC
-+
-+#define DP_COM_CONF           0x0
-+#define DP_GRAPH_WIND_CTRL    0x0004
-+#define DP_FG_POS             0x0008
-+#define DP_CSC_A_0            0x0044
-+#define DP_CSC_A_1            0x0048
-+#define DP_CSC_A_2            0x004C
-+#define DP_CSC_A_3            0x0050
-+#define DP_CSC_0              0x0054
-+#define DP_CSC_1              0x0058
-+
-+#define DP_COM_CONF_FG_EN             (1 << 0)
-+#define DP_COM_CONF_GWSEL             (1 << 1)
-+#define DP_COM_CONF_GWAM              (1 << 2)
-+#define DP_COM_CONF_GWCKE             (1 << 3)
-+#define DP_COM_CONF_CSC_DEF_MASK      (3 << 8)
-+#define DP_COM_CONF_CSC_DEF_OFFSET    8
-+#define DP_COM_CONF_CSC_DEF_FG                (3 << 8)
-+#define DP_COM_CONF_CSC_DEF_BG                (2 << 8)
-+#define DP_COM_CONF_CSC_DEF_BOTH      (1 << 8)
-+
-+#define IPUV3_NUM_FLOWS               3
-+
-+struct ipu_dp_priv;
-+
-+struct ipu_dp {
-+      u32 flow;
-+      bool in_use;
-+      bool foreground;
-+      enum ipu_color_space in_cs;
-+};
-+
-+struct ipu_flow {
-+      struct ipu_dp foreground;
-+      struct ipu_dp background;
-+      enum ipu_color_space out_cs;
-+      void __iomem *base;
-+      struct ipu_dp_priv *priv;
-+};
-+
-+struct ipu_dp_priv {
-+      struct ipu_soc *ipu;
-+      struct device *dev;
-+      void __iomem *base;
-+      struct ipu_flow flow[IPUV3_NUM_FLOWS];
-+      struct mutex mutex;
-+      int use_count;
-+};
-+
-+static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
-+
-+static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
-+{
-+      if (dp->foreground)
-+              return container_of(dp, struct ipu_flow, foreground);
-+      else
-+              return container_of(dp, struct ipu_flow, background);
-+}
-+
-+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
-+              u8 alpha, bool bg_chan)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      if (bg_chan)
-+              reg &= ~DP_COM_CONF_GWSEL;
-+      else
-+              reg |= DP_COM_CONF_GWSEL;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      if (enable) {
-+              reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
-+              writel(reg | ((u32) alpha << 24),
-+                           flow->base + DP_GRAPH_WIND_CTRL);
-+
-+              reg = readl(flow->base + DP_COM_CONF);
-+              writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-+      } else {
-+              reg = readl(flow->base + DP_COM_CONF);
-+              writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-+      }
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
-+
-+int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+
-+      writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
-+
-+static void ipu_dp_csc_init(struct ipu_flow *flow,
-+              enum ipu_color_space in,
-+              enum ipu_color_space out,
-+              u32 place)
-+{
-+      u32 reg;
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-+
-+      if (in == out) {
-+              writel(reg, flow->base + DP_COM_CONF);
-+              return;
-+      }
-+
-+      if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
-+              writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
-+              writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
-+              writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
-+              writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
-+              writel(0x3d6 | (0x0000 << 16) | (2 << 30),
-+                              flow->base + DP_CSC_0);
-+              writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
-+                              flow->base + DP_CSC_1);
-+      } else {
-+              writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
-+              writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
-+              writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
-+              writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
-+              writel(0x000 | (0x3e42 << 16) | (1 << 30),
-+                              flow->base + DP_CSC_0);
-+              writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
-+                              flow->base + DP_CSC_1);
-+      }
-+
-+      reg |= place;
-+
-+      writel(reg, flow->base + DP_COM_CONF);
-+}
-+
-+int ipu_dp_setup_channel(struct ipu_dp *dp,
-+              enum ipu_color_space in,
-+              enum ipu_color_space out)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      dp->in_cs = in;
-+
-+      if (!dp->foreground)
-+              flow->out_cs = out;
-+
-+      if (flow->foreground.in_cs == flow->background.in_cs) {
-+              /*
-+               * foreground and background are of same colorspace, put
-+               * colorspace converter after combining unit.
-+               */
-+              ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
-+                              DP_COM_CONF_CSC_DEF_BOTH);
-+      } else {
-+              if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
-+                  flow->foreground.in_cs == flow->out_cs)
-+                      /*
-+                       * foreground identical to output, apply color
-+                       * conversion on background
-+                       */
-+                      ipu_dp_csc_init(flow, flow->background.in_cs,
-+                                      flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
-+              else
-+                      ipu_dp_csc_init(flow, flow->foreground.in_cs,
-+                                      flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
-+      }
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
-+
-+int ipu_dp_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_enable);
-+
-+int ipu_dp_enable_channel(struct ipu_dp *dp)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg;
-+
-+      if (!dp->foreground)
-+              return 0;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      reg |= DP_COM_CONF_FG_EN;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
-+
-+void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg, csc;
-+
-+      dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+
-+      if (!dp->foreground)
-+              return;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      csc = reg & DP_COM_CONF_CSC_DEF_MASK;
-+      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-+      if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
-+              reg |= DP_COM_CONF_CSC_DEF_BG;
-+
-+      reg &= ~DP_COM_CONF_FG_EN;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      writel(0, flow->base + DP_FG_POS);
-+      ipu_srm_dp_update(priv->ipu, sync);
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
-+
-+void ipu_dp_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_disable);
-+
-+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+      struct ipu_dp *dp;
-+
-+      if ((flow >> 1) >= IPUV3_NUM_FLOWS)
-+              return ERR_PTR(-EINVAL);
-+
-+      if (flow & 1)
-+              dp = &priv->flow[flow >> 1].foreground;
-+      else
-+              dp = &priv->flow[flow >> 1].background;
-+
-+      if (dp->in_use)
-+              return ERR_PTR(-EBUSY);
-+
-+      dp->in_use = true;
-+
-+      return dp;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_get);
-+
-+void ipu_dp_put(struct ipu_dp *dp)
-+{
-+      dp->in_use = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_put);
-+
-+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
-+{
-+      struct ipu_dp_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+
-+      ipu->dp_priv = priv;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      mutex_init(&priv->mutex);
-+
-+      for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
-+              priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+              priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+              priv->flow[i].foreground.foreground = true;
-+              priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
-+              priv->flow[i].priv = priv;
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_dp_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-ic.c
-@@ -0,0 +1,761 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2014 Mentor Graphics Inc.
-+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/spinlock.h>
-+#include <linux/bitrev.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/sizes.h>
-+#include "ipu-prv.h"
-+
-+/* IC Register Offsets */
-+#define IC_CONF                 0x0000
-+#define IC_PRP_ENC_RSC          0x0004
-+#define IC_PRP_VF_RSC           0x0008
-+#define IC_PP_RSC               0x000C
-+#define IC_CMBP_1               0x0010
-+#define IC_CMBP_2               0x0014
-+#define IC_IDMAC_1              0x0018
-+#define IC_IDMAC_2              0x001C
-+#define IC_IDMAC_3              0x0020
-+#define IC_IDMAC_4              0x0024
-+
-+/* IC Register Fields */
-+#define IC_CONF_PRPENC_EN       (1 << 0)
-+#define IC_CONF_PRPENC_CSC1     (1 << 1)
-+#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
-+#define IC_CONF_PRPVF_EN        (1 << 8)
-+#define IC_CONF_PRPVF_CSC1      (1 << 9)
-+#define IC_CONF_PRPVF_CSC2      (1 << 10)
-+#define IC_CONF_PRPVF_CMB       (1 << 11)
-+#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
-+#define IC_CONF_PP_EN           (1 << 16)
-+#define IC_CONF_PP_CSC1         (1 << 17)
-+#define IC_CONF_PP_CSC2         (1 << 18)
-+#define IC_CONF_PP_CMB          (1 << 19)
-+#define IC_CONF_PP_ROT_EN       (1 << 20)
-+#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
-+#define IC_CONF_KEY_COLOR_EN    (1 << 29)
-+#define IC_CONF_RWS_EN          (1 << 30)
-+#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
-+
-+#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
-+#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
-+#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
-+#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
-+#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
-+#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
-+#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
-+#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
-+#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
-+#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
-+#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
-+#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
-+#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
-+#define IC_IDMAC_1_PP_ROT_OFFSET        17
-+#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
-+#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
-+#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
-+
-+#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
-+#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
-+#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
-+#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
-+#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
-+#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
-+
-+#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
-+#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
-+#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
-+#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
-+#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
-+#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
-+
-+struct ic_task_regoffs {
-+      u32 rsc;
-+      u32 tpmem_csc[2];
-+};
-+
-+struct ic_task_bitfields {
-+      u32 ic_conf_en;
-+      u32 ic_conf_rot_en;
-+      u32 ic_conf_cmb_en;
-+      u32 ic_conf_csc1_en;
-+      u32 ic_conf_csc2_en;
-+      u32 ic_cmb_galpha_bit;
-+};
-+
-+static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
-+      [IC_TASK_ENCODER] = {
-+              .rsc = IC_PRP_ENC_RSC,
-+              .tpmem_csc = {0x2008, 0},
-+      },
-+      [IC_TASK_VIEWFINDER] = {
-+              .rsc = IC_PRP_VF_RSC,
-+              .tpmem_csc = {0x4028, 0x4040},
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .rsc = IC_PP_RSC,
-+              .tpmem_csc = {0x6060, 0x6078},
-+      },
-+};
-+
-+static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
-+      [IC_TASK_ENCODER] = {
-+              .ic_conf_en = IC_CONF_PRPENC_EN,
-+              .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
-+              .ic_conf_cmb_en = 0,    /* NA */
-+              .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
-+              .ic_conf_csc2_en = 0,   /* NA */
-+              .ic_cmb_galpha_bit = 0, /* NA */
-+      },
-+      [IC_TASK_VIEWFINDER] = {
-+              .ic_conf_en = IC_CONF_PRPVF_EN,
-+              .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
-+              .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
-+              .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
-+              .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
-+              .ic_cmb_galpha_bit = 0,
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .ic_conf_en = IC_CONF_PP_EN,
-+              .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
-+              .ic_conf_cmb_en = IC_CONF_PP_CMB,
-+              .ic_conf_csc1_en = IC_CONF_PP_CSC1,
-+              .ic_conf_csc2_en = IC_CONF_PP_CSC2,
-+              .ic_cmb_galpha_bit = 8,
-+      },
-+};
-+
-+struct ipu_ic_priv;
-+
-+struct ipu_ic {
-+      enum ipu_ic_task task;
-+      const struct ic_task_regoffs *reg;
-+      const struct ic_task_bitfields *bit;
-+
-+      struct ipu_ic_colorspace in_cs;
-+      struct ipu_ic_colorspace g_in_cs;
-+      struct ipu_ic_colorspace out_cs;
-+
-+      bool graphics;
-+      bool rotation;
-+      bool in_use;
-+
-+      struct ipu_ic_priv *priv;
-+};
-+
-+struct ipu_ic_priv {
-+      void __iomem *base;
-+      void __iomem *tpmem_base;
-+      spinlock_t lock;
-+      struct ipu_soc *ipu;
-+      int use_count;
-+      int irt_use_count;
-+      struct ipu_ic task[IC_NUM_TASKS];
-+};
-+
-+static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
-+{
-+      return readl(ic->priv->base + offset);
-+}
-+
-+static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
-+{
-+      writel(value, ic->priv->base + offset);
-+}
-+
-+static int init_csc(struct ipu_ic *ic,
-+                  const struct ipu_ic_csc *csc,
-+                  int csc_index)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      u32 __iomem *base;
-+      const u16 (*c)[3];
-+      const u16 *a;
-+      u32 param;
-+
-+      base = (u32 __iomem *)
-+              (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
-+
-+      /* Cast to unsigned */
-+      c = (const u16 (*)[3])csc->params.coeff;
-+      a = (const u16 *)csc->params.offset;
-+
-+      param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
-+              ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
-+              (csc->params.sat << 10);
-+      writel(param, base++);
-+
-+      param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
-+              ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[1] & 0x1fe0) >> 5);
-+      writel(param, base++);
-+
-+      param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
-+              ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[2] & 0x1fe0) >> 5);
-+      writel(param, base++);
-+
-+      return 0;
-+}
-+
-+static int calc_resize_coeffs(struct ipu_ic *ic,
-+                            u32 in_size, u32 out_size,
-+                            u32 *resize_coeff,
-+                            u32 *downsize_coeff)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+      u32 temp_size, temp_downsize;
-+
-+      /*
-+       * Input size cannot be more than 4096, and output size cannot
-+       * be more than 1024
-+       */
-+      if (in_size > 4096) {
-+              dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
-+              return -EINVAL;
-+      }
-+      if (out_size > 1024) {
-+              dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Cannot downsize more than 4:1 */
-+      if ((out_size << 2) < in_size) {
-+              dev_err(ipu->dev, "Unsupported downsize\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Compute downsizing coefficient */
-+      temp_downsize = 0;
-+      temp_size = in_size;
-+      while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
-+             (temp_downsize < 2)) {
-+              temp_size >>= 1;
-+              temp_downsize++;
-+      }
-+      *downsize_coeff = temp_downsize;
-+
-+      /*
-+       * compute resizing coefficient using the following equation:
-+       * resize_coeff = M * (SI - 1) / (SO - 1)
-+       * where M = 2^13, SI = input size, SO = output size
-+       */
-+      *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
-+      if (*resize_coeff >= 16384L) {
-+              dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
-+              *resize_coeff = 0x3FFF;
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_ic_task_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+      u32 ic_conf;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      ic_conf |= ic->bit->ic_conf_en;
-+
-+      if (ic->rotation)
-+              ic_conf |= ic->bit->ic_conf_rot_en;
-+
-+      if (ic->in_cs.cs != ic->out_cs.cs)
-+              ic_conf |= ic->bit->ic_conf_csc1_en;
-+
-+      if (ic->graphics) {
-+              ic_conf |= ic->bit->ic_conf_cmb_en;
-+              ic_conf |= ic->bit->ic_conf_csc1_en;
-+
-+              if (ic->g_in_cs.cs != ic->out_cs.cs)
-+                      ic_conf |= ic->bit->ic_conf_csc2_en;
-+      }
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
-+
-+void ipu_ic_task_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+      u32 ic_conf;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      ic_conf &= ~(ic->bit->ic_conf_en |
-+                   ic->bit->ic_conf_csc1_en |
-+                   ic->bit->ic_conf_rot_en);
-+      if (ic->bit->ic_conf_csc2_en)
-+              ic_conf &= ~ic->bit->ic_conf_csc2_en;
-+      if (ic->bit->ic_conf_cmb_en)
-+              ic_conf &= ~ic->bit->ic_conf_cmb_en;
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
-+
-+int ipu_ic_task_graphics_init(struct ipu_ic *ic,
-+                            const struct ipu_ic_colorspace *g_in_cs,
-+                            bool galpha_en, u32 galpha,
-+                            bool colorkey_en, u32 colorkey)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_ic_csc csc2;
-+      unsigned long flags;
-+      u32 reg, ic_conf;
-+      int ret = 0;
-+
-+      if (ic->task == IC_TASK_ENCODER)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
-+              struct ipu_ic_csc csc1;
-+
-+              ret = ipu_ic_calc_csc(&csc1,
-+                                    V4L2_YCBCR_ENC_601,
-+                                    V4L2_QUANTIZATION_FULL_RANGE,
-+                                    IPUV3_COLORSPACE_RGB,
-+                                    V4L2_YCBCR_ENC_601,
-+                                    V4L2_QUANTIZATION_FULL_RANGE,
-+                                    IPUV3_COLORSPACE_RGB);
-+              if (ret)
-+                      goto unlock;
-+
-+              /* need transparent CSC1 conversion */
-+              ret = init_csc(ic, &csc1, 0);
-+              if (ret)
-+                      goto unlock;
-+      }
-+
-+      ic->g_in_cs = *g_in_cs;
-+      csc2.in_cs = ic->g_in_cs;
-+      csc2.out_cs = ic->out_cs;
-+
-+      ret = __ipu_ic_calc_csc(&csc2);
-+      if (ret)
-+              goto unlock;
-+
-+      ret = init_csc(ic, &csc2, 1);
-+      if (ret)
-+              goto unlock;
-+
-+      if (galpha_en) {
-+              ic_conf |= IC_CONF_IC_GLB_LOC_A;
-+              reg = ipu_ic_read(ic, IC_CMBP_1);
-+              reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
-+              reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
-+              ipu_ic_write(ic, reg, IC_CMBP_1);
-+      } else
-+              ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
-+
-+      if (colorkey_en) {
-+              ic_conf |= IC_CONF_KEY_COLOR_EN;
-+              ipu_ic_write(ic, colorkey, IC_CMBP_2);
-+      } else
-+              ic_conf &= ~IC_CONF_KEY_COLOR_EN;
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      ic->graphics = true;
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
-+
-+int ipu_ic_task_init_rsc(struct ipu_ic *ic,
-+                       const struct ipu_ic_csc *csc,
-+                       int in_width, int in_height,
-+                       int out_width, int out_height,
-+                       u32 rsc)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      u32 downsize_coeff, resize_coeff;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if (!rsc) {
-+              /* Setup vertical resizing */
-+
-+              ret = calc_resize_coeffs(ic, in_height, out_height,
-+                                       &resize_coeff, &downsize_coeff);
-+              if (ret)
-+                      return ret;
-+
-+              rsc = (downsize_coeff << 30) | (resize_coeff << 16);
-+
-+              /* Setup horizontal resizing */
-+              ret = calc_resize_coeffs(ic, in_width, out_width,
-+                                       &resize_coeff, &downsize_coeff);
-+              if (ret)
-+                      return ret;
-+
-+              rsc |= (downsize_coeff << 14) | resize_coeff;
-+      }
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ipu_ic_write(ic, rsc, ic->reg->rsc);
-+
-+      /* Setup color space conversion */
-+      ic->in_cs = csc->in_cs;
-+      ic->out_cs = csc->out_cs;
-+
-+      ret = init_csc(ic, csc, 0);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+
-+int ipu_ic_task_init(struct ipu_ic *ic,
-+                   const struct ipu_ic_csc *csc,
-+                   int in_width, int in_height,
-+                   int out_width, int out_height)
-+{
-+      return ipu_ic_task_init_rsc(ic, csc,
-+                                  in_width, in_height,
-+                                  out_width, out_height, 0);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_init);
-+
-+int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
-+                        u32 width, u32 height, int burst_size,
-+                        enum ipu_rotate_mode rot)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+      u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
-+      u32 temp_rot = bitrev8(rot) >> 5;
-+      bool need_hor_flip = false;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if ((burst_size != 8) && (burst_size != 16)) {
-+              dev_err(ipu->dev, "Illegal burst length for IC\n");
-+              return -EINVAL;
-+      }
-+
-+      width--;
-+      height--;
-+
-+      if (temp_rot & 0x2)     /* Need horizontal flip */
-+              need_hor_flip = true;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
-+      ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
-+      ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
-+
-+      switch (channel->num) {
-+      case IPUV3_CHANNEL_IC_PP_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_IC_PP:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_PP:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_IC_PRP_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_ENC:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_IC_PRP_VF_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_VF:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_G_MEM_IC_PP:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_VDI_MEM_IC_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
-+              break;
-+      default:
-+              goto unlock;
-+      }
-+
-+      ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
-+      ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
-+      ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
-+
-+      if (ipu_rot_mode_is_irt(rot))
-+              ic->rotation = true;
-+
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
-+
-+static void ipu_irt_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+
-+      if (!priv->irt_use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
-+
-+      priv->irt_use_count++;
-+}
-+
-+static void ipu_irt_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+
-+      if (priv->irt_use_count) {
-+              if (!--priv->irt_use_count)
-+                      ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
-+      }
-+}
-+
-+int ipu_ic_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
-+
-+      priv->use_count++;
-+
-+      if (ic->rotation)
-+              ipu_irt_enable(ic);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_enable);
-+
-+int ipu_ic_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      if (ic->rotation)
-+              ipu_irt_disable(ic);
-+
-+      ic->rotation = ic->graphics = false;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_disable);
-+
-+struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
-+{
-+      struct ipu_ic_priv *priv = ipu->ic_priv;
-+      unsigned long flags;
-+      struct ipu_ic *ic, *ret;
-+
-+      if (task >= IC_NUM_TASKS)
-+              return ERR_PTR(-EINVAL);
-+
-+      ic = &priv->task[task];
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (ic->in_use) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      ic->in_use = true;
-+      ret = ic;
-+
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_get);
-+
-+void ipu_ic_put(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+      ic->in_use = false;
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_put);
-+
-+int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long tpmem_base)
-+{
-+      struct ipu_ic_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->ic_priv = priv;
-+
-+      spin_lock_init(&priv->lock);
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+      priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
-+      if (!priv->tpmem_base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
-+
-+      priv->ipu = ipu;
-+
-+      for (i = 0; i < IC_NUM_TASKS; i++) {
-+              priv->task[i].task = i;
-+              priv->task[i].priv = priv;
-+              priv->task[i].reg = &ic_task_reg[i];
-+              priv->task[i].bit = &ic_task_bit[i];
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_ic_exit(struct ipu_soc *ipu)
-+{
-+}
-+
-+void ipu_ic_dump(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+
-+      dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CONF));
-+      dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PRP_ENC_RSC));
-+      dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PRP_VF_RSC));
-+      dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PP_RSC));
-+      dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CMBP_1));
-+      dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CMBP_2));
-+      dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_1));
-+      dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_2));
-+      dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_3));
-+      dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_4));
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_dump);
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-image-convert.c
-@@ -0,0 +1,2475 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2016 Mentor Graphics Inc.
-+ *
-+ * Queued image conversion support, with tiling and rotation.
-+ */
-+
-+#include <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <video/imx-ipu-image-convert.h>
-+#include "ipu-prv.h"
-+
-+/*
-+ * The IC Resizer has a restriction that the output frame from the
-+ * resizer must be 1024 or less in both width (pixels) and height
-+ * (lines).
-+ *
-+ * The image converter attempts to split up a conversion when
-+ * the desired output (converted) frame resolution exceeds the
-+ * IC resizer limit of 1024 in either dimension.
-+ *
-+ * If either dimension of the output frame exceeds the limit, the
-+ * dimension is split into 1, 2, or 4 equal stripes, for a maximum
-+ * of 4*4 or 16 tiles. A conversion is then carried out for each
-+ * tile (but taking care to pass the full frame stride length to
-+ * the DMA channel's parameter memory!). IDMA double-buffering is used
-+ * to convert each tile back-to-back when possible (see note below
-+ * when double_buffering boolean is set).
-+ *
-+ * Note that the input frame must be split up into the same number
-+ * of tiles as the output frame:
-+ *
-+ *                       +---------+-----+
-+ *   +-----+---+         |  A      | B   |
-+ *   | A   | B |         |         |     |
-+ *   +-----+---+   -->   +---------+-----+
-+ *   | C   | D |         |  C      | D   |
-+ *   +-----+---+         |         |     |
-+ *                       +---------+-----+
-+ *
-+ * Clockwise 90° rotations are handled by first rescaling into a
-+ * reusable temporary tile buffer and then rotating with the 8x8
-+ * block rotator, writing to the correct destination:
-+ *
-+ *                                         +-----+-----+
-+ *                                         |     |     |
-+ *   +-----+---+         +---------+       | C   | A   |
-+ *   | A   | B |         | A,B, |  |       |     |     |
-+ *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
-+ *   | C   | D |         +---------+       +-----+-----+
-+ *   +-----+---+                           | D   | B   |
-+ *                                         |     |     |
-+ *                                         +-----+-----+
-+ *
-+ * If the 8x8 block rotator is used, horizontal or vertical flipping
-+ * is done during the rotation step, otherwise flipping is done
-+ * during the scaling step.
-+ * With rotation or flipping, tile order changes between input and
-+ * output image. Tiles are numbered row major from top left to bottom
-+ * right for both input and output image.
-+ */
-+
-+#define MAX_STRIPES_W    4
-+#define MAX_STRIPES_H    4
-+#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
-+
-+#define MIN_W     16
-+#define MIN_H     8
-+#define MAX_W     4096
-+#define MAX_H     4096
-+
-+enum ipu_image_convert_type {
-+      IMAGE_CONVERT_IN = 0,
-+      IMAGE_CONVERT_OUT,
-+};
-+
-+struct ipu_image_convert_dma_buf {
-+      void          *virt;
-+      dma_addr_t    phys;
-+      unsigned long len;
-+};
-+
-+struct ipu_image_convert_dma_chan {
-+      int in;
-+      int out;
-+      int rot_in;
-+      int rot_out;
-+      int vdi_in_p;
-+      int vdi_in;
-+      int vdi_in_n;
-+};
-+
-+/* dimensions of one tile */
-+struct ipu_image_tile {
-+      u32 width;
-+      u32 height;
-+      u32 left;
-+      u32 top;
-+      /* size and strides are in bytes */
-+      u32 size;
-+      u32 stride;
-+      u32 rot_stride;
-+      /* start Y or packed offset of this tile */
-+      u32 offset;
-+      /* offset from start to tile in U plane, for planar formats */
-+      u32 u_off;
-+      /* offset from start to tile in V plane, for planar formats */
-+      u32 v_off;
-+};
-+
-+struct ipu_image_convert_image {
-+      struct ipu_image base;
-+      enum ipu_image_convert_type type;
-+
-+      const struct ipu_image_pixfmt *fmt;
-+      unsigned int stride;
-+
-+      /* # of rows (horizontal stripes) if dest height is > 1024 */
-+      unsigned int num_rows;
-+      /* # of columns (vertical stripes) if dest width is > 1024 */
-+      unsigned int num_cols;
-+
-+      struct ipu_image_tile tile[MAX_TILES];
-+};
-+
-+struct ipu_image_pixfmt {
-+      u32     fourcc;        /* V4L2 fourcc */
-+      int     bpp;           /* total bpp */
-+      int     uv_width_dec;  /* decimation in width for U/V planes */
-+      int     uv_height_dec; /* decimation in height for U/V planes */
-+      bool    planar;        /* planar format */
-+      bool    uv_swapped;    /* U and V planes are swapped */
-+      bool    uv_packed;     /* partial planar (U and V in same plane) */
-+};
-+
-+struct ipu_image_convert_ctx;
-+struct ipu_image_convert_chan;
-+struct ipu_image_convert_priv;
-+
-+struct ipu_image_convert_ctx {
-+      struct ipu_image_convert_chan *chan;
-+
-+      ipu_image_convert_cb_t complete;
-+      void *complete_context;
-+
-+      /* Source/destination image data and rotation mode */
-+      struct ipu_image_convert_image in;
-+      struct ipu_image_convert_image out;
-+      struct ipu_ic_csc csc;
-+      enum ipu_rotate_mode rot_mode;
-+      u32 downsize_coeff_h;
-+      u32 downsize_coeff_v;
-+      u32 image_resize_coeff_h;
-+      u32 image_resize_coeff_v;
-+      u32 resize_coeffs_h[MAX_STRIPES_W];
-+      u32 resize_coeffs_v[MAX_STRIPES_H];
-+
-+      /* intermediate buffer for rotation */
-+      struct ipu_image_convert_dma_buf rot_intermediate[2];
-+
-+      /* current buffer number for double buffering */
-+      int cur_buf_num;
-+
-+      bool aborting;
-+      struct completion aborted;
-+
-+      /* can we use double-buffering for this conversion operation? */
-+      bool double_buffering;
-+      /* num_rows * num_cols */
-+      unsigned int num_tiles;
-+      /* next tile to process */
-+      unsigned int next_tile;
-+      /* where to place converted tile in dest image */
-+      unsigned int out_tile_map[MAX_TILES];
-+
-+      struct list_head list;
-+};
-+
-+struct ipu_image_convert_chan {
-+      struct ipu_image_convert_priv *priv;
-+
-+      enum ipu_ic_task ic_task;
-+      const struct ipu_image_convert_dma_chan *dma_ch;
-+
-+      struct ipu_ic *ic;
-+      struct ipuv3_channel *in_chan;
-+      struct ipuv3_channel *out_chan;
-+      struct ipuv3_channel *rotation_in_chan;
-+      struct ipuv3_channel *rotation_out_chan;
-+
-+      /* the IPU end-of-frame irqs */
-+      int out_eof_irq;
-+      int rot_out_eof_irq;
-+
-+      spinlock_t irqlock;
-+
-+      /* list of convert contexts */
-+      struct list_head ctx_list;
-+      /* queue of conversion runs */
-+      struct list_head pending_q;
-+      /* queue of completed runs */
-+      struct list_head done_q;
-+
-+      /* the current conversion run */
-+      struct ipu_image_convert_run *current_run;
-+};
-+
-+struct ipu_image_convert_priv {
-+      struct ipu_image_convert_chan chan[IC_NUM_TASKS];
-+      struct ipu_soc *ipu;
-+};
-+
-+static const struct ipu_image_convert_dma_chan
-+image_convert_dma_chan[IC_NUM_TASKS] = {
-+      [IC_TASK_VIEWFINDER] = {
-+              .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
-+              .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
-+              .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
-+              .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
-+              .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
-+              .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
-+              .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .in = IPUV3_CHANNEL_MEM_IC_PP,
-+              .out = IPUV3_CHANNEL_IC_PP_MEM,
-+              .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
-+              .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
-+      },
-+};
-+
-+static const struct ipu_image_pixfmt image_convert_formats[] = {
-+      {
-+              .fourcc = V4L2_PIX_FMT_RGB565,
-+              .bpp    = 16,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGB24,
-+              .bpp    = 24,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGR24,
-+              .bpp    = 24,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGB32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGR32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_XRGB32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_XBGR32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGRX32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGBX32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUYV,
-+              .bpp    = 16,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_UYVY,
-+              .bpp    = 16,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUV420,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YVU420,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+              .uv_swapped = true,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_NV12,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+              .uv_packed = true,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUV422P,
-+              .bpp    = 16,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_NV16,
-+              .bpp    = 16,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+              .uv_packed = true,
-+      },
-+};
-+
-+static const struct ipu_image_pixfmt *get_format(u32 fourcc)
-+{
-+      const struct ipu_image_pixfmt *ret = NULL;
-+      unsigned int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
-+              if (image_convert_formats[i].fourcc == fourcc) {
-+                      ret = &image_convert_formats[i];
-+                      break;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static void dump_format(struct ipu_image_convert_ctx *ctx,
-+                      struct ipu_image_convert_image *ic_image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev,
-+              "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
-+              chan->ic_task, ctx,
-+              ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
-+              ic_image->base.pix.width, ic_image->base.pix.height,
-+              ic_image->num_cols, ic_image->num_rows,
-+              ic_image->fmt->fourcc & 0xff,
-+              (ic_image->fmt->fourcc >> 8) & 0xff,
-+              (ic_image->fmt->fourcc >> 16) & 0xff,
-+              (ic_image->fmt->fourcc >> 24) & 0xff);
-+}
-+
-+int ipu_image_convert_enum_format(int index, u32 *fourcc)
-+{
-+      const struct ipu_image_pixfmt *fmt;
-+
-+      if (index >= (int)ARRAY_SIZE(image_convert_formats))
-+              return -EINVAL;
-+
-+      /* Format found */
-+      fmt = &image_convert_formats[index];
-+      *fourcc = fmt->fourcc;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
-+
-+static void free_dma_buf(struct ipu_image_convert_priv *priv,
-+                       struct ipu_image_convert_dma_buf *buf)
-+{
-+      if (buf->virt)
-+              dma_free_coherent(priv->ipu->dev,
-+                                buf->len, buf->virt, buf->phys);
-+      buf->virt = NULL;
-+      buf->phys = 0;
-+}
-+
-+static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
-+                       struct ipu_image_convert_dma_buf *buf,
-+                       int size)
-+{
-+      buf->len = PAGE_ALIGN(size);
-+      buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
-+                                     GFP_DMA | GFP_KERNEL);
-+      if (!buf->virt) {
-+              dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static inline int num_stripes(int dim)
-+{
-+      return (dim - 1) / 1024 + 1;
-+}
-+
-+/*
-+ * Calculate downsizing coefficients, which are the same for all tiles,
-+ * and initial bilinear resizing coefficients, which are used to find the
-+ * best seam positions.
-+ * Also determine the number of tiles necessary to guarantee that no tile
-+ * is larger than 1024 pixels in either dimension at the output and between
-+ * IC downsizing and main processing sections.
-+ */
-+static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
-+                                        struct ipu_image *in,
-+                                        struct ipu_image *out)
-+{
-+      u32 downsized_width = in->rect.width;
-+      u32 downsized_height = in->rect.height;
-+      u32 downsize_coeff_v = 0;
-+      u32 downsize_coeff_h = 0;
-+      u32 resized_width = out->rect.width;
-+      u32 resized_height = out->rect.height;
-+      u32 resize_coeff_h;
-+      u32 resize_coeff_v;
-+      u32 cols;
-+      u32 rows;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              resized_width = out->rect.height;
-+              resized_height = out->rect.width;
-+      }
-+
-+      /* Do not let invalid input lead to an endless loop below */
-+      if (WARN_ON(resized_width == 0 || resized_height == 0))
-+              return -EINVAL;
-+
-+      while (downsized_width >= resized_width * 2) {
-+              downsized_width >>= 1;
-+              downsize_coeff_h++;
-+      }
-+
-+      while (downsized_height >= resized_height * 2) {
-+              downsized_height >>= 1;
-+              downsize_coeff_v++;
-+      }
-+
-+      /*
-+       * Calculate the bilinear resizing coefficients that could be used if
-+       * we were converting with a single tile. The bottom right output pixel
-+       * should sample as close as possible to the bottom right input pixel
-+       * out of the decimator, but not overshoot it:
-+       */
-+      resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
-+      resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
-+
-+      /*
-+       * Both the output of the IC downsizing section before being passed to
-+       * the IC main processing section and the final output of the IC main
-+       * processing section must be <= 1024 pixels in both dimensions.
-+       */
-+      cols = num_stripes(max_t(u32, downsized_width, resized_width));
-+      rows = num_stripes(max_t(u32, downsized_height, resized_height));
-+
-+      dev_dbg(ctx->chan->priv->ipu->dev,
-+              "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
-+              __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
-+              resize_coeff_v, cols, rows);
-+
-+      if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
-+          resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
-+              return -EINVAL;
-+
-+      ctx->downsize_coeff_h = downsize_coeff_h;
-+      ctx->downsize_coeff_v = downsize_coeff_v;
-+      ctx->image_resize_coeff_h = resize_coeff_h;
-+      ctx->image_resize_coeff_v = resize_coeff_v;
-+      ctx->in.num_cols = cols;
-+      ctx->in.num_rows = rows;
-+
-+      return 0;
-+}
-+
-+#define round_closest(x, y) round_down((x) + (y)/2, (y))
-+
-+/*
-+ * Find the best aligned seam position for the given column / row index.
-+ * Rotation and image offsets are out of scope.
-+ *
-+ * @index: column / row index, used to calculate valid interval
-+ * @in_edge: input right / bottom edge
-+ * @out_edge: output right / bottom edge
-+ * @in_align: input alignment, either horizontal 8-byte line start address
-+ *            alignment, or pixel alignment due to image format
-+ * @out_align: output alignment, either horizontal 8-byte line start address
-+ *             alignment, or pixel alignment due to image format or rotator
-+ *             block size
-+ * @in_burst: horizontal input burst size in case of horizontal flip
-+ * @out_burst: horizontal output burst size or rotator block size
-+ * @downsize_coeff: downsizing section coefficient
-+ * @resize_coeff: main processing section resizing coefficient
-+ * @_in_seam: aligned input seam position return value
-+ * @_out_seam: aligned output seam position return value
-+ */
-+static void find_best_seam(struct ipu_image_convert_ctx *ctx,
-+                         unsigned int index,
-+                         unsigned int in_edge,
-+                         unsigned int out_edge,
-+                         unsigned int in_align,
-+                         unsigned int out_align,
-+                         unsigned int in_burst,
-+                         unsigned int out_burst,
-+                         unsigned int downsize_coeff,
-+                         unsigned int resize_coeff,
-+                         u32 *_in_seam,
-+                         u32 *_out_seam)
-+{
-+      struct device *dev = ctx->chan->priv->ipu->dev;
-+      unsigned int out_pos;
-+      /* Input / output seam position candidates */
-+      unsigned int out_seam = 0;
-+      unsigned int in_seam = 0;
-+      unsigned int min_diff = UINT_MAX;
-+      unsigned int out_start;
-+      unsigned int out_end;
-+      unsigned int in_start;
-+      unsigned int in_end;
-+
-+      /* Start within 1024 pixels of the right / bottom edge */
-+      out_start = max_t(int, index * out_align, out_edge - 1024);
-+      /* End before having to add more columns to the left / rows above */
-+      out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
-+
-+      /*
-+       * Limit input seam position to make sure that the downsized input tile
-+       * to the right or bottom does not exceed 1024 pixels.
-+       */
-+      in_start = max_t(int, index * in_align,
-+                       in_edge - (1024 << downsize_coeff));
-+      in_end = min_t(unsigned int, in_edge,
-+                     index * (1024 << downsize_coeff) + 1);
-+
-+      /*
-+       * Output tiles must start at a multiple of 8 bytes horizontally and
-+       * possibly at an even line horizontally depending on the pixel format.
-+       * Only consider output aligned positions for the seam.
-+       */
-+      out_start = round_up(out_start, out_align);
-+      for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
-+              unsigned int in_pos;
-+              unsigned int in_pos_aligned;
-+              unsigned int in_pos_rounded;
-+              unsigned int abs_diff;
-+
-+              /*
-+               * Tiles in the right row / bottom column may not be allowed to
-+               * overshoot horizontally / vertically. out_burst may be the
-+               * actual DMA burst size, or the rotator block size.
-+               */
-+              if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
-+                      continue;
-+
-+              /*
-+               * Input sample position, corresponding to out_pos, 19.13 fixed
-+               * point.
-+               */
-+              in_pos = (out_pos * resize_coeff) << downsize_coeff;
-+              /*
-+               * The closest input sample position that we could actually
-+               * start the input tile at, 19.13 fixed point.
-+               */
-+              in_pos_aligned = round_closest(in_pos, 8192U * in_align);
-+              /* Convert 19.13 fixed point to integer */
-+              in_pos_rounded = in_pos_aligned / 8192U;
-+
-+              if (in_pos_rounded < in_start)
-+                      continue;
-+              if (in_pos_rounded >= in_end)
-+                      break;
-+
-+              if ((in_burst > 1) &&
-+                  (in_edge - in_pos_rounded) % in_burst)
-+                      continue;
-+
-+              if (in_pos < in_pos_aligned)
-+                      abs_diff = in_pos_aligned - in_pos;
-+              else
-+                      abs_diff = in_pos - in_pos_aligned;
-+
-+              if (abs_diff < min_diff) {
-+                      in_seam = in_pos_rounded;
-+                      out_seam = out_pos;
-+                      min_diff = abs_diff;
-+              }
-+      }
-+
-+      *_out_seam = out_seam;
-+      *_in_seam = in_seam;
-+
-+      dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
-+              __func__, out_seam, out_align, out_start, out_end,
-+              in_seam, in_align, in_start, in_end, min_diff / 8192,
-+              DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
-+}
-+
-+/*
-+ * Tile left edges are required to be aligned to multiples of 8 bytes
-+ * by the IDMAC.
-+ */
-+static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
-+{
-+      if (fmt->planar)
-+              return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
-+      else
-+              return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
-+}
-+
-+/*
-+ * Tile top edge alignment is only limited by chroma subsampling.
-+ */
-+static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
-+{
-+      return fmt->uv_height_dec > 1 ? 2 : 1;
-+}
-+
-+static inline u32 tile_width_align(enum ipu_image_convert_type type,
-+                                 const struct ipu_image_pixfmt *fmt,
-+                                 enum ipu_rotate_mode rot_mode)
-+{
-+      if (type == IMAGE_CONVERT_IN) {
-+              /*
-+               * The IC burst reads 8 pixels at a time. Reading beyond the
-+               * end of the line is usually acceptable. Those pixels are
-+               * ignored, unless the IC has to write the scaled line in
-+               * reverse.
-+               */
-+              return (!ipu_rot_mode_is_irt(rot_mode) &&
-+                      (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
-+      }
-+
-+      /*
-+       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
-+       * formats to guarantee 8-byte aligned line start addresses in the
-+       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
-+       * for all other formats.
-+       */
-+      return (ipu_rot_mode_is_irt(rot_mode) &&
-+              fmt->planar && !fmt->uv_packed) ?
-+              8 * fmt->uv_width_dec : 8;
-+}
-+
-+static inline u32 tile_height_align(enum ipu_image_convert_type type,
-+                                  const struct ipu_image_pixfmt *fmt,
-+                                  enum ipu_rotate_mode rot_mode)
-+{
-+      if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
-+              return 2;
-+
-+      /*
-+       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
-+       * formats to guarantee 8-byte aligned line start addresses in the
-+       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
-+       * for all other formats.
-+       */
-+      return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
-+}
-+
-+/*
-+ * Fill in left position and width and for all tiles in an input column, and
-+ * for all corresponding output tiles. If the 90° rotator is used, the output
-+ * tiles are in a row, and output tile top position and height are set.
-+ */
-+static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
-+                           unsigned int col,
-+                           struct ipu_image_convert_image *in,
-+                           unsigned int in_left, unsigned int in_width,
-+                           struct ipu_image_convert_image *out,
-+                           unsigned int out_left, unsigned int out_width)
-+{
-+      unsigned int row, tile_idx;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+
-+      for (row = 0; row < in->num_rows; row++) {
-+              tile_idx = in->num_cols * row + col;
-+              in_tile = &in->tile[tile_idx];
-+              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
-+
-+              in_tile->left = in_left;
-+              in_tile->width = in_width;
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+                      out_tile->top = out_left;
-+                      out_tile->height = out_width;
-+              } else {
-+                      out_tile->left = out_left;
-+                      out_tile->width = out_width;
-+              }
-+      }
-+}
-+
-+/*
-+ * Fill in top position and height and for all tiles in an input row, and
-+ * for all corresponding output tiles. If the 90° rotator is used, the output
-+ * tiles are in a column, and output tile left position and width are set.
-+ */
-+static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
-+                        struct ipu_image_convert_image *in,
-+                        unsigned int in_top, unsigned int in_height,
-+                        struct ipu_image_convert_image *out,
-+                        unsigned int out_top, unsigned int out_height)
-+{
-+      unsigned int col, tile_idx;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+
-+      for (col = 0; col < in->num_cols; col++) {
-+              tile_idx = in->num_cols * row + col;
-+              in_tile = &in->tile[tile_idx];
-+              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
-+
-+              in_tile->top = in_top;
-+              in_tile->height = in_height;
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+                      out_tile->left = out_top;
-+                      out_tile->width = out_height;
-+              } else {
-+                      out_tile->top = out_top;
-+                      out_tile->height = out_height;
-+              }
-+      }
-+}
-+
-+/*
-+ * Find the best horizontal and vertical seam positions to split into tiles.
-+ * Minimize the fractional part of the input sampling position for the
-+ * top / left pixels of each tile.
-+ */
-+static void find_seams(struct ipu_image_convert_ctx *ctx,
-+                     struct ipu_image_convert_image *in,
-+                     struct ipu_image_convert_image *out)
-+{
-+      struct device *dev = ctx->chan->priv->ipu->dev;
-+      unsigned int resized_width = out->base.rect.width;
-+      unsigned int resized_height = out->base.rect.height;
-+      unsigned int col;
-+      unsigned int row;
-+      unsigned int in_left_align = tile_left_align(in->fmt);
-+      unsigned int in_top_align = tile_top_align(in->fmt);
-+      unsigned int out_left_align = tile_left_align(out->fmt);
-+      unsigned int out_top_align = tile_top_align(out->fmt);
-+      unsigned int out_width_align = tile_width_align(out->type, out->fmt,
-+                                                      ctx->rot_mode);
-+      unsigned int out_height_align = tile_height_align(out->type, out->fmt,
-+                                                        ctx->rot_mode);
-+      unsigned int in_right = in->base.rect.width;
-+      unsigned int in_bottom = in->base.rect.height;
-+      unsigned int out_right = out->base.rect.width;
-+      unsigned int out_bottom = out->base.rect.height;
-+      unsigned int flipped_out_left;
-+      unsigned int flipped_out_top;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* Switch width/height and align top left to IRT block size */
-+              resized_width = out->base.rect.height;
-+              resized_height = out->base.rect.width;
-+              out_left_align = out_height_align;
-+              out_top_align = out_width_align;
-+              out_width_align = out_left_align;
-+              out_height_align = out_top_align;
-+              out_right = out->base.rect.height;
-+              out_bottom = out->base.rect.width;
-+      }
-+
-+      for (col = in->num_cols - 1; col > 0; col--) {
-+              bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
-+                                        !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              bool allow_out_overshoot = (col < in->num_cols - 1) &&
-+                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              unsigned int in_left;
-+              unsigned int out_left;
-+
-+              /*
-+               * Align input width to burst length if the scaling step flips
-+               * horizontally.
-+               */
-+
-+              find_best_seam(ctx, col,
-+                             in_right, out_right,
-+                             in_left_align, out_left_align,
-+                             allow_in_overshoot ? 1 : 8 /* burst length */,
-+                             allow_out_overshoot ? 1 : out_width_align,
-+                             ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
-+                             &in_left, &out_left);
-+
-+              if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
-+                      flipped_out_left = resized_width - out_right;
-+              else
-+                      flipped_out_left = out_left;
-+
-+              fill_tile_column(ctx, col, in, in_left, in_right - in_left,
-+                               out, flipped_out_left, out_right - out_left);
-+
-+              dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
-+                      in_left, in_right - in_left,
-+                      flipped_out_left, out_right - out_left);
-+
-+              in_right = in_left;
-+              out_right = out_left;
-+      }
-+
-+      flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
-+                         resized_width - out_right : 0;
-+
-+      fill_tile_column(ctx, 0, in, 0, in_right,
-+                       out, flipped_out_left, out_right);
-+
-+      dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
-+              in_right, flipped_out_left, out_right);
-+
-+      for (row = in->num_rows - 1; row > 0; row--) {
-+              bool allow_overshoot = row < in->num_rows - 1;
-+              unsigned int in_top;
-+              unsigned int out_top;
-+
-+              find_best_seam(ctx, row,
-+                             in_bottom, out_bottom,
-+                             in_top_align, out_top_align,
-+                             1, allow_overshoot ? 1 : out_height_align,
-+                             ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
-+                             &in_top, &out_top);
-+
-+              if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
-+                  ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      flipped_out_top = resized_height - out_bottom;
-+              else
-+                      flipped_out_top = out_top;
-+
-+              fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
-+                            out, flipped_out_top, out_bottom - out_top);
-+
-+              dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
-+                      in_top, in_bottom - in_top,
-+                      flipped_out_top, out_bottom - out_top);
-+
-+              in_bottom = in_top;
-+              out_bottom = out_top;
-+      }
-+
-+      if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
-+          ipu_rot_mode_is_irt(ctx->rot_mode))
-+              flipped_out_top = resized_height - out_bottom;
-+      else
-+              flipped_out_top = 0;
-+
-+      fill_tile_row(ctx, 0, in, 0, in_bottom,
-+                    out, flipped_out_top, out_bottom);
-+
-+      dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
-+              in_bottom, flipped_out_top, out_bottom);
-+}
-+
-+static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
-+                              struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      unsigned int max_width = 1024;
-+      unsigned int max_height = 1024;
-+      unsigned int i;
-+
-+      if (image->type == IMAGE_CONVERT_IN) {
-+              /* Up to 4096x4096 input tile size */
-+              max_width <<= ctx->downsize_coeff_h;
-+              max_height <<= ctx->downsize_coeff_v;
-+      }
-+
-+      for (i = 0; i < ctx->num_tiles; i++) {
-+              struct ipu_image_tile *tile;
-+              const unsigned int row = i / image->num_cols;
-+              const unsigned int col = i % image->num_cols;
-+
-+              if (image->type == IMAGE_CONVERT_OUT)
-+                      tile = &image->tile[ctx->out_tile_map[i]];
-+              else
-+                      tile = &image->tile[i];
-+
-+              tile->size = ((tile->height * image->fmt->bpp) >> 3) *
-+                      tile->width;
-+
-+              if (image->fmt->planar) {
-+                      tile->stride = tile->width;
-+                      tile->rot_stride = tile->height;
-+              } else {
-+                      tile->stride =
-+                              (image->fmt->bpp * tile->width) >> 3;
-+                      tile->rot_stride =
-+                              (image->fmt->bpp * tile->height) >> 3;
-+              }
-+
-+              dev_dbg(priv->ipu->dev,
-+                      "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
-+                      chan->ic_task, ctx,
-+                      image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
-+                      row, col,
-+                      tile->width, tile->height, tile->left, tile->top);
-+
-+              if (!tile->width || tile->width > max_width ||
-+                  !tile->height || tile->height > max_height) {
-+                      dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
-+                              image->type == IMAGE_CONVERT_IN ? "input" :
-+                              "output", tile->width, tile->height);
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Use the rotation transformation to find the tile coordinates
-+ * (row, col) of a tile in the destination frame that corresponds
-+ * to the given tile coordinates of a source frame. The destination
-+ * coordinate is then converted to a tile index.
-+ */
-+static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
-+                              int src_row, int src_col)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      int dst_row, dst_col;
-+
-+      /* with no rotation it's a 1:1 mapping */
-+      if (ctx->rot_mode == IPU_ROTATE_NONE)
-+              return src_row * s_image->num_cols + src_col;
-+
-+      /*
-+       * before doing the transform, first we have to translate
-+       * source row,col for an origin in the center of s_image
-+       */
-+      src_row = src_row * 2 - (s_image->num_rows - 1);
-+      src_col = src_col * 2 - (s_image->num_cols - 1);
-+
-+      /* do the rotation transform */
-+      if (ctx->rot_mode & IPU_ROT_BIT_90) {
-+              dst_col = -src_row;
-+              dst_row = src_col;
-+      } else {
-+              dst_col = src_col;
-+              dst_row = src_row;
-+      }
-+
-+      /* apply flip */
-+      if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
-+              dst_col = -dst_col;
-+      if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
-+              dst_row = -dst_row;
-+
-+      dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
-+              chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
-+
-+      /*
-+       * finally translate dest row,col using an origin in upper
-+       * left of d_image
-+       */
-+      dst_row += d_image->num_rows - 1;
-+      dst_col += d_image->num_cols - 1;
-+      dst_row /= 2;
-+      dst_col /= 2;
-+
-+      return dst_row * d_image->num_cols + dst_col;
-+}
-+
-+/*
-+ * Fill the out_tile_map[] with transformed destination tile indeces.
-+ */
-+static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      unsigned int row, col, tile = 0;
-+
-+      for (row = 0; row < s_image->num_rows; row++) {
-+              for (col = 0; col < s_image->num_cols; col++) {
-+                      ctx->out_tile_map[tile] =
-+                              transform_tile_index(ctx, row, col);
-+                      tile++;
-+              }
-+      }
-+}
-+
-+static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
-+                                  struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      const struct ipu_image_pixfmt *fmt = image->fmt;
-+      unsigned int row, col, tile = 0;
-+      u32 H, top, y_stride, uv_stride;
-+      u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
-+      u32 y_row_off, y_col_off, y_off;
-+      u32 y_size, uv_size;
-+
-+      /* setup some convenience vars */
-+      H = image->base.pix.height;
-+
-+      y_stride = image->stride;
-+      uv_stride = y_stride / fmt->uv_width_dec;
-+      if (fmt->uv_packed)
-+              uv_stride *= 2;
-+
-+      y_size = H * y_stride;
-+      uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
-+
-+      for (row = 0; row < image->num_rows; row++) {
-+              top = image->tile[tile].top;
-+              y_row_off = top * y_stride;
-+              uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
-+
-+              for (col = 0; col < image->num_cols; col++) {
-+                      y_col_off = image->tile[tile].left;
-+                      uv_col_off = y_col_off / fmt->uv_width_dec;
-+                      if (fmt->uv_packed)
-+                              uv_col_off *= 2;
-+
-+                      y_off = y_row_off + y_col_off;
-+                      uv_off = uv_row_off + uv_col_off;
-+
-+                      u_off = y_size - y_off + uv_off;
-+                      v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
-+                      if (fmt->uv_swapped) {
-+                              tmp = u_off;
-+                              u_off = v_off;
-+                              v_off = tmp;
-+                      }
-+
-+                      image->tile[tile].offset = y_off;
-+                      image->tile[tile].u_off = u_off;
-+                      image->tile[tile++].v_off = v_off;
-+
-+                      if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
-+                              dev_err(priv->ipu->dev,
-+                                      "task %u: ctx %p: %s@[%d,%d]: "
-+                                      "y_off %08x, u_off %08x, v_off %08x\n",
-+                                      chan->ic_task, ctx,
-+                                      image->type == IMAGE_CONVERT_IN ?
-+                                      "Input" : "Output", row, col,
-+                                      y_off, u_off, v_off);
-+                              return -EINVAL;
-+                      }
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
-+                                  struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      const struct ipu_image_pixfmt *fmt = image->fmt;
-+      unsigned int row, col, tile = 0;
-+      u32 bpp, stride, offset;
-+      u32 row_off, col_off;
-+
-+      /* setup some convenience vars */
-+      stride = image->stride;
-+      bpp = fmt->bpp;
-+
-+      for (row = 0; row < image->num_rows; row++) {
-+              row_off = image->tile[tile].top * stride;
-+
-+              for (col = 0; col < image->num_cols; col++) {
-+                      col_off = (image->tile[tile].left * bpp) >> 3;
-+
-+                      offset = row_off + col_off;
-+
-+                      image->tile[tile].offset = offset;
-+                      image->tile[tile].u_off = 0;
-+                      image->tile[tile++].v_off = 0;
-+
-+                      if (offset & 0x7) {
-+                              dev_err(priv->ipu->dev,
-+                                      "task %u: ctx %p: %s@[%d,%d]: "
-+                                      "phys %08x\n",
-+                                      chan->ic_task, ctx,
-+                                      image->type == IMAGE_CONVERT_IN ?
-+                                      "Input" : "Output", row, col,
-+                                      row_off + col_off);
-+                              return -EINVAL;
-+                      }
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
-+                            struct ipu_image_convert_image *image)
-+{
-+      if (image->fmt->planar)
-+              return calc_tile_offsets_planar(ctx, image);
-+
-+      return calc_tile_offsets_packed(ctx, image);
-+}
-+
-+/*
-+ * Calculate the resizing ratio for the IC main processing section given input
-+ * size, fixed downsizing coefficient, and output size.
-+ * Either round to closest for the next tile's first pixel to minimize seams
-+ * and distortion (for all but right column / bottom row), or round down to
-+ * avoid sampling beyond the edges of the input image for this tile's last
-+ * pixel.
-+ * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
-+ */
-+static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
-+                           u32 output_size, bool allow_overshoot)
-+{
-+      u32 downsized = input_size >> downsize_coeff;
-+
-+      if (allow_overshoot)
-+              return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
-+      else
-+              return 8192 * (downsized - 1) / (output_size - 1);
-+}
-+
-+/*
-+ * Slightly modify resize coefficients per tile to hide the bilinear
-+ * interpolator reset at tile borders, shifting the right / bottom edge
-+ * by up to a half input pixel. This removes noticeable seams between
-+ * tiles at higher upscaling factors.
-+ */
-+static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+      unsigned int col, row, tile_idx;
-+      unsigned int last_output;
-+
-+      for (col = 0; col < ctx->in.num_cols; col++) {
-+              bool closest = (col < ctx->in.num_cols - 1) &&
-+                             !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              u32 resized_width;
-+              u32 resize_coeff_h;
-+              u32 in_width;
-+
-+              tile_idx = col;
-+              in_tile = &ctx->in.tile[tile_idx];
-+              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      resized_width = out_tile->height;
-+              else
-+                      resized_width = out_tile->width;
-+
-+              resize_coeff_h = calc_resize_coeff(in_tile->width,
-+                                                 ctx->downsize_coeff_h,
-+                                                 resized_width, closest);
-+
-+              dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
-+                      __func__, col, resize_coeff_h);
-+
-+              /*
-+               * With the horizontal scaling factor known, round up resized
-+               * width (output width or height) to burst size.
-+               */
-+              resized_width = round_up(resized_width, 8);
-+
-+              /*
-+               * Calculate input width from the last accessed input pixel
-+               * given resized width and scaling coefficients. Round up to
-+               * burst size.
-+               */
-+              last_output = resized_width - 1;
-+              if (closest && ((last_output * resize_coeff_h) % 8192))
-+                      last_output++;
-+              in_width = round_up(
-+                      (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
-+                      << ctx->downsize_coeff_h, 8);
-+
-+              for (row = 0; row < ctx->in.num_rows; row++) {
-+                      tile_idx = row * ctx->in.num_cols + col;
-+                      in_tile = &ctx->in.tile[tile_idx];
-+                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                              out_tile->height = resized_width;
-+                      else
-+                              out_tile->width = resized_width;
-+
-+                      in_tile->width = in_width;
-+              }
-+
-+              ctx->resize_coeffs_h[col] = resize_coeff_h;
-+      }
-+
-+      for (row = 0; row < ctx->in.num_rows; row++) {
-+              bool closest = (row < ctx->in.num_rows - 1) &&
-+                             !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
-+              u32 resized_height;
-+              u32 resize_coeff_v;
-+              u32 in_height;
-+
-+              tile_idx = row * ctx->in.num_cols;
-+              in_tile = &ctx->in.tile[tile_idx];
-+              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      resized_height = out_tile->width;
-+              else
-+                      resized_height = out_tile->height;
-+
-+              resize_coeff_v = calc_resize_coeff(in_tile->height,
-+                                                 ctx->downsize_coeff_v,
-+                                                 resized_height, closest);
-+
-+              dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
-+                      __func__, row, resize_coeff_v);
-+
-+              /*
-+               * With the vertical scaling factor known, round up resized
-+               * height (output width or height) to IDMAC limitations.
-+               */
-+              resized_height = round_up(resized_height, 2);
-+
-+              /*
-+               * Calculate input width from the last accessed input pixel
-+               * given resized height and scaling coefficients. Align to
-+               * IDMAC restrictions.
-+               */
-+              last_output = resized_height - 1;
-+              if (closest && ((last_output * resize_coeff_v) % 8192))
-+                      last_output++;
-+              in_height = round_up(
-+                      (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
-+                      << ctx->downsize_coeff_v, 2);
-+
-+              for (col = 0; col < ctx->in.num_cols; col++) {
-+                      tile_idx = row * ctx->in.num_cols + col;
-+                      in_tile = &ctx->in.tile[tile_idx];
-+                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                              out_tile->width = resized_height;
-+                      else
-+                              out_tile->height = resized_height;
-+
-+                      in_tile->height = in_height;
-+              }
-+
-+              ctx->resize_coeffs_v[row] = resize_coeff_v;
-+      }
-+}
-+
-+/*
-+ * return the number of runs in given queue (pending_q or done_q)
-+ * for this context. hold irqlock when calling.
-+ */
-+static int get_run_count(struct ipu_image_convert_ctx *ctx,
-+                       struct list_head *q)
-+{
-+      struct ipu_image_convert_run *run;
-+      int count = 0;
-+
-+      lockdep_assert_held(&ctx->chan->irqlock);
-+
-+      list_for_each_entry(run, q, list) {
-+              if (run->ctx == ctx)
-+                      count++;
-+      }
-+
-+      return count;
-+}
-+
-+static void convert_stop(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
-+              __func__, chan->ic_task, ctx, run);
-+
-+      /* disable IC tasks and the channels */
-+      ipu_ic_task_disable(chan->ic);
-+      ipu_idmac_disable_channel(chan->in_chan);
-+      ipu_idmac_disable_channel(chan->out_chan);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_idmac_disable_channel(chan->rotation_in_chan);
-+              ipu_idmac_disable_channel(chan->rotation_out_chan);
-+              ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
-+      }
-+
-+      ipu_ic_disable(chan->ic);
-+}
-+
-+static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
-+                             struct ipuv3_channel *channel,
-+                             struct ipu_image_convert_image *image,
-+                             enum ipu_rotate_mode rot_mode,
-+                             bool rot_swap_width_height,
-+                             unsigned int tile)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      unsigned int burst_size;
-+      u32 width, height, stride;
-+      dma_addr_t addr0, addr1 = 0;
-+      struct ipu_image tile_image;
-+      unsigned int tile_idx[2];
-+
-+      if (image->type == IMAGE_CONVERT_OUT) {
-+              tile_idx[0] = ctx->out_tile_map[tile];
-+              tile_idx[1] = ctx->out_tile_map[1];
-+      } else {
-+              tile_idx[0] = tile;
-+              tile_idx[1] = 1;
-+      }
-+
-+      if (rot_swap_width_height) {
-+              width = image->tile[tile_idx[0]].height;
-+              height = image->tile[tile_idx[0]].width;
-+              stride = image->tile[tile_idx[0]].rot_stride;
-+              addr0 = ctx->rot_intermediate[0].phys;
-+              if (ctx->double_buffering)
-+                      addr1 = ctx->rot_intermediate[1].phys;
-+      } else {
-+              width = image->tile[tile_idx[0]].width;
-+              height = image->tile[tile_idx[0]].height;
-+              stride = image->stride;
-+              addr0 = image->base.phys0 +
-+                      image->tile[tile_idx[0]].offset;
-+              if (ctx->double_buffering)
-+                      addr1 = image->base.phys0 +
-+                              image->tile[tile_idx[1]].offset;
-+      }
-+
-+      ipu_cpmem_zero(channel);
-+
-+      memset(&tile_image, 0, sizeof(tile_image));
-+      tile_image.pix.width = tile_image.rect.width = width;
-+      tile_image.pix.height = tile_image.rect.height = height;
-+      tile_image.pix.bytesperline = stride;
-+      tile_image.pix.pixelformat =  image->fmt->fourcc;
-+      tile_image.phys0 = addr0;
-+      tile_image.phys1 = addr1;
-+      if (image->fmt->planar && !rot_swap_width_height) {
-+              tile_image.u_offset = image->tile[tile_idx[0]].u_off;
-+              tile_image.v_offset = image->tile[tile_idx[0]].v_off;
-+      }
-+
-+      ipu_cpmem_set_image(channel, &tile_image);
-+
-+      if (rot_mode)
-+              ipu_cpmem_set_rotation(channel, rot_mode);
-+
-+      /*
-+       * Skip writing U and V components to odd rows in the output
-+       * channels for planar 4:2:0.
-+       */
-+      if ((channel == chan->out_chan ||
-+           channel == chan->rotation_out_chan) &&
-+          image->fmt->planar && image->fmt->uv_height_dec == 2)
-+              ipu_cpmem_skip_odd_chroma_rows(channel);
-+
-+      if (channel == chan->rotation_in_chan ||
-+          channel == chan->rotation_out_chan) {
-+              burst_size = 8;
-+              ipu_cpmem_set_block_mode(channel);
-+      } else
-+              burst_size = (width % 16) ? 8 : 16;
-+
-+      ipu_cpmem_set_burstsize(channel, burst_size);
-+
-+      ipu_ic_task_idma_init(chan->ic, channel, width, height,
-+                            burst_size, rot_mode);
-+
-+      /*
-+       * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
-+       * only do this when there is no PRG present.
-+       */
-+      if (!channel->ipu->prg_priv)
-+              ipu_cpmem_set_axi_id(channel, 1);
-+
-+      ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
-+}
-+
-+static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      unsigned int dst_tile = ctx->out_tile_map[tile];
-+      unsigned int dest_width, dest_height;
-+      unsigned int col, row;
-+      u32 rsc;
-+      int ret;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
-+              __func__, chan->ic_task, ctx, run, tile, dst_tile);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* swap width/height for resizer */
-+              dest_width = d_image->tile[dst_tile].height;
-+              dest_height = d_image->tile[dst_tile].width;
-+      } else {
-+              dest_width = d_image->tile[dst_tile].width;
-+              dest_height = d_image->tile[dst_tile].height;
-+      }
-+
-+      row = tile / s_image->num_cols;
-+      col = tile % s_image->num_cols;
-+
-+      rsc =  (ctx->downsize_coeff_v << 30) |
-+             (ctx->resize_coeffs_v[row] << 16) |
-+             (ctx->downsize_coeff_h << 14) |
-+             (ctx->resize_coeffs_h[col]);
-+
-+      dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
-+              __func__, s_image->tile[tile].width,
-+              s_image->tile[tile].height, dest_width, dest_height, rsc);
-+
-+      /* setup the IC resizer and CSC */
-+      ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
-+                                 s_image->tile[tile].width,
-+                                 s_image->tile[tile].height,
-+                                 dest_width,
-+                                 dest_height,
-+                                 rsc);
-+      if (ret) {
-+              dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* init the source MEM-->IC PP IDMAC channel */
-+      init_idmac_channel(ctx, chan->in_chan, s_image,
-+                         IPU_ROTATE_NONE, false, tile);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* init the IC PP-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->out_chan, d_image,
-+                                 IPU_ROTATE_NONE, true, tile);
-+
-+              /* init the MEM-->IC PP ROT IDMAC channel */
-+              init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
-+                                 ctx->rot_mode, true, tile);
-+
-+              /* init the destination IC PP ROT-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
-+                                 IPU_ROTATE_NONE, false, tile);
-+
-+              /* now link IC PP-->MEM to MEM-->IC PP ROT */
-+              ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
-+      } else {
-+              /* init the destination IC PP-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->out_chan, d_image,
-+                                 ctx->rot_mode, false, tile);
-+      }
-+
-+      /* enable the IC */
-+      ipu_ic_enable(chan->ic);
-+
-+      /* set buffers ready */
-+      ipu_idmac_select_buffer(chan->in_chan, 0);
-+      ipu_idmac_select_buffer(chan->out_chan, 0);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+              ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
-+      if (ctx->double_buffering) {
-+              ipu_idmac_select_buffer(chan->in_chan, 1);
-+              ipu_idmac_select_buffer(chan->out_chan, 1);
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
-+      }
-+
-+      /* enable the channels! */
-+      ipu_idmac_enable_channel(chan->in_chan);
-+      ipu_idmac_enable_channel(chan->out_chan);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_idmac_enable_channel(chan->rotation_in_chan);
-+              ipu_idmac_enable_channel(chan->rotation_out_chan);
-+      }
-+
-+      ipu_ic_task_enable(chan->ic);
-+
-+      ipu_cpmem_dump(chan->in_chan);
-+      ipu_cpmem_dump(chan->out_chan);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_cpmem_dump(chan->rotation_in_chan);
-+              ipu_cpmem_dump(chan->rotation_out_chan);
-+      }
-+
-+      ipu_dump(priv->ipu);
-+
-+      return 0;
-+}
-+
-+/* hold irqlock when calling */
-+static int do_run(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      ctx->in.base.phys0 = run->in_phys;
-+      ctx->out.base.phys0 = run->out_phys;
-+
-+      ctx->cur_buf_num = 0;
-+      ctx->next_tile = 1;
-+
-+      /* remove run from pending_q and set as current */
-+      list_del(&run->list);
-+      chan->current_run = run;
-+
-+      return convert_start(run, 0);
-+}
-+
-+/* hold irqlock when calling */
-+static void run_next(struct ipu_image_convert_chan *chan)
-+{
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run, *tmp;
-+      int ret;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
-+              /* skip contexts that are aborting */
-+              if (run->ctx->aborting) {
-+                      dev_dbg(priv->ipu->dev,
-+                              "%s: task %u: skipping aborting ctx %p run %p\n",
-+                              __func__, chan->ic_task, run->ctx, run);
-+                      continue;
-+              }
-+
-+              ret = do_run(run);
-+              if (!ret)
-+                      break;
-+
-+              /*
-+               * something went wrong with start, add the run
-+               * to done q and continue to the next run in the
-+               * pending q.
-+               */
-+              run->status = ret;
-+              list_add_tail(&run->list, &chan->done_q);
-+              chan->current_run = NULL;
-+      }
-+}
-+
-+static void empty_done_q(struct ipu_image_convert_chan *chan)
-+{
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      while (!list_empty(&chan->done_q)) {
-+              run = list_entry(chan->done_q.next,
-+                               struct ipu_image_convert_run,
-+                               list);
-+
-+              list_del(&run->list);
-+
-+              dev_dbg(priv->ipu->dev,
-+                      "%s: task %u: completing ctx %p run %p with %d\n",
-+                      __func__, chan->ic_task, run->ctx, run, run->status);
-+
-+              /* call the completion callback and free the run */
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              run->ctx->complete(run, run->ctx->complete_context);
-+              spin_lock_irqsave(&chan->irqlock, flags);
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+}
-+
-+/*
-+ * the bottom half thread clears out the done_q, calling the
-+ * completion handler for each.
-+ */
-+static irqreturn_t do_bh(int irq, void *dev_id)
-+{
-+      struct ipu_image_convert_chan *chan = dev_id;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
-+              chan->ic_task);
-+
-+      empty_done_q(chan);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /*
-+       * the done_q is cleared out, signal any contexts
-+       * that are aborting that abort can complete.
-+       */
-+      list_for_each_entry(ctx, &chan->ctx_list, list) {
-+              if (ctx->aborting) {
-+                      dev_dbg(priv->ipu->dev,
-+                              "%s: task %u: signaling abort for ctx %p\n",
-+                              __func__, chan->ic_task, ctx);
-+                      complete_all(&ctx->aborted);
-+              }
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
-+              chan->ic_task);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
-+{
-+      unsigned int cur_tile = ctx->next_tile - 1;
-+      unsigned int next_tile = ctx->next_tile;
-+
-+      if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
-+          ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
-+          ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
-+          ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
-+          ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
-+          ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
-+          ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
-+          ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
-+              return true;
-+
-+      return false;
-+}
-+
-+/* hold irqlock when calling */
-+static irqreturn_t do_irq(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_tile *src_tile, *dst_tile;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      struct ipuv3_channel *outch;
-+      unsigned int dst_idx;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
-+              chan->rotation_out_chan : chan->out_chan;
-+
-+      /*
-+       * It is difficult to stop the channel DMA before the channels
-+       * enter the paused state. Without double-buffering the channels
-+       * are always in a paused state when the EOF irq occurs, so it
-+       * is safe to stop the channels now. For double-buffering we
-+       * just ignore the abort until the operation completes, when it
-+       * is safe to shut down.
-+       */
-+      if (ctx->aborting && !ctx->double_buffering) {
-+              convert_stop(run);
-+              run->status = -EIO;
-+              goto done;
-+      }
-+
-+      if (ctx->next_tile == ctx->num_tiles) {
-+              /*
-+               * the conversion is complete
-+               */
-+              convert_stop(run);
-+              run->status = 0;
-+              goto done;
-+      }
-+
-+      /*
-+       * not done, place the next tile buffers.
-+       */
-+      if (!ctx->double_buffering) {
-+              if (ic_settings_changed(ctx)) {
-+                      convert_stop(run);
-+                      convert_start(run, ctx->next_tile);
-+              } else {
-+                      src_tile = &s_image->tile[ctx->next_tile];
-+                      dst_idx = ctx->out_tile_map[ctx->next_tile];
-+                      dst_tile = &d_image->tile[dst_idx];
-+
-+                      ipu_cpmem_set_buffer(chan->in_chan, 0,
-+                                           s_image->base.phys0 +
-+                                           src_tile->offset);
-+                      ipu_cpmem_set_buffer(outch, 0,
-+                                           d_image->base.phys0 +
-+                                           dst_tile->offset);
-+                      if (s_image->fmt->planar)
-+                              ipu_cpmem_set_uv_offset(chan->in_chan,
-+                                                      src_tile->u_off,
-+                                                      src_tile->v_off);
-+                      if (d_image->fmt->planar)
-+                              ipu_cpmem_set_uv_offset(outch,
-+                                                      dst_tile->u_off,
-+                                                      dst_tile->v_off);
-+
-+                      ipu_idmac_select_buffer(chan->in_chan, 0);
-+                      ipu_idmac_select_buffer(outch, 0);
-+              }
-+      } else if (ctx->next_tile < ctx->num_tiles - 1) {
-+
-+              src_tile = &s_image->tile[ctx->next_tile + 1];
-+              dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
-+              dst_tile = &d_image->tile[dst_idx];
-+
-+              ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
-+                                   s_image->base.phys0 + src_tile->offset);
-+              ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
-+                                   d_image->base.phys0 + dst_tile->offset);
-+
-+              ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
-+              ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
-+
-+              ctx->cur_buf_num ^= 1;
-+      }
-+
-+      ctx->next_tile++;
-+      return IRQ_HANDLED;
-+done:
-+      list_add_tail(&run->list, &chan->done_q);
-+      chan->current_run = NULL;
-+      run_next(chan);
-+      return IRQ_WAKE_THREAD;
-+}
-+
-+static irqreturn_t norotate_irq(int irq, void *data)
-+{
-+      struct ipu_image_convert_chan *chan = data;
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+      irqreturn_t ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* get current run and its context */
-+      run = chan->current_run;
-+      if (!run) {
-+              ret = IRQ_NONE;
-+              goto out;
-+      }
-+
-+      ctx = run->ctx;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* this is a rotation operation, just ignore */
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              return IRQ_HANDLED;
-+      }
-+
-+      ret = do_irq(run);
-+out:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+
-+static irqreturn_t rotate_irq(int irq, void *data)
-+{
-+      struct ipu_image_convert_chan *chan = data;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+      irqreturn_t ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* get current run and its context */
-+      run = chan->current_run;
-+      if (!run) {
-+              ret = IRQ_NONE;
-+              goto out;
-+      }
-+
-+      ctx = run->ctx;
-+
-+      if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* this was NOT a rotation operation, shouldn't happen */
-+              dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              return IRQ_HANDLED;
-+      }
-+
-+      ret = do_irq(run);
-+out:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+
-+/*
-+ * try to force the completion of runs for this ctx. Called when
-+ * abort wait times out in ipu_image_convert_abort().
-+ */
-+static void force_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      run = chan->current_run;
-+      if (run && run->ctx == ctx) {
-+              convert_stop(run);
-+              run->status = -EIO;
-+              list_add_tail(&run->list, &chan->done_q);
-+              chan->current_run = NULL;
-+              run_next(chan);
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      empty_done_q(chan);
-+}
-+
-+static void release_ipu_resources(struct ipu_image_convert_chan *chan)
-+{
-+      if (chan->out_eof_irq >= 0)
-+              free_irq(chan->out_eof_irq, chan);
-+      if (chan->rot_out_eof_irq >= 0)
-+              free_irq(chan->rot_out_eof_irq, chan);
-+
-+      if (!IS_ERR_OR_NULL(chan->in_chan))
-+              ipu_idmac_put(chan->in_chan);
-+      if (!IS_ERR_OR_NULL(chan->out_chan))
-+              ipu_idmac_put(chan->out_chan);
-+      if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
-+              ipu_idmac_put(chan->rotation_in_chan);
-+      if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
-+              ipu_idmac_put(chan->rotation_out_chan);
-+      if (!IS_ERR_OR_NULL(chan->ic))
-+              ipu_ic_put(chan->ic);
-+
-+      chan->in_chan = chan->out_chan = chan->rotation_in_chan =
-+              chan->rotation_out_chan = NULL;
-+      chan->out_eof_irq = chan->rot_out_eof_irq = -1;
-+}
-+
-+static int get_ipu_resources(struct ipu_image_convert_chan *chan)
-+{
-+      const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      int ret;
-+
-+      /* get IC */
-+      chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
-+      if (IS_ERR(chan->ic)) {
-+              dev_err(priv->ipu->dev, "could not acquire IC\n");
-+              ret = PTR_ERR(chan->ic);
-+              goto err;
-+      }
-+
-+      /* get IDMAC channels */
-+      chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
-+      chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
-+      if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
-+              dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
-+              ret = -EBUSY;
-+              goto err;
-+      }
-+
-+      chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
-+      chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
-+      if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
-+              dev_err(priv->ipu->dev,
-+                      "could not acquire idmac rotation channels\n");
-+              ret = -EBUSY;
-+              goto err;
-+      }
-+
-+      /* acquire the EOF interrupts */
-+      chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-+                                                chan->out_chan,
-+                                                IPU_IRQ_EOF);
-+
-+      ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
-+                                 0, "ipu-ic", chan);
-+      if (ret < 0) {
-+              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-+                       chan->out_eof_irq);
-+              chan->out_eof_irq = -1;
-+              goto err;
-+      }
-+
-+      chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-+                                                   chan->rotation_out_chan,
-+                                                   IPU_IRQ_EOF);
-+
-+      ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
-+                                 0, "ipu-ic", chan);
-+      if (ret < 0) {
-+              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-+                      chan->rot_out_eof_irq);
-+              chan->rot_out_eof_irq = -1;
-+              goto err;
-+      }
-+
-+      return 0;
-+err:
-+      release_ipu_resources(chan);
-+      return ret;
-+}
-+
-+static int fill_image(struct ipu_image_convert_ctx *ctx,
-+                    struct ipu_image_convert_image *ic_image,
-+                    struct ipu_image *image,
-+                    enum ipu_image_convert_type type)
-+{
-+      struct ipu_image_convert_priv *priv = ctx->chan->priv;
-+
-+      ic_image->base = *image;
-+      ic_image->type = type;
-+
-+      ic_image->fmt = get_format(image->pix.pixelformat);
-+      if (!ic_image->fmt) {
-+              dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
-+                      type == IMAGE_CONVERT_OUT ? "Output" : "Input");
-+              return -EINVAL;
-+      }
-+
-+      if (ic_image->fmt->planar)
-+              ic_image->stride = ic_image->base.pix.width;
-+      else
-+              ic_image->stride  = ic_image->base.pix.bytesperline;
-+
-+      return 0;
-+}
-+
-+/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
-+static unsigned int clamp_align(unsigned int x, unsigned int min,
-+                              unsigned int max, unsigned int align)
-+{
-+      /* Bits that must be zero to be aligned */
-+      unsigned int mask = ~((1 << align) - 1);
-+
-+      /* Clamp to aligned min and max */
-+      x = clamp(x, (min + ~mask) & mask, max & mask);
-+
-+      /* Round to nearest aligned value */
-+      if (align)
-+              x = (x + (1 << (align - 1))) & mask;
-+
-+      return x;
-+}
-+
-+/* Adjusts input/output images to IPU restrictions */
-+void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
-+                            enum ipu_rotate_mode rot_mode)
-+{
-+      const struct ipu_image_pixfmt *infmt, *outfmt;
-+      u32 w_align_out, h_align_out;
-+      u32 w_align_in, h_align_in;
-+
-+      infmt = get_format(in->pix.pixelformat);
-+      outfmt = get_format(out->pix.pixelformat);
-+
-+      /* set some default pixel formats if needed */
-+      if (!infmt) {
-+              in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
-+              infmt = get_format(V4L2_PIX_FMT_RGB24);
-+      }
-+      if (!outfmt) {
-+              out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
-+              outfmt = get_format(V4L2_PIX_FMT_RGB24);
-+      }
-+
-+      /* image converter does not handle fields */
-+      in->pix.field = out->pix.field = V4L2_FIELD_NONE;
-+
-+      /* resizer cannot downsize more than 4:1 */
-+      if (ipu_rot_mode_is_irt(rot_mode)) {
-+              out->pix.height = max_t(__u32, out->pix.height,
-+                                      in->pix.width / 4);
-+              out->pix.width = max_t(__u32, out->pix.width,
-+                                     in->pix.height / 4);
-+      } else {
-+              out->pix.width = max_t(__u32, out->pix.width,
-+                                     in->pix.width / 4);
-+              out->pix.height = max_t(__u32, out->pix.height,
-+                                      in->pix.height / 4);
-+      }
-+
-+      /* align input width/height */
-+      w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
-+                                          rot_mode));
-+      h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
-+                                           rot_mode));
-+      in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
-+                                  w_align_in);
-+      in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
-+                                   h_align_in);
-+
-+      /* align output width/height */
-+      w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
-+                                           rot_mode));
-+      h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
-+                                            rot_mode));
-+      out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
-+                                   w_align_out);
-+      out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
-+                                    h_align_out);
-+
-+      /* set input/output strides and image sizes */
-+      in->pix.bytesperline = infmt->planar ?
-+              clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
-+                          w_align_in) :
-+              clamp_align((in->pix.width * infmt->bpp) >> 3,
-+                          ((2 << w_align_in) * infmt->bpp) >> 3,
-+                          (MAX_W * infmt->bpp) >> 3,
-+                          w_align_in);
-+      in->pix.sizeimage = infmt->planar ?
-+              (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
-+              in->pix.height * in->pix.bytesperline;
-+      out->pix.bytesperline = outfmt->planar ? out->pix.width :
-+              (out->pix.width * outfmt->bpp) >> 3;
-+      out->pix.sizeimage = outfmt->planar ?
-+              (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
-+              out->pix.height * out->pix.bytesperline;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
-+
-+/*
-+ * this is used by ipu_image_convert_prepare() to verify set input and
-+ * output images are valid before starting the conversion. Clients can
-+ * also call it before calling ipu_image_convert_prepare().
-+ */
-+int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
-+                           enum ipu_rotate_mode rot_mode)
-+{
-+      struct ipu_image testin, testout;
-+
-+      testin = *in;
-+      testout = *out;
-+
-+      ipu_image_convert_adjust(&testin, &testout, rot_mode);
-+
-+      if (testin.pix.width != in->pix.width ||
-+          testin.pix.height != in->pix.height ||
-+          testout.pix.width != out->pix.width ||
-+          testout.pix.height != out->pix.height)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
-+
-+/*
-+ * Call ipu_image_convert_prepare() to prepare for the conversion of
-+ * given images and rotation mode. Returns a new conversion context.
-+ */
-+struct ipu_image_convert_ctx *
-+ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                        struct ipu_image *in, struct ipu_image *out,
-+                        enum ipu_rotate_mode rot_mode,
-+                        ipu_image_convert_cb_t complete,
-+                        void *complete_context)
-+{
-+      struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
-+      struct ipu_image_convert_image *s_image, *d_image;
-+      struct ipu_image_convert_chan *chan;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+      unsigned int i;
-+      bool get_res;
-+      int ret;
-+
-+      if (!in || !out || !complete ||
-+          (ic_task != IC_TASK_VIEWFINDER &&
-+           ic_task != IC_TASK_POST_PROCESSOR))
-+              return ERR_PTR(-EINVAL);
-+
-+      /* verify the in/out images before continuing */
-+      ret = ipu_image_convert_verify(in, out, rot_mode);
-+      if (ret) {
-+              dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
-+                      __func__);
-+              return ERR_PTR(ret);
-+      }
-+
-+      chan = &priv->chan[ic_task];
-+
-+      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+      if (!ctx)
-+              return ERR_PTR(-ENOMEM);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
-+              chan->ic_task, ctx);
-+
-+      ctx->chan = chan;
-+      init_completion(&ctx->aborted);
-+
-+      ctx->rot_mode = rot_mode;
-+
-+      /* Sets ctx->in.num_rows/cols as well */
-+      ret = calc_image_resize_coefficients(ctx, in, out);
-+      if (ret)
-+              goto out_free;
-+
-+      s_image = &ctx->in;
-+      d_image = &ctx->out;
-+
-+      /* set tiling and rotation */
-+      if (ipu_rot_mode_is_irt(rot_mode)) {
-+              d_image->num_rows = s_image->num_cols;
-+              d_image->num_cols = s_image->num_rows;
-+      } else {
-+              d_image->num_rows = s_image->num_rows;
-+              d_image->num_cols = s_image->num_cols;
-+      }
-+
-+      ctx->num_tiles = d_image->num_cols * d_image->num_rows;
-+
-+      ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
-+      if (ret)
-+              goto out_free;
-+      ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_out_tile_map(ctx);
-+
-+      find_seams(ctx, s_image, d_image);
-+
-+      ret = calc_tile_dimensions(ctx, s_image);
-+      if (ret)
-+              goto out_free;
-+
-+      ret = calc_tile_offsets(ctx, s_image);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_tile_dimensions(ctx, d_image);
-+      ret = calc_tile_offsets(ctx, d_image);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_tile_resize_coefficients(ctx);
-+
-+      ret = ipu_ic_calc_csc(&ctx->csc,
-+                      s_image->base.pix.ycbcr_enc,
-+                      s_image->base.pix.quantization,
-+                      ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
-+                      d_image->base.pix.ycbcr_enc,
-+                      d_image->base.pix.quantization,
-+                      ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
-+      if (ret)
-+              goto out_free;
-+
-+      dump_format(ctx, s_image);
-+      dump_format(ctx, d_image);
-+
-+      ctx->complete = complete;
-+      ctx->complete_context = complete_context;
-+
-+      /*
-+       * Can we use double-buffering for this operation? If there is
-+       * only one tile (the whole image can be converted in a single
-+       * operation) there's no point in using double-buffering. Also,
-+       * the IPU's IDMAC channels allow only a single U and V plane
-+       * offset shared between both buffers, but these offsets change
-+       * for every tile, and therefore would have to be updated for
-+       * each buffer which is not possible. So double-buffering is
-+       * impossible when either the source or destination images are
-+       * a planar format (YUV420, YUV422P, etc.). Further, differently
-+       * sized tiles or different resizing coefficients per tile
-+       * prevent double-buffering as well.
-+       */
-+      ctx->double_buffering = (ctx->num_tiles > 1 &&
-+                               !s_image->fmt->planar &&
-+                               !d_image->fmt->planar);
-+      for (i = 1; i < ctx->num_tiles; i++) {
-+              if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
-+                  ctx->in.tile[i].height != ctx->in.tile[0].height ||
-+                  ctx->out.tile[i].width != ctx->out.tile[0].width ||
-+                  ctx->out.tile[i].height != ctx->out.tile[0].height) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+      for (i = 1; i < ctx->in.num_cols; i++) {
-+              if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+      for (i = 1; i < ctx->in.num_rows; i++) {
-+              if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              unsigned long intermediate_size = d_image->tile[0].size;
-+
-+              for (i = 1; i < ctx->num_tiles; i++) {
-+                      if (d_image->tile[i].size > intermediate_size)
-+                              intermediate_size = d_image->tile[i].size;
-+              }
-+
-+              ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
-+                                  intermediate_size);
-+              if (ret)
-+                      goto out_free;
-+              if (ctx->double_buffering) {
-+                      ret = alloc_dma_buf(priv,
-+                                          &ctx->rot_intermediate[1],
-+                                          intermediate_size);
-+                      if (ret)
-+                              goto out_free_dmabuf0;
-+              }
-+      }
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      get_res = list_empty(&chan->ctx_list);
-+
-+      list_add_tail(&ctx->list, &chan->ctx_list);
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (get_res) {
-+              ret = get_ipu_resources(chan);
-+              if (ret)
-+                      goto out_free_dmabuf1;
-+      }
-+
-+      return ctx;
-+
-+out_free_dmabuf1:
-+      free_dma_buf(priv, &ctx->rot_intermediate[1]);
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+      list_del(&ctx->list);
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+out_free_dmabuf0:
-+      free_dma_buf(priv, &ctx->rot_intermediate[0]);
-+out_free:
-+      kfree(ctx);
-+      return ERR_PTR(ret);
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
-+
-+/*
-+ * Carry out a single image conversion run. Only the physaddr's of the input
-+ * and output image buffers are needed. The conversion context must have
-+ * been created previously with ipu_image_convert_prepare().
-+ */
-+int ipu_image_convert_queue(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_chan *chan;
-+      struct ipu_image_convert_priv *priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if (!run || !run->ctx || !run->in_phys || !run->out_phys)
-+              return -EINVAL;
-+
-+      ctx = run->ctx;
-+      chan = ctx->chan;
-+      priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
-+              chan->ic_task, ctx, run);
-+
-+      INIT_LIST_HEAD(&run->list);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      if (ctx->aborting) {
-+              ret = -EIO;
-+              goto unlock;
-+      }
-+
-+      list_add_tail(&run->list, &chan->pending_q);
-+
-+      if (!chan->current_run) {
-+              ret = do_run(run);
-+              if (ret)
-+                      chan->current_run = NULL;
-+      }
-+unlock:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
-+
-+/* Abort any active or pending conversions for this context */
-+static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run, *active_run, *tmp;
-+      unsigned long flags;
-+      int run_count, ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* move all remaining pending runs in this context to done_q */
-+      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
-+              if (run->ctx != ctx)
-+                      continue;
-+              run->status = -EIO;
-+              list_move_tail(&run->list, &chan->done_q);
-+      }
-+
-+      run_count = get_run_count(ctx, &chan->done_q);
-+      active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
-+              chan->current_run : NULL;
-+
-+      if (active_run)
-+              reinit_completion(&ctx->aborted);
-+
-+      ctx->aborting = true;
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (!run_count && !active_run) {
-+              dev_dbg(priv->ipu->dev,
-+                      "%s: task %u: no abort needed for ctx %p\n",
-+                      __func__, chan->ic_task, ctx);
-+              return;
-+      }
-+
-+      if (!active_run) {
-+              empty_done_q(chan);
-+              return;
-+      }
-+
-+      dev_dbg(priv->ipu->dev,
-+              "%s: task %u: wait for completion: %d runs\n",
-+              __func__, chan->ic_task, run_count);
-+
-+      ret = wait_for_completion_timeout(&ctx->aborted,
-+                                        msecs_to_jiffies(10000));
-+      if (ret == 0) {
-+              dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
-+              force_abort(ctx);
-+      }
-+}
-+
-+void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      __ipu_image_convert_abort(ctx);
-+      ctx->aborting = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
-+
-+/* Unprepare image conversion context */
-+void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      unsigned long flags;
-+      bool put_res;
-+
-+      /* make sure no runs are hanging around */
-+      __ipu_image_convert_abort(ctx);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
-+              chan->ic_task, ctx);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      list_del(&ctx->list);
-+
-+      put_res = list_empty(&chan->ctx_list);
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (put_res)
-+              release_ipu_resources(chan);
-+
-+      free_dma_buf(priv, &ctx->rot_intermediate[1]);
-+      free_dma_buf(priv, &ctx->rot_intermediate[0]);
-+
-+      kfree(ctx);
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
-+
-+/*
-+ * "Canned" asynchronous single image conversion. Allocates and returns
-+ * a new conversion run.  On successful return the caller must free the
-+ * run and call ipu_image_convert_unprepare() after conversion completes.
-+ */
-+struct ipu_image_convert_run *
-+ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                struct ipu_image *in, struct ipu_image *out,
-+                enum ipu_rotate_mode rot_mode,
-+                ipu_image_convert_cb_t complete,
-+                void *complete_context)
-+{
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      int ret;
-+
-+      ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
-+                                      complete, complete_context);
-+      if (IS_ERR(ctx))
-+              return ERR_CAST(ctx);
-+
-+      run = kzalloc(sizeof(*run), GFP_KERNEL);
-+      if (!run) {
-+              ipu_image_convert_unprepare(ctx);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      run->ctx = ctx;
-+      run->in_phys = in->phys0;
-+      run->out_phys = out->phys0;
-+
-+      ret = ipu_image_convert_queue(run);
-+      if (ret) {
-+              ipu_image_convert_unprepare(ctx);
-+              kfree(run);
-+              return ERR_PTR(ret);
-+      }
-+
-+      return run;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert);
-+
-+/* "Canned" synchronous single image conversion */
-+static void image_convert_sync_complete(struct ipu_image_convert_run *run,
-+                                      void *data)
-+{
-+      struct completion *comp = data;
-+
-+      complete(comp);
-+}
-+
-+int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                         struct ipu_image *in, struct ipu_image *out,
-+                         enum ipu_rotate_mode rot_mode)
-+{
-+      struct ipu_image_convert_run *run;
-+      struct completion comp;
-+      int ret;
-+
-+      init_completion(&comp);
-+
-+      run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
-+                              image_convert_sync_complete, &comp);
-+      if (IS_ERR(run))
-+              return PTR_ERR(run);
-+
-+      ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
-+      ret = (ret == 0) ? -ETIMEDOUT : 0;
-+
-+      ipu_image_convert_unprepare(run->ctx);
-+      kfree(run);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
-+
-+int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
-+{
-+      struct ipu_image_convert_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->image_convert_priv = priv;
-+      priv->ipu = ipu;
-+
-+      for (i = 0; i < IC_NUM_TASKS; i++) {
-+              struct ipu_image_convert_chan *chan = &priv->chan[i];
-+
-+              chan->ic_task = i;
-+              chan->priv = priv;
-+              chan->dma_ch = &image_convert_dma_chan[i];
-+              chan->out_eof_irq = -1;
-+              chan->rot_out_eof_irq = -1;
-+
-+              spin_lock_init(&chan->irqlock);
-+              INIT_LIST_HEAD(&chan->ctx_list);
-+              INIT_LIST_HEAD(&chan->pending_q);
-+              INIT_LIST_HEAD(&chan->done_q);
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_image_convert_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-pre.c
-@@ -0,0 +1,346 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (c) 2017 Lucas Stach, Pengutronix
-+ */
-+
-+#include <drm/drm_fourcc.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/genalloc.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+#define IPU_PRE_MAX_WIDTH     2048
-+#define IPU_PRE_NUM_SCANLINES 8
-+
-+#define IPU_PRE_CTRL                                  0x000
-+#define IPU_PRE_CTRL_SET                              0x004
-+#define  IPU_PRE_CTRL_ENABLE                          (1 << 0)
-+#define  IPU_PRE_CTRL_BLOCK_EN                                (1 << 1)
-+#define  IPU_PRE_CTRL_BLOCK_16                                (1 << 2)
-+#define  IPU_PRE_CTRL_SDW_UPDATE                      (1 << 4)
-+#define  IPU_PRE_CTRL_VFLIP                           (1 << 5)
-+#define  IPU_PRE_CTRL_SO                              (1 << 6)
-+#define  IPU_PRE_CTRL_INTERLACED_FIELD                        (1 << 7)
-+#define  IPU_PRE_CTRL_HANDSHAKE_EN                    (1 << 8)
-+#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)           ((v & 0x3) << 9)
-+#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN         (1 << 11)
-+#define  IPU_PRE_CTRL_EN_REPEAT                               (1 << 28)
-+#define  IPU_PRE_CTRL_TPR_REST_SEL                    (1 << 29)
-+#define  IPU_PRE_CTRL_CLKGATE                         (1 << 30)
-+#define  IPU_PRE_CTRL_SFTRST                          (1 << 31)
-+
-+#define IPU_PRE_CUR_BUF                                       0x030
-+
-+#define IPU_PRE_NEXT_BUF                              0x040
-+
-+#define IPU_PRE_TPR_CTRL                              0x070
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)              ((v & 0xff) << 0)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK            0xff
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT          (1 << 0)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF               (1 << 4)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF      (1 << 5)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED     (1 << 6)
-+
-+#define IPU_PRE_PREFETCH_ENG_CTRL                     0x080
-+#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN            (1 << 0)
-+#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)                ((v & 0x7) << 1)
-+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)    ((v & 0x3) << 4)
-+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)  ((v & 0x7) << 8)
-+#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS           (1 << 11)
-+#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE          (1 << 12)
-+#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP                (1 << 14)
-+#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN     (1 << 15)
-+
-+#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                       0x0a0
-+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)     ((v & 0xffff) << 0)
-+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)    ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_PREFETCH_ENG_PITCH                    0x0d0
-+#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)              ((v & 0xffff) << 0)
-+#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)             ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_STORE_ENG_CTRL                                0x110
-+#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN              (1 << 0)
-+#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)               ((v & 0x7) << 1)
-+#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)  ((v & 0x3) << 4)
-+
-+#define IPU_PRE_STORE_ENG_STATUS                      0x120
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK  0xffff
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK  0x3fff
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL     (1 << 30)
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD         (1 << 31)
-+
-+#define IPU_PRE_STORE_ENG_SIZE                                0x130
-+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)                ((v & 0xffff) << 0)
-+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)               ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_STORE_ENG_PITCH                               0x140
-+#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)         ((v & 0xffff) << 0)
-+
-+#define IPU_PRE_STORE_ENG_ADDR                                0x150
-+
-+struct ipu_pre {
-+      struct list_head        list;
-+      struct device           *dev;
-+
-+      void __iomem            *regs;
-+      struct clk              *clk_axi;
-+      struct gen_pool         *iram;
-+
-+      dma_addr_t              buffer_paddr;
-+      void                    *buffer_virt;
-+      bool                    in_use;
-+      unsigned int            safe_window_end;
-+      unsigned int            last_bufaddr;
-+};
-+
-+static DEFINE_MUTEX(ipu_pre_list_mutex);
-+static LIST_HEAD(ipu_pre_list);
-+static int available_pres;
-+
-+int ipu_pre_get_available_count(void)
-+{
-+      return available_pres;
-+}
-+
-+struct ipu_pre *
-+ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
-+{
-+      struct device_node *pre_node = of_parse_phandle(dev->of_node,
-+                                                      name, index);
-+      struct ipu_pre *pre;
-+
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_for_each_entry(pre, &ipu_pre_list, list) {
-+              if (pre_node == pre->dev->of_node) {
-+                      mutex_unlock(&ipu_pre_list_mutex);
-+                      device_link_add(dev, pre->dev,
-+                                      DL_FLAG_AUTOREMOVE_CONSUMER);
-+                      of_node_put(pre_node);
-+                      return pre;
-+              }
-+      }
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      of_node_put(pre_node);
-+
-+      return NULL;
-+}
-+
-+int ipu_pre_get(struct ipu_pre *pre)
-+{
-+      u32 val;
-+
-+      if (pre->in_use)
-+              return -EBUSY;
-+
-+      /* first get the engine out of reset and remove clock gating */
-+      writel(0, pre->regs + IPU_PRE_CTRL);
-+
-+      /* init defaults that should be applied to all streams */
-+      val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
-+            IPU_PRE_CTRL_HANDSHAKE_EN |
-+            IPU_PRE_CTRL_TPR_REST_SEL |
-+            IPU_PRE_CTRL_SDW_UPDATE;
-+      writel(val, pre->regs + IPU_PRE_CTRL);
-+
-+      pre->in_use = true;
-+      return 0;
-+}
-+
-+void ipu_pre_put(struct ipu_pre *pre)
-+{
-+      writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
-+
-+      pre->in_use = false;
-+}
-+
-+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
-+                     unsigned int height, unsigned int stride, u32 format,
-+                     uint64_t modifier, unsigned int bufaddr)
-+{
-+      const struct drm_format_info *info = drm_format_info(format);
-+      u32 active_bpp = info->cpp[0] >> 1;
-+      u32 val;
-+
-+      /* calculate safe window for ctrl register updates */
-+      if (modifier == DRM_FORMAT_MOD_LINEAR)
-+              pre->safe_window_end = height - 2;
-+      else
-+              pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
-+
-+      writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
-+      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
-+      pre->last_bufaddr = bufaddr;
-+
-+      val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
-+            IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
-+            IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
-+            IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
-+            IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
-+
-+      val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
-+            IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
-+
-+      val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
-+
-+      val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
-+            IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
-+            IPU_PRE_STORE_ENG_CTRL_STORE_EN;
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
-+
-+      val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
-+            IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
-+
-+      val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
-+
-+      writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
-+
-+      val = readl(pre->regs + IPU_PRE_TPR_CTRL);
-+      val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
-+      if (modifier != DRM_FORMAT_MOD_LINEAR) {
-+              /* only support single buffer formats for now */
-+              val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
-+              if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
-+                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
-+              if (info->cpp[0] == 2)
-+                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
-+      }
-+      writel(val, pre->regs + IPU_PRE_TPR_CTRL);
-+
-+      val = readl(pre->regs + IPU_PRE_CTRL);
-+      val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
-+             IPU_PRE_CTRL_SDW_UPDATE;
-+      if (modifier == DRM_FORMAT_MOD_LINEAR)
-+              val &= ~IPU_PRE_CTRL_BLOCK_EN;
-+      else
-+              val |= IPU_PRE_CTRL_BLOCK_EN;
-+      writel(val, pre->regs + IPU_PRE_CTRL);
-+}
-+
-+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
-+{
-+      unsigned long timeout = jiffies + msecs_to_jiffies(5);
-+      unsigned short current_yblock;
-+      u32 val;
-+
-+      if (bufaddr == pre->last_bufaddr)
-+              return;
-+
-+      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
-+      pre->last_bufaddr = bufaddr;
-+
-+      do {
-+              if (time_after(jiffies, timeout)) {
-+                      dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
-+                      return;
-+              }
-+
-+              val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
-+              current_yblock =
-+                      (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
-+                      IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
-+      } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
-+
-+      writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
-+}
-+
-+bool ipu_pre_update_pending(struct ipu_pre *pre)
-+{
-+      return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
-+                IPU_PRE_CTRL_SDW_UPDATE);
-+}
-+
-+u32 ipu_pre_get_baddr(struct ipu_pre *pre)
-+{
-+      return (u32)pre->buffer_paddr;
-+}
-+
-+static int ipu_pre_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct resource *res;
-+      struct ipu_pre *pre;
-+
-+      pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
-+      if (!pre)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      pre->regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(pre->regs))
-+              return PTR_ERR(pre->regs);
-+
-+      pre->clk_axi = devm_clk_get(dev, "axi");
-+      if (IS_ERR(pre->clk_axi))
-+              return PTR_ERR(pre->clk_axi);
-+
-+      pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
-+      if (!pre->iram)
-+              return -EPROBE_DEFER;
-+
-+      /*
-+       * Allocate IRAM buffer with maximum size. This could be made dynamic,
-+       * but as there is no other user of this IRAM region and we can fit all
-+       * max sized buffers into it, there is no need yet.
-+       */
-+      pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
-+                                            IPU_PRE_NUM_SCANLINES * 4,
-+                                            &pre->buffer_paddr);
-+      if (!pre->buffer_virt)
-+              return -ENOMEM;
-+
-+      clk_prepare_enable(pre->clk_axi);
-+
-+      pre->dev = dev;
-+      platform_set_drvdata(pdev, pre);
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_add(&pre->list, &ipu_pre_list);
-+      available_pres++;
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      return 0;
-+}
-+
-+static int ipu_pre_remove(struct platform_device *pdev)
-+{
-+      struct ipu_pre *pre = platform_get_drvdata(pdev);
-+
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_del(&pre->list);
-+      available_pres--;
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      clk_disable_unprepare(pre->clk_axi);
-+
-+      if (pre->buffer_virt)
-+              gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
-+                            IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
-+      return 0;
-+}
-+
-+static const struct of_device_id ipu_pre_dt_ids[] = {
-+      { .compatible = "fsl,imx6qp-pre", },
-+      { /* sentinel */ },
-+};
-+
-+struct platform_driver ipu_pre_drv = {
-+      .probe          = ipu_pre_probe,
-+      .remove         = ipu_pre_remove,
-+      .driver         = {
-+              .name   = "imx-ipu-pre",
-+              .of_match_table = ipu_pre_dt_ids,
-+      },
-+};
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-prg.c
-@@ -0,0 +1,483 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
-+ */
-+
-+#include <drm/drm_fourcc.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/iopoll.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regmap.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+#define IPU_PRG_CTL                           0x00
-+#define  IPU_PRG_CTL_BYPASS(i)                        (1 << (0 + i))
-+#define  IPU_PRG_CTL_SOFT_ARID_MASK           0x3
-+#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)               (8 + i * 2)
-+#define  IPU_PRG_CTL_SOFT_ARID(i, v)          ((v & 0x3) << (8 + 2 * i))
-+#define  IPU_PRG_CTL_SO(i)                    (1 << (16 + i))
-+#define  IPU_PRG_CTL_VFLIP(i)                 (1 << (19 + i))
-+#define  IPU_PRG_CTL_BLOCK_MODE(i)            (1 << (22 + i))
-+#define  IPU_PRG_CTL_CNT_LOAD_EN(i)           (1 << (25 + i))
-+#define  IPU_PRG_CTL_SOFTRST                  (1 << 30)
-+#define  IPU_PRG_CTL_SHADOW_EN                        (1 << 31)
-+
-+#define IPU_PRG_STATUS                                0x04
-+#define  IPU_PRG_STATUS_BUFFER0_READY(i)      (1 << (0 + i * 2))
-+#define  IPU_PRG_STATUS_BUFFER1_READY(i)      (1 << (1 + i * 2))
-+
-+#define IPU_PRG_QOS                           0x08
-+#define  IPU_PRG_QOS_ARID_MASK                        0xf
-+#define  IPU_PRG_QOS_ARID_SHIFT(i)            (0 + i * 4)
-+
-+#define IPU_PRG_REG_UPDATE                    0x0c
-+#define  IPU_PRG_REG_UPDATE_REG_UPDATE                (1 << 0)
-+
-+#define IPU_PRG_STRIDE(i)                     (0x10 + i * 0x4)
-+#define  IPU_PRG_STRIDE_STRIDE_MASK           0x3fff
-+
-+#define IPU_PRG_CROP_LINE                     0x1c
-+
-+#define IPU_PRG_THD                           0x20
-+
-+#define IPU_PRG_BADDR(i)                      (0x24 + i * 0x4)
-+
-+#define IPU_PRG_OFFSET(i)                     (0x30 + i * 0x4)
-+
-+#define IPU_PRG_ILO(i)                                (0x3c + i * 0x4)
-+
-+#define IPU_PRG_HEIGHT(i)                     (0x48 + i * 0x4)
-+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK               0xfff
-+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT      0
-+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK               0xfff
-+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT      16
-+
-+struct ipu_prg_channel {
-+      bool                    enabled;
-+      int                     used_pre;
-+};
-+
-+struct ipu_prg {
-+      struct list_head        list;
-+      struct device           *dev;
-+      int                     id;
-+
-+      void __iomem            *regs;
-+      struct clk              *clk_ipg, *clk_axi;
-+      struct regmap           *iomuxc_gpr;
-+      struct ipu_pre          *pres[3];
-+
-+      struct ipu_prg_channel  chan[3];
-+};
-+
-+static DEFINE_MUTEX(ipu_prg_list_mutex);
-+static LIST_HEAD(ipu_prg_list);
-+
-+struct ipu_prg *
-+ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
-+{
-+      struct device_node *prg_node = of_parse_phandle(dev->of_node,
-+                                                      name, 0);
-+      struct ipu_prg *prg;
-+
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_for_each_entry(prg, &ipu_prg_list, list) {
-+              if (prg_node == prg->dev->of_node) {
-+                      mutex_unlock(&ipu_prg_list_mutex);
-+                      device_link_add(dev, prg->dev,
-+                                      DL_FLAG_AUTOREMOVE_CONSUMER);
-+                      prg->id = ipu_id;
-+                      of_node_put(prg_node);
-+                      return prg;
-+              }
-+      }
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      of_node_put(prg_node);
-+
-+      return NULL;
-+}
-+
-+int ipu_prg_max_active_channels(void)
-+{
-+      return ipu_pre_get_available_count();
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
-+
-+bool ipu_prg_present(struct ipu_soc *ipu)
-+{
-+      if (ipu->prg_priv)
-+              return true;
-+
-+      return false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_present);
-+
-+bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
-+                            uint64_t modifier)
-+{
-+      const struct drm_format_info *info = drm_format_info(format);
-+
-+      if (info->num_planes != 1)
-+              return false;
-+
-+      switch (modifier) {
-+      case DRM_FORMAT_MOD_LINEAR:
-+      case DRM_FORMAT_MOD_VIVANTE_TILED:
-+      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
-+              return true;
-+      default:
-+              return false;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
-+
-+int ipu_prg_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_prg *prg = ipu->prg_priv;
-+
-+      if (!prg)
-+              return 0;
-+
-+      return pm_runtime_get_sync(prg->dev);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_enable);
-+
-+void ipu_prg_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_prg *prg = ipu->prg_priv;
-+
-+      if (!prg)
-+              return;
-+
-+      pm_runtime_put(prg->dev);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_disable);
-+
-+/*
-+ * The channel configuartion functions below are not thread safe, as they
-+ * must be only called from the atomic commit path in the DRM driver, which
-+ * is properly serialized.
-+ */
-+static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
-+{
-+      /*
-+       * This isn't clearly documented in the RM, but IPU to PRG channel
-+       * assignment is fixed, as only with this mapping the control signals
-+       * match up.
-+       */
-+      switch (ipu_chan) {
-+      case IPUV3_CHANNEL_MEM_BG_SYNC:
-+              return 0;
-+      case IPUV3_CHANNEL_MEM_FG_SYNC:
-+              return 1;
-+      case IPUV3_CHANNEL_MEM_DC_SYNC:
-+              return 2;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
-+{
-+      int i, ret;
-+
-+      /* channel 0 is special as it is hardwired to one of the PREs */
-+      if (prg_chan == 0) {
-+              ret = ipu_pre_get(prg->pres[0]);
-+              if (ret)
-+                      goto fail;
-+              prg->chan[prg_chan].used_pre = 0;
-+              return 0;
-+      }
-+
-+      for (i = 1; i < 3; i++) {
-+              ret = ipu_pre_get(prg->pres[i]);
-+              if (!ret) {
-+                      u32 val, mux;
-+                      int shift;
-+
-+                      prg->chan[prg_chan].used_pre = i;
-+
-+                      /* configure the PRE to PRG channel mux */
-+                      shift = (i == 1) ? 12 : 14;
-+                      mux = (prg->id << 1) | (prg_chan - 1);
-+                      regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
-+                                         0x3 << shift, mux << shift);
-+
-+                      /* check other mux, must not point to same channel */
-+                      shift = (i == 1) ? 14 : 12;
-+                      regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
-+                      if (((val >> shift) & 0x3) == mux) {
-+                              regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
-+                                                 0x3 << shift,
-+                                                 (mux ^ 0x1) << shift);
-+                      }
-+
-+                      return 0;
-+              }
-+      }
-+
-+fail:
-+      dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
-+      return ret;
-+}
-+
-+static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
-+{
-+      struct ipu_prg_channel *chan = &prg->chan[prg_chan];
-+
-+      ipu_pre_put(prg->pres[chan->used_pre]);
-+      chan->used_pre = -1;
-+}
-+
-+void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+      u32 val;
-+
-+      if (prg_chan < 0)
-+              return;
-+
-+      chan = &prg->chan[prg_chan];
-+      if (!chan->enabled)
-+              return;
-+
-+      pm_runtime_get_sync(prg->dev);
-+
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      val |= IPU_PRG_CTL_BYPASS(prg_chan);
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
-+      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
-+
-+      pm_runtime_put(prg->dev);
-+
-+      ipu_prg_put_pre(prg, prg_chan);
-+
-+      chan->enabled = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
-+
-+int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
-+                            unsigned int axi_id, unsigned int width,
-+                            unsigned int height, unsigned int stride,
-+                            u32 format, uint64_t modifier, unsigned long *eba)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+      u32 val;
-+      int ret;
-+
-+      if (prg_chan < 0)
-+              return prg_chan;
-+
-+      chan = &prg->chan[prg_chan];
-+
-+      if (chan->enabled) {
-+              ipu_pre_update(prg->pres[chan->used_pre], *eba);
-+              return 0;
-+      }
-+
-+      ret = ipu_prg_get_pre(prg, prg_chan);
-+      if (ret)
-+              return ret;
-+
-+      ipu_pre_configure(prg->pres[chan->used_pre],
-+                        width, height, stride, format, modifier, *eba);
-+
-+
-+      pm_runtime_get_sync(prg->dev);
-+
-+      val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
-+      writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
-+
-+      val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
-+             IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
-+            ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
-+             IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
-+      writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
-+
-+      val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
-+      *eba = val;
-+      writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
-+
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      /* config AXI ID */
-+      val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
-+               IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
-+      val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
-+      /* enable channel */
-+      val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
-+      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
-+
-+      /* wait for both double buffers to be filled */
-+      readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
-+                         (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
-+                         (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
-+                         5, 1000);
-+
-+      pm_runtime_put(prg->dev);
-+
-+      chan->enabled = true;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
-+
-+bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+
-+      if (prg_chan < 0)
-+              return false;
-+
-+      chan = &prg->chan[prg_chan];
-+      WARN_ON(!chan->enabled);
-+
-+      return ipu_pre_update_pending(prg->pres[chan->used_pre]);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
-+
-+static int ipu_prg_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct resource *res;
-+      struct ipu_prg *prg;
-+      u32 val;
-+      int i, ret;
-+
-+      prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
-+      if (!prg)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      prg->regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(prg->regs))
-+              return PTR_ERR(prg->regs);
-+
-+
-+      prg->clk_ipg = devm_clk_get(dev, "ipg");
-+      if (IS_ERR(prg->clk_ipg))
-+              return PTR_ERR(prg->clk_ipg);
-+
-+      prg->clk_axi = devm_clk_get(dev, "axi");
-+      if (IS_ERR(prg->clk_axi))
-+              return PTR_ERR(prg->clk_axi);
-+
-+      prg->iomuxc_gpr =
-+              syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
-+      if (IS_ERR(prg->iomuxc_gpr))
-+              return PTR_ERR(prg->iomuxc_gpr);
-+
-+      for (i = 0; i < 3; i++) {
-+              prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
-+              if (!prg->pres[i])
-+                      return -EPROBE_DEFER;
-+      }
-+
-+      ret = clk_prepare_enable(prg->clk_ipg);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_prepare_enable(prg->clk_axi);
-+      if (ret) {
-+              clk_disable_unprepare(prg->clk_ipg);
-+              return ret;
-+      }
-+
-+      /* init to free running mode */
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      val |= IPU_PRG_CTL_SHADOW_EN;
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      /* disable address threshold */
-+      writel(0xffffffff, prg->regs + IPU_PRG_THD);
-+
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+
-+      prg->dev = dev;
-+      platform_set_drvdata(pdev, prg);
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_add(&prg->list, &ipu_prg_list);
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      return 0;
-+}
-+
-+static int ipu_prg_remove(struct platform_device *pdev)
-+{
-+      struct ipu_prg *prg = platform_get_drvdata(pdev);
-+
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_del(&prg->list);
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int prg_suspend(struct device *dev)
-+{
-+      struct ipu_prg *prg = dev_get_drvdata(dev);
-+
-+      clk_disable_unprepare(prg->clk_axi);
-+      clk_disable_unprepare(prg->clk_ipg);
-+
-+      return 0;
-+}
-+
-+static int prg_resume(struct device *dev)
-+{
-+      struct ipu_prg *prg = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = clk_prepare_enable(prg->clk_ipg);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_prepare_enable(prg->clk_axi);
-+      if (ret) {
-+              clk_disable_unprepare(prg->clk_ipg);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
-+static const struct dev_pm_ops prg_pm_ops = {
-+      SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
-+};
-+
-+static const struct of_device_id ipu_prg_dt_ids[] = {
-+      { .compatible = "fsl,imx6qp-prg", },
-+      { /* sentinel */ },
-+};
-+
-+struct platform_driver ipu_prg_drv = {
-+      .probe          = ipu_prg_probe,
-+      .remove         = ipu_prg_remove,
-+      .driver         = {
-+              .name   = "imx-ipu-prg",
-+              .pm     = &prg_pm_ops,
-+              .of_match_table = ipu_prg_dt_ids,
-+      },
-+};
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-prv.h
-@@ -0,0 +1,274 @@
-+/* SPDX-License-Identifier: GPL-2.0-or-later */
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#ifndef __IPU_PRV_H__
-+#define __IPU_PRV_H__
-+
-+struct ipu_soc;
-+
-+#include <linux/types.h>
-+#include <linux/device.h>
-+#include <linux/clk.h>
-+#include <linux/platform_device.h>
-+
-+#include <video/imx-ipu-v3.h>
-+
-+#define IPU_MCU_T_DEFAULT     8
-+#define IPU_CM_IDMAC_REG_OFS  0x00008000
-+#define IPU_CM_IC_REG_OFS     0x00020000
-+#define IPU_CM_IRT_REG_OFS    0x00028000
-+#define IPU_CM_CSI0_REG_OFS   0x00030000
-+#define IPU_CM_CSI1_REG_OFS   0x00038000
-+#define IPU_CM_SMFC_REG_OFS   0x00050000
-+#define IPU_CM_DC_REG_OFS     0x00058000
-+#define IPU_CM_DMFC_REG_OFS   0x00060000
-+
-+/* Register addresses */
-+/* IPU Common registers */
-+#define IPU_CM_REG(offset)    (offset)
-+
-+#define IPU_CONF                      IPU_CM_REG(0)
-+
-+#define IPU_SRM_PRI1                  IPU_CM_REG(0x00a0)
-+#define IPU_SRM_PRI2                  IPU_CM_REG(0x00a4)
-+#define IPU_FS_PROC_FLOW1             IPU_CM_REG(0x00a8)
-+#define IPU_FS_PROC_FLOW2             IPU_CM_REG(0x00ac)
-+#define IPU_FS_PROC_FLOW3             IPU_CM_REG(0x00b0)
-+#define IPU_FS_DISP_FLOW1             IPU_CM_REG(0x00b4)
-+#define IPU_FS_DISP_FLOW2             IPU_CM_REG(0x00b8)
-+#define IPU_SKIP                      IPU_CM_REG(0x00bc)
-+#define IPU_DISP_ALT_CONF             IPU_CM_REG(0x00c0)
-+#define IPU_DISP_GEN                  IPU_CM_REG(0x00c4)
-+#define IPU_DISP_ALT1                 IPU_CM_REG(0x00c8)
-+#define IPU_DISP_ALT2                 IPU_CM_REG(0x00cc)
-+#define IPU_DISP_ALT3                 IPU_CM_REG(0x00d0)
-+#define IPU_DISP_ALT4                 IPU_CM_REG(0x00d4)
-+#define IPU_SNOOP                     IPU_CM_REG(0x00d8)
-+#define IPU_MEM_RST                   IPU_CM_REG(0x00dc)
-+#define IPU_PM                                IPU_CM_REG(0x00e0)
-+#define IPU_GPR                               IPU_CM_REG(0x00e4)
-+#define IPU_CHA_DB_MODE_SEL(ch)               IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_DB_MODE_SEL(ch)   IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
-+#define IPU_CHA_CUR_BUF(ch)           IPU_CM_REG(0x023C + 4 * ((ch) / 32))
-+#define IPU_ALT_CUR_BUF0              IPU_CM_REG(0x0244)
-+#define IPU_ALT_CUR_BUF1              IPU_CM_REG(0x0248)
-+#define IPU_SRM_STAT                  IPU_CM_REG(0x024C)
-+#define IPU_PROC_TASK_STAT            IPU_CM_REG(0x0250)
-+#define IPU_DISP_TASK_STAT            IPU_CM_REG(0x0254)
-+#define IPU_CHA_BUF0_RDY(ch)          IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
-+#define IPU_CHA_BUF1_RDY(ch)          IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
-+#define IPU_CHA_BUF2_RDY(ch)          IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_BUF0_RDY(ch)      IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_BUF1_RDY(ch)      IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
-+
-+#define IPU_INT_CTRL(n)               IPU_CM_REG(0x003C + 4 * (n))
-+#define IPU_INT_STAT(n)               IPU_CM_REG(0x0200 + 4 * (n))
-+
-+/* SRM_PRI2 */
-+#define DP_S_SRM_MODE_MASK            (0x3 << 3)
-+#define DP_S_SRM_MODE_NOW             (0x3 << 3)
-+#define DP_S_SRM_MODE_NEXT_FRAME      (0x1 << 3)
-+
-+/* FS_PROC_FLOW1 */
-+#define FS_PRPENC_ROT_SRC_SEL_MASK    (0xf << 0)
-+#define FS_PRPENC_ROT_SRC_SEL_ENC             (0x7 << 0)
-+#define FS_PRPVF_ROT_SRC_SEL_MASK     (0xf << 8)
-+#define FS_PRPVF_ROT_SRC_SEL_VF                       (0x8 << 8)
-+#define FS_PP_SRC_SEL_MASK            (0xf << 12)
-+#define FS_PP_ROT_SRC_SEL_MASK                (0xf << 16)
-+#define FS_PP_ROT_SRC_SEL_PP                  (0x5 << 16)
-+#define FS_VDI1_SRC_SEL_MASK          (0x3 << 20)
-+#define FS_VDI3_SRC_SEL_MASK          (0x3 << 20)
-+#define FS_PRP_SRC_SEL_MASK           (0xf << 24)
-+#define FS_VDI_SRC_SEL_MASK           (0x3 << 28)
-+#define FS_VDI_SRC_SEL_CSI_DIRECT             (0x1 << 28)
-+#define FS_VDI_SRC_SEL_VDOA                   (0x2 << 28)
-+
-+/* FS_PROC_FLOW2 */
-+#define FS_PRP_ENC_DEST_SEL_MASK      (0xf << 0)
-+#define FS_PRP_ENC_DEST_SEL_IRT_ENC           (0x1 << 0)
-+#define FS_PRPVF_DEST_SEL_MASK                (0xf << 4)
-+#define FS_PRPVF_DEST_SEL_IRT_VF              (0x1 << 4)
-+#define FS_PRPVF_ROT_DEST_SEL_MASK    (0xf << 8)
-+#define FS_PP_DEST_SEL_MASK           (0xf << 12)
-+#define FS_PP_DEST_SEL_IRT_PP                 (0x3 << 12)
-+#define FS_PP_ROT_DEST_SEL_MASK               (0xf << 16)
-+#define FS_PRPENC_ROT_DEST_SEL_MASK   (0xf << 20)
-+#define FS_PRP_DEST_SEL_MASK          (0xf << 24)
-+
-+#define IPU_DI0_COUNTER_RELEASE                       (1 << 24)
-+#define IPU_DI1_COUNTER_RELEASE                       (1 << 25)
-+
-+#define IPU_IDMAC_REG(offset) (offset)
-+
-+#define IDMAC_CONF                    IPU_IDMAC_REG(0x0000)
-+#define IDMAC_CHA_EN(ch)              IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
-+#define IDMAC_SEP_ALPHA                       IPU_IDMAC_REG(0x000c)
-+#define IDMAC_ALT_SEP_ALPHA           IPU_IDMAC_REG(0x0010)
-+#define IDMAC_CHA_PRI(ch)             IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
-+#define IDMAC_WM_EN(ch)                       IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
-+#define IDMAC_CH_LOCK_EN_1            IPU_IDMAC_REG(0x0024)
-+#define IDMAC_CH_LOCK_EN_2            IPU_IDMAC_REG(0x0028)
-+#define IDMAC_SUB_ADDR_0              IPU_IDMAC_REG(0x002c)
-+#define IDMAC_SUB_ADDR_1              IPU_IDMAC_REG(0x0030)
-+#define IDMAC_SUB_ADDR_2              IPU_IDMAC_REG(0x0034)
-+#define IDMAC_BAND_EN(ch)             IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
-+#define IDMAC_CHA_BUSY(ch)            IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
-+
-+#define IPU_NUM_IRQS  (32 * 15)
-+
-+enum ipu_modules {
-+      IPU_CONF_CSI0_EN                = (1 << 0),
-+      IPU_CONF_CSI1_EN                = (1 << 1),
-+      IPU_CONF_IC_EN                  = (1 << 2),
-+      IPU_CONF_ROT_EN                 = (1 << 3),
-+      IPU_CONF_ISP_EN                 = (1 << 4),
-+      IPU_CONF_DP_EN                  = (1 << 5),
-+      IPU_CONF_DI0_EN                 = (1 << 6),
-+      IPU_CONF_DI1_EN                 = (1 << 7),
-+      IPU_CONF_SMFC_EN                = (1 << 8),
-+      IPU_CONF_DC_EN                  = (1 << 9),
-+      IPU_CONF_DMFC_EN                = (1 << 10),
-+
-+      IPU_CONF_VDI_EN                 = (1 << 12),
-+
-+      IPU_CONF_IDMAC_DIS              = (1 << 22),
-+
-+      IPU_CONF_IC_DMFC_SEL            = (1 << 25),
-+      IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
-+      IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
-+
-+      IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
-+      IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
-+      IPU_CONF_IC_INPUT               = (1 << 30),
-+      IPU_CONF_CSI_SEL                = (1 << 31),
-+};
-+
-+struct ipuv3_channel {
-+      unsigned int num;
-+      struct ipu_soc *ipu;
-+      struct list_head list;
-+};
-+
-+struct ipu_cpmem;
-+struct ipu_csi;
-+struct ipu_dc_priv;
-+struct ipu_dmfc_priv;
-+struct ipu_di;
-+struct ipu_ic_priv;
-+struct ipu_vdi;
-+struct ipu_image_convert_priv;
-+struct ipu_smfc_priv;
-+struct ipu_pre;
-+struct ipu_prg;
-+
-+struct ipu_devtype;
-+
-+struct ipu_soc {
-+      struct device           *dev;
-+      const struct ipu_devtype        *devtype;
-+      enum ipuv3_type         ipu_type;
-+      spinlock_t              lock;
-+      struct mutex            channel_lock;
-+      struct list_head        channels;
-+
-+      void __iomem            *cm_reg;
-+      void __iomem            *idmac_reg;
-+
-+      int                     id;
-+      int                     usecount;
-+
-+      struct clk              *clk;
-+
-+      int                     irq_sync;
-+      int                     irq_err;
-+      struct irq_domain       *domain;
-+
-+      struct ipu_cpmem        *cpmem_priv;
-+      struct ipu_dc_priv      *dc_priv;
-+      struct ipu_dp_priv      *dp_priv;
-+      struct ipu_dmfc_priv    *dmfc_priv;
-+      struct ipu_di           *di_priv[2];
-+      struct ipu_csi          *csi_priv[2];
-+      struct ipu_ic_priv      *ic_priv;
-+      struct ipu_vdi          *vdi_priv;
-+      struct ipu_image_convert_priv *image_convert_priv;
-+      struct ipu_smfc_priv    *smfc_priv;
-+      struct ipu_prg          *prg_priv;
-+};
-+
-+static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
-+{
-+      return readl(ipu->idmac_reg + offset);
-+}
-+
-+static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
-+                                 unsigned offset)
-+{
-+      writel(value, ipu->idmac_reg + offset);
-+}
-+
-+void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
-+
-+int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
-+int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
-+
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
-+
-+int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
-+               unsigned long base, u32 module, struct clk *clk_ipu);
-+void ipu_csi_exit(struct ipu_soc *ipu, int id);
-+
-+int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long tpmem_base);
-+void ipu_ic_exit(struct ipu_soc *ipu);
-+
-+int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
-+               unsigned long base, u32 module);
-+void ipu_vdi_exit(struct ipu_soc *ipu);
-+
-+int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
-+void ipu_image_convert_exit(struct ipu_soc *ipu);
-+
-+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-+              unsigned long base, u32 module, struct clk *ipu_clk);
-+void ipu_di_exit(struct ipu_soc *ipu, int id);
-+
-+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              struct clk *ipu_clk);
-+void ipu_dmfc_exit(struct ipu_soc *ipu);
-+
-+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_dp_exit(struct ipu_soc *ipu);
-+
-+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              unsigned long template_base);
-+void ipu_dc_exit(struct ipu_soc *ipu);
-+
-+int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_cpmem_exit(struct ipu_soc *ipu);
-+
-+int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_smfc_exit(struct ipu_soc *ipu);
-+
-+struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
-+                                        int index);
-+int ipu_pre_get_available_count(void);
-+int ipu_pre_get(struct ipu_pre *pre);
-+void ipu_pre_put(struct ipu_pre *pre);
-+u32 ipu_pre_get_baddr(struct ipu_pre *pre);
-+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
-+                     unsigned int height, unsigned int stride, u32 format,
-+                     uint64_t modifier, unsigned int bufaddr);
-+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
-+bool ipu_pre_update_pending(struct ipu_pre *pre);
-+
-+struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
-+                                        int ipu_id);
-+
-+extern struct platform_driver ipu_pre_drv;
-+extern struct platform_driver ipu_prg_drv;
-+
-+#endif                                /* __IPU_PRV_H__ */
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-smfc.c
-@@ -0,0 +1,202 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/errno.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/clk.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+struct ipu_smfc {
-+      struct ipu_smfc_priv *priv;
-+      int chno;
-+      bool inuse;
-+};
-+
-+struct ipu_smfc_priv {
-+      void __iomem *base;
-+      spinlock_t lock;
-+      struct ipu_soc *ipu;
-+      struct ipu_smfc channel[4];
-+      int use_count;
-+};
-+
-+/*SMFC Registers */
-+#define SMFC_MAP      0x0000
-+#define SMFC_WMC      0x0004
-+#define SMFC_BS               0x0008
-+
-+int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 4;
-+      val = readl(priv->base + SMFC_BS);
-+      val &= ~(0xf << shift);
-+      val |= burstsize << shift;
-+      writel(val, priv->base + SMFC_BS);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
-+
-+int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 3;
-+      val = readl(priv->base + SMFC_MAP);
-+      val &= ~(0x7 << shift);
-+      val |= ((csi_id << 2) | mipi_id) << shift;
-+      writel(val, priv->base + SMFC_MAP);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
-+
-+int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
-+      val = readl(priv->base + SMFC_WMC);
-+      val &= ~(0x3f << shift);
-+      val |= ((clr_level << 3) | set_level) << shift;
-+      writel(val, priv->base + SMFC_WMC);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
-+
-+int ipu_smfc_enable(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
-+
-+      priv->use_count++;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_enable);
-+
-+int ipu_smfc_disable(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_disable);
-+
-+struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
-+{
-+      struct ipu_smfc_priv *priv = ipu->smfc_priv;
-+      struct ipu_smfc *smfc, *ret;
-+      unsigned long flags;
-+
-+      if (chno >= 4)
-+              return ERR_PTR(-EINVAL);
-+
-+      smfc = &priv->channel[chno];
-+      ret = smfc;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (smfc->inuse) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      smfc->inuse = true;
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_get);
-+
-+void ipu_smfc_put(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+      smfc->inuse = false;
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_put);
-+
-+int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
-+                unsigned long base)
-+{
-+      struct ipu_smfc_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->smfc_priv = priv;
-+      spin_lock_init(&priv->lock);
-+      priv->ipu = ipu;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      for (i = 0; i < 4; i++) {
-+              priv->channel[i].priv = priv;
-+              priv->channel[i].chno = i;
-+      }
-+
-+      pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
-+
-+      return 0;
-+}
-+
-+void ipu_smfc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/imx/ipu-v3/ipu-vdi.c
-@@ -0,0 +1,234 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2016 Mentor Graphics Inc.
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/io.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_vdi {
-+      void __iomem *base;
-+      u32 module;
-+      spinlock_t lock;
-+      int use_count;
-+      struct ipu_soc *ipu;
-+};
-+
-+
-+/* VDI Register Offsets */
-+#define VDI_FSIZE 0x0000
-+#define VDI_C     0x0004
-+
-+/* VDI Register Fields */
-+#define VDI_C_CH_420             (0 << 1)
-+#define VDI_C_CH_422             (1 << 1)
-+#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
-+#define VDI_C_MOT_SEL_FULL       (2 << 2)
-+#define VDI_C_MOT_SEL_LOW        (1 << 2)
-+#define VDI_C_MOT_SEL_MED        (0 << 2)
-+#define VDI_C_BURST_SIZE1_4      (3 << 4)
-+#define VDI_C_BURST_SIZE2_4      (3 << 8)
-+#define VDI_C_BURST_SIZE3_4      (3 << 12)
-+#define VDI_C_BURST_SIZE_MASK    0xF
-+#define VDI_C_BURST_SIZE1_OFFSET 4
-+#define VDI_C_BURST_SIZE2_OFFSET 8
-+#define VDI_C_BURST_SIZE3_OFFSET 12
-+#define VDI_C_VWM1_SET_1         (0 << 16)
-+#define VDI_C_VWM1_SET_2         (1 << 16)
-+#define VDI_C_VWM1_CLR_2         (1 << 19)
-+#define VDI_C_VWM3_SET_1         (0 << 22)
-+#define VDI_C_VWM3_SET_2         (1 << 22)
-+#define VDI_C_VWM3_CLR_2         (1 << 25)
-+#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
-+#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
-+
-+static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
-+{
-+      return readl(vdi->base + offset);
-+}
-+
-+static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
-+                               unsigned int offset)
-+{
-+      writel(value, vdi->base + offset);
-+}
-+
-+void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
-+{
-+      bool top_field_0 = false;
-+      unsigned long flags;
-+      u32 reg;
-+
-+      switch (field) {
-+      case V4L2_FIELD_INTERLACED_TB:
-+      case V4L2_FIELD_SEQ_TB:
-+      case V4L2_FIELD_TOP:
-+              top_field_0 = true;
-+              break;
-+      case V4L2_FIELD_INTERLACED_BT:
-+      case V4L2_FIELD_SEQ_BT:
-+      case V4L2_FIELD_BOTTOM:
-+              top_field_0 = false;
-+              break;
-+      default:
-+              top_field_0 = (std & V4L2_STD_525_60) ? true : false;
-+              break;
-+      }
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+      if (top_field_0)
-+              reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
-+      else
-+              reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
-+
-+void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+
-+      reg &= ~VDI_C_MOT_SEL_MASK;
-+
-+      switch (motion_sel) {
-+      case MED_MOTION:
-+              reg |= VDI_C_MOT_SEL_MED;
-+              break;
-+      case HIGH_MOTION:
-+              reg |= VDI_C_MOT_SEL_FULL;
-+              break;
-+      default:
-+              reg |= VDI_C_MOT_SEL_LOW;
-+              break;
-+      }
-+
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
-+
-+void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
-+{
-+      unsigned long flags;
-+      u32 pixel_fmt, reg;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ((yres - 1) << 16) | (xres - 1);
-+      ipu_vdi_write(vdi, reg, VDI_FSIZE);
-+
-+      /*
-+       * Full motion, only vertical filter is used.
-+       * Burst size is 4 accesses
-+       */
-+      if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
-+          code == MEDIA_BUS_FMT_UYVY8_1X16 ||
-+          code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-+          code == MEDIA_BUS_FMT_YUYV8_1X16)
-+              pixel_fmt = VDI_C_CH_422;
-+      else
-+              pixel_fmt = VDI_C_CH_420;
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+      reg |= pixel_fmt;
-+      reg |= VDI_C_BURST_SIZE2_4;
-+      reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
-+      reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_setup);
-+
-+void ipu_vdi_unsetup(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+      ipu_vdi_write(vdi, 0, VDI_FSIZE);
-+      ipu_vdi_write(vdi, 0, VDI_C);
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
-+
-+int ipu_vdi_enable(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      if (!vdi->use_count)
-+              ipu_module_enable(vdi->ipu, vdi->module);
-+
-+      vdi->use_count++;
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_enable);
-+
-+int ipu_vdi_disable(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      if (vdi->use_count) {
-+              if (!--vdi->use_count)
-+                      ipu_module_disable(vdi->ipu, vdi->module);
-+      }
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_disable);
-+
-+struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
-+{
-+      return ipu->vdi_priv;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_get);
-+
-+void ipu_vdi_put(struct ipu_vdi *vdi)
-+{
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_put);
-+
-+int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
-+               unsigned long base, u32 module)
-+{
-+      struct ipu_vdi *vdi;
-+
-+      vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
-+      if (!vdi)
-+              return -ENOMEM;
-+
-+      ipu->vdi_priv = vdi;
-+
-+      spin_lock_init(&vdi->lock);
-+      vdi->module = module;
-+      vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!vdi->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
-+      vdi->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_vdi_exit(struct ipu_soc *ipu)
-+{
-+}
---- a/drivers/gpu/ipu-v3/Kconfig
-+++ /dev/null
-@@ -1,11 +0,0 @@
--# SPDX-License-Identifier: GPL-2.0-only
--config IMX_IPUV3_CORE
--      tristate "IPUv3 core support"
--      depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
--      depends on DRM || !DRM # if DRM=m, this can't be 'y'
--      select BITREVERSE
--      select GENERIC_ALLOCATOR if DRM
--      select GENERIC_IRQ_CHIP
--      help
--        Choose this if you have a i.MX5/6 system and want to use the Image
--        Processing Unit. This option only enables IPU base support.
---- a/drivers/gpu/ipu-v3/Makefile
-+++ /dev/null
-@@ -1,10 +0,0 @@
--# SPDX-License-Identifier: GPL-2.0
--obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
--
--imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
--              ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
--              ipu-image-convert.o ipu-smfc.o ipu-vdi.o
--
--ifdef CONFIG_DRM
--      imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
--endif
---- a/drivers/gpu/ipu-v3/ipu-common.c
-+++ /dev/null
-@@ -1,1565 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/module.h>
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/reset.h>
--#include <linux/platform_device.h>
--#include <linux/err.h>
--#include <linux/spinlock.h>
--#include <linux/delay.h>
--#include <linux/interrupt.h>
--#include <linux/io.h>
--#include <linux/clk.h>
--#include <linux/list.h>
--#include <linux/irq.h>
--#include <linux/irqchip/chained_irq.h>
--#include <linux/irqdomain.h>
--#include <linux/of_device.h>
--#include <linux/of_graph.h>
--
--#include <drm/drm_fourcc.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
--{
--      return readl(ipu->cm_reg + offset);
--}
--
--static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
--{
--      writel(value, ipu->cm_reg + offset);
--}
--
--int ipu_get_num(struct ipu_soc *ipu)
--{
--      return ipu->id;
--}
--EXPORT_SYMBOL_GPL(ipu_get_num);
--
--void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
--{
--      u32 val;
--
--      val = ipu_cm_read(ipu, IPU_SRM_PRI2);
--      val &= ~DP_S_SRM_MODE_MASK;
--      val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
--                    DP_S_SRM_MODE_NOW;
--      ipu_cm_write(ipu, val, IPU_SRM_PRI2);
--}
--EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
--
--enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
--{
--      switch (drm_fourcc) {
--      case DRM_FORMAT_ARGB1555:
--      case DRM_FORMAT_ABGR1555:
--      case DRM_FORMAT_RGBA5551:
--      case DRM_FORMAT_BGRA5551:
--      case DRM_FORMAT_RGB565:
--      case DRM_FORMAT_BGR565:
--      case DRM_FORMAT_RGB888:
--      case DRM_FORMAT_BGR888:
--      case DRM_FORMAT_ARGB4444:
--      case DRM_FORMAT_XRGB8888:
--      case DRM_FORMAT_XBGR8888:
--      case DRM_FORMAT_RGBX8888:
--      case DRM_FORMAT_BGRX8888:
--      case DRM_FORMAT_ARGB8888:
--      case DRM_FORMAT_ABGR8888:
--      case DRM_FORMAT_RGBA8888:
--      case DRM_FORMAT_BGRA8888:
--      case DRM_FORMAT_RGB565_A8:
--      case DRM_FORMAT_BGR565_A8:
--      case DRM_FORMAT_RGB888_A8:
--      case DRM_FORMAT_BGR888_A8:
--      case DRM_FORMAT_RGBX8888_A8:
--      case DRM_FORMAT_BGRX8888_A8:
--              return IPUV3_COLORSPACE_RGB;
--      case DRM_FORMAT_YUYV:
--      case DRM_FORMAT_UYVY:
--      case DRM_FORMAT_YUV420:
--      case DRM_FORMAT_YVU420:
--      case DRM_FORMAT_YUV422:
--      case DRM_FORMAT_YVU422:
--      case DRM_FORMAT_YUV444:
--      case DRM_FORMAT_YVU444:
--      case DRM_FORMAT_NV12:
--      case DRM_FORMAT_NV21:
--      case DRM_FORMAT_NV16:
--      case DRM_FORMAT_NV61:
--              return IPUV3_COLORSPACE_YUV;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
--
--enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_UYVY:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              return IPUV3_COLORSPACE_YUV;
--      case V4L2_PIX_FMT_RGB565:
--      case V4L2_PIX_FMT_BGR24:
--      case V4L2_PIX_FMT_RGB24:
--      case V4L2_PIX_FMT_ABGR32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_BGRA32:
--      case V4L2_PIX_FMT_BGRX32:
--      case V4L2_PIX_FMT_RGBA32:
--      case V4L2_PIX_FMT_RGBX32:
--      case V4L2_PIX_FMT_ARGB32:
--      case V4L2_PIX_FMT_XRGB32:
--              return IPUV3_COLORSPACE_RGB;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
--
--bool ipu_pixelformat_is_planar(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              return true;
--      }
--
--      return false;
--}
--EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
--
--enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
--{
--      switch (mbus_code & 0xf000) {
--      case 0x1000:
--              return IPUV3_COLORSPACE_RGB;
--      case 0x2000:
--              return IPUV3_COLORSPACE_YUV;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
--
--int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              /*
--               * for the planar YUV formats, the stride passed to
--               * cpmem must be the stride in bytes of the Y plane.
--               * And all the planar YUV formats have an 8-bit
--               * Y component.
--               */
--              return (8 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_RGB565:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_UYVY:
--              return (16 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_BGR24:
--      case V4L2_PIX_FMT_RGB24:
--              return (24 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_BGR32:
--      case V4L2_PIX_FMT_RGB32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_XRGB32:
--              return (32 * pixel_stride) >> 3;
--      default:
--              break;
--      }
--
--      return -EINVAL;
--}
--EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
--
--int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
--                          bool hflip, bool vflip)
--{
--      u32 r90, vf, hf;
--
--      switch (degrees) {
--      case 0:
--              vf = hf = r90 = 0;
--              break;
--      case 90:
--              vf = hf = 0;
--              r90 = 1;
--              break;
--      case 180:
--              vf = hf = 1;
--              r90 = 0;
--              break;
--      case 270:
--              vf = hf = r90 = 1;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      hf ^= (u32)hflip;
--      vf ^= (u32)vflip;
--
--      *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
--
--int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
--                          bool hflip, bool vflip)
--{
--      u32 r90, vf, hf;
--
--      r90 = ((u32)mode >> 2) & 0x1;
--      hf = ((u32)mode >> 1) & 0x1;
--      vf = ((u32)mode >> 0) & 0x1;
--      hf ^= (u32)hflip;
--      vf ^= (u32)vflip;
--
--      switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
--      case IPU_ROTATE_NONE:
--              *degrees = 0;
--              break;
--      case IPU_ROTATE_90_RIGHT:
--              *degrees = 90;
--              break;
--      case IPU_ROTATE_180:
--              *degrees = 180;
--              break;
--      case IPU_ROTATE_90_LEFT:
--              *degrees = 270;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
--
--struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
--{
--      struct ipuv3_channel *channel;
--
--      dev_dbg(ipu->dev, "%s %d\n", __func__, num);
--
--      if (num > 63)
--              return ERR_PTR(-ENODEV);
--
--      mutex_lock(&ipu->channel_lock);
--
--      list_for_each_entry(channel, &ipu->channels, list) {
--              if (channel->num == num) {
--                      channel = ERR_PTR(-EBUSY);
--                      goto out;
--              }
--      }
--
--      channel = kzalloc(sizeof(*channel), GFP_KERNEL);
--      if (!channel) {
--              channel = ERR_PTR(-ENOMEM);
--              goto out;
--      }
--
--      channel->num = num;
--      channel->ipu = ipu;
--      list_add(&channel->list, &ipu->channels);
--
--out:
--      mutex_unlock(&ipu->channel_lock);
--
--      return channel;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_get);
--
--void ipu_idmac_put(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--
--      dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
--
--      mutex_lock(&ipu->channel_lock);
--
--      list_del(&channel->list);
--      kfree(channel);
--
--      mutex_unlock(&ipu->channel_lock);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_put);
--
--#define idma_mask(ch)                 (1 << ((ch) & 0x1f))
--
--/*
-- * This is an undocumented feature, a write one to a channel bit in
-- * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
-- * internal current buffer pointer so that transfers start from buffer
-- * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
-- * only says these are read-only registers). This operation is required
-- * for channel linking to work correctly, for instance video capture
-- * pipelines that carry out image rotations will fail after the first
-- * streaming unless this function is called for each channel before
-- * re-enabling the channels.
-- */
--static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--
--      ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
--}
--
--void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
--              bool doublebuffer)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
--      if (doublebuffer)
--              reg |= idma_mask(channel->num);
--      else
--              reg &= ~idma_mask(channel->num);
--      ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
--
--      __ipu_idmac_reset_current_buffer(channel);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
--
--static const struct {
--      int chnum;
--      u32 reg;
--      int shift;
--} idmac_lock_en_info[] = {
--      { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
--      { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
--      { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
--      { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
--      { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
--      { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
--      { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
--      { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
--      { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
--      { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
--      { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
--      { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
--      { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
--      { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
--      { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
--      { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
--      { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
--};
--
--int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 bursts, regval;
--      int i;
--
--      switch (num_bursts) {
--      case 0:
--      case 1:
--              bursts = 0x00; /* locking disabled */
--              break;
--      case 2:
--              bursts = 0x01;
--              break;
--      case 4:
--              bursts = 0x02;
--              break;
--      case 8:
--              bursts = 0x03;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      /*
--       * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
--       * i.MX53 channel arbitration locking doesn't seem to work properly.
--       * Allow enabling the lock feature on IPUv3H / i.MX6 only.
--       */
--      if (bursts && ipu->ipu_type != IPUV3H)
--              return -EINVAL;
--
--      for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
--              if (channel->num == idmac_lock_en_info[i].chnum)
--                      break;
--      }
--      if (i >= ARRAY_SIZE(idmac_lock_en_info))
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
--      regval &= ~(0x03 << idmac_lock_en_info[i].shift);
--      regval |= (bursts << idmac_lock_en_info[i].shift);
--      ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
--
--int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
--{
--      unsigned long lock_flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, lock_flags);
--
--      val = ipu_cm_read(ipu, IPU_DISP_GEN);
--
--      if (mask & IPU_CONF_DI0_EN)
--              val |= IPU_DI0_COUNTER_RELEASE;
--      if (mask & IPU_CONF_DI1_EN)
--              val |= IPU_DI1_COUNTER_RELEASE;
--
--      ipu_cm_write(ipu, val, IPU_DISP_GEN);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      val |= mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, lock_flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_module_enable);
--
--int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
--{
--      unsigned long lock_flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, lock_flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      val &= ~mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      val = ipu_cm_read(ipu, IPU_DISP_GEN);
--
--      if (mask & IPU_CONF_DI0_EN)
--              val &= ~IPU_DI0_COUNTER_RELEASE;
--      if (mask & IPU_CONF_DI1_EN)
--              val &= ~IPU_DI1_COUNTER_RELEASE;
--
--      ipu_cm_write(ipu, val, IPU_DISP_GEN);
--
--      spin_unlock_irqrestore(&ipu->lock, lock_flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_module_disable);
--
--int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--
--      return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
--
--bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 reg = 0;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--      switch (buf_num) {
--      case 0:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
--              break;
--      case 1:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
--              break;
--      case 2:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
--              break;
--      }
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return ((reg & idma_mask(channel->num)) != 0);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
--
--void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      /* Mark buffer as ready. */
--      if (buf_num == 0)
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
--      else
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
--
--void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
--      switch (buf_num) {
--      case 0:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
--              break;
--      case 1:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
--              break;
--      case 2:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
--              break;
--      default:
--              break;
--      }
--      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
--
--int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      u32 val;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
--      val |= idma_mask(channel->num);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
--
--bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
--{
--      return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
--
--int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long timeout;
--
--      timeout = jiffies + msecs_to_jiffies(ms);
--      while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
--                      idma_mask(channel->num)) {
--              if (time_after(jiffies, timeout))
--                      return -ETIMEDOUT;
--              cpu_relax();
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
--
--int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      u32 val;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      /* Disable DMA channel(s) */
--      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
--      val &= ~idma_mask(channel->num);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
--
--      __ipu_idmac_reset_current_buffer(channel);
--
--      /* Set channel buffers NOT to be ready */
--      ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
--
--      if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
--                      idma_mask(channel->num)) {
--              ipu_cm_write(ipu, idma_mask(channel->num),
--                           IPU_CHA_BUF0_RDY(channel->num));
--      }
--
--      if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
--                      idma_mask(channel->num)) {
--              ipu_cm_write(ipu, idma_mask(channel->num),
--                           IPU_CHA_BUF1_RDY(channel->num));
--      }
--
--      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
--
--      /* Reset the double buffer */
--      val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
--      val &= ~idma_mask(channel->num);
--      ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
--
--/*
-- * The imx6 rev. D TRM says that enabling the WM feature will increase
-- * a channel's priority. Refer to Table 36-8 Calculated priority value.
-- * The sub-module that is the sink or source for the channel must enable
-- * watermark signal for this to take effect (SMFC_WM for instance).
-- */
--void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
--      if (enable)
--              val |= 1 << (channel->num % 32);
--      else
--              val &= ~(1 << (channel->num % 32));
--      ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
--
--static int ipu_memory_reset(struct ipu_soc *ipu)
--{
--      unsigned long timeout;
--
--      ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
--
--      timeout = jiffies + msecs_to_jiffies(1000);
--      while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
--              if (time_after(jiffies, timeout))
--                      return -ETIME;
--              cpu_relax();
--      }
--
--      return 0;
--}
--
--/*
-- * Set the source mux for the given CSI. Selects either parallel or
-- * MIPI CSI2 sources.
-- */
--void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
--{
--      unsigned long flags;
--      u32 val, mask;
--
--      mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
--              IPU_CONF_CSI0_DATA_SOURCE;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      if (mipi_csi2)
--              val |= mask;
--      else
--              val &= ~mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
--
--/*
-- * Set the source mux for the IC. Selects either CSI[01] or the VDI.
-- */
--void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
--{
--      unsigned long flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      if (vdi)
--              val |= IPU_CONF_IC_INPUT;
--      else
--              val &= ~IPU_CONF_IC_INPUT;
--
--      if (csi_id == 1)
--              val |= IPU_CONF_CSI_SEL;
--      else
--              val &= ~IPU_CONF_CSI_SEL;
--
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
--
--
--/* Frame Synchronization Unit Channel Linking */
--
--struct fsu_link_reg_info {
--      int chno;
--      u32 reg;
--      u32 mask;
--      u32 val;
--};
--
--struct fsu_link_info {
--      struct fsu_link_reg_info src;
--      struct fsu_link_reg_info sink;
--};
--
--static const struct fsu_link_info fsu_link_info[] = {
--      {
--              .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
--                        FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
--      }, {
--              .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
--                        FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
--      }, {
--              .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
--                        FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
--      }, {
--              .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
--              .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
--                        FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
--      },
--};
--
--static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
--{
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
--              if (src == fsu_link_info[i].src.chno &&
--                  sink == fsu_link_info[i].sink.chno)
--                      return &fsu_link_info[i];
--      }
--
--      return NULL;
--}
--
--/*
-- * Links a source channel to a sink channel in the FSU.
-- */
--int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
--{
--      const struct fsu_link_info *link;
--      u32 src_reg, sink_reg;
--      unsigned long flags;
--
--      link = find_fsu_link_info(src_ch, sink_ch);
--      if (!link)
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      if (link->src.mask) {
--              src_reg = ipu_cm_read(ipu, link->src.reg);
--              src_reg &= ~link->src.mask;
--              src_reg |= link->src.val;
--              ipu_cm_write(ipu, src_reg, link->src.reg);
--      }
--
--      if (link->sink.mask) {
--              sink_reg = ipu_cm_read(ipu, link->sink.reg);
--              sink_reg &= ~link->sink.mask;
--              sink_reg |= link->sink.val;
--              ipu_cm_write(ipu, sink_reg, link->sink.reg);
--      }
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_fsu_link);
--
--/*
-- * Unlinks source and sink channels in the FSU.
-- */
--int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
--{
--      const struct fsu_link_info *link;
--      u32 src_reg, sink_reg;
--      unsigned long flags;
--
--      link = find_fsu_link_info(src_ch, sink_ch);
--      if (!link)
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      if (link->src.mask) {
--              src_reg = ipu_cm_read(ipu, link->src.reg);
--              src_reg &= ~link->src.mask;
--              ipu_cm_write(ipu, src_reg, link->src.reg);
--      }
--
--      if (link->sink.mask) {
--              sink_reg = ipu_cm_read(ipu, link->sink.reg);
--              sink_reg &= ~link->sink.mask;
--              ipu_cm_write(ipu, sink_reg, link->sink.reg);
--      }
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
--
--/* Link IDMAC channels in the FSU */
--int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
--{
--      return ipu_fsu_link(src->ipu, src->num, sink->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_link);
--
--/* Unlink IDMAC channels in the FSU */
--int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
--{
--      return ipu_fsu_unlink(src->ipu, src->num, sink->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
--
--struct ipu_devtype {
--      const char *name;
--      unsigned long cm_ofs;
--      unsigned long cpmem_ofs;
--      unsigned long srm_ofs;
--      unsigned long tpm_ofs;
--      unsigned long csi0_ofs;
--      unsigned long csi1_ofs;
--      unsigned long ic_ofs;
--      unsigned long disp0_ofs;
--      unsigned long disp1_ofs;
--      unsigned long dc_tmpl_ofs;
--      unsigned long vdi_ofs;
--      enum ipuv3_type type;
--};
--
--static struct ipu_devtype ipu_type_imx51 = {
--      .name = "IPUv3EX",
--      .cm_ofs = 0x1e000000,
--      .cpmem_ofs = 0x1f000000,
--      .srm_ofs = 0x1f040000,
--      .tpm_ofs = 0x1f060000,
--      .csi0_ofs = 0x1e030000,
--      .csi1_ofs = 0x1e038000,
--      .ic_ofs = 0x1e020000,
--      .disp0_ofs = 0x1e040000,
--      .disp1_ofs = 0x1e048000,
--      .dc_tmpl_ofs = 0x1f080000,
--      .vdi_ofs = 0x1e068000,
--      .type = IPUV3EX,
--};
--
--static struct ipu_devtype ipu_type_imx53 = {
--      .name = "IPUv3M",
--      .cm_ofs = 0x06000000,
--      .cpmem_ofs = 0x07000000,
--      .srm_ofs = 0x07040000,
--      .tpm_ofs = 0x07060000,
--      .csi0_ofs = 0x06030000,
--      .csi1_ofs = 0x06038000,
--      .ic_ofs = 0x06020000,
--      .disp0_ofs = 0x06040000,
--      .disp1_ofs = 0x06048000,
--      .dc_tmpl_ofs = 0x07080000,
--      .vdi_ofs = 0x06068000,
--      .type = IPUV3M,
--};
--
--static struct ipu_devtype ipu_type_imx6q = {
--      .name = "IPUv3H",
--      .cm_ofs = 0x00200000,
--      .cpmem_ofs = 0x00300000,
--      .srm_ofs = 0x00340000,
--      .tpm_ofs = 0x00360000,
--      .csi0_ofs = 0x00230000,
--      .csi1_ofs = 0x00238000,
--      .ic_ofs = 0x00220000,
--      .disp0_ofs = 0x00240000,
--      .disp1_ofs = 0x00248000,
--      .dc_tmpl_ofs = 0x00380000,
--      .vdi_ofs = 0x00268000,
--      .type = IPUV3H,
--};
--
--static const struct of_device_id imx_ipu_dt_ids[] = {
--      { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
--      { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
--      { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
--      { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
--      { /* sentinel */ }
--};
--MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
--
--static int ipu_submodules_init(struct ipu_soc *ipu,
--              struct platform_device *pdev, unsigned long ipu_base,
--              struct clk *ipu_clk)
--{
--      char *unit;
--      int ret;
--      struct device *dev = &pdev->dev;
--      const struct ipu_devtype *devtype = ipu->devtype;
--
--      ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
--      if (ret) {
--              unit = "cpmem";
--              goto err_cpmem;
--      }
--
--      ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
--                         IPU_CONF_CSI0_EN, ipu_clk);
--      if (ret) {
--              unit = "csi0";
--              goto err_csi_0;
--      }
--
--      ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
--                         IPU_CONF_CSI1_EN, ipu_clk);
--      if (ret) {
--              unit = "csi1";
--              goto err_csi_1;
--      }
--
--      ret = ipu_ic_init(ipu, dev,
--                        ipu_base + devtype->ic_ofs,
--                        ipu_base + devtype->tpm_ofs);
--      if (ret) {
--              unit = "ic";
--              goto err_ic;
--      }
--
--      ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
--                         IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
--                         IPU_CONF_IC_INPUT);
--      if (ret) {
--              unit = "vdi";
--              goto err_vdi;
--      }
--
--      ret = ipu_image_convert_init(ipu, dev);
--      if (ret) {
--              unit = "image_convert";
--              goto err_image_convert;
--      }
--
--      ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
--                        IPU_CONF_DI0_EN, ipu_clk);
--      if (ret) {
--              unit = "di0";
--              goto err_di_0;
--      }
--
--      ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
--                      IPU_CONF_DI1_EN, ipu_clk);
--      if (ret) {
--              unit = "di1";
--              goto err_di_1;
--      }
--
--      ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
--                      IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
--      if (ret) {
--              unit = "dc_template";
--              goto err_dc;
--      }
--
--      ret = ipu_dmfc_init(ipu, dev, ipu_base +
--                      devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
--      if (ret) {
--              unit = "dmfc";
--              goto err_dmfc;
--      }
--
--      ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
--      if (ret) {
--              unit = "dp";
--              goto err_dp;
--      }
--
--      ret = ipu_smfc_init(ipu, dev, ipu_base +
--                      devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
--      if (ret) {
--              unit = "smfc";
--              goto err_smfc;
--      }
--
--      return 0;
--
--err_smfc:
--      ipu_dp_exit(ipu);
--err_dp:
--      ipu_dmfc_exit(ipu);
--err_dmfc:
--      ipu_dc_exit(ipu);
--err_dc:
--      ipu_di_exit(ipu, 1);
--err_di_1:
--      ipu_di_exit(ipu, 0);
--err_di_0:
--      ipu_image_convert_exit(ipu);
--err_image_convert:
--      ipu_vdi_exit(ipu);
--err_vdi:
--      ipu_ic_exit(ipu);
--err_ic:
--      ipu_csi_exit(ipu, 1);
--err_csi_1:
--      ipu_csi_exit(ipu, 0);
--err_csi_0:
--      ipu_cpmem_exit(ipu);
--err_cpmem:
--      dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
--      return ret;
--}
--
--static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
--{
--      unsigned long status;
--      int i, bit, irq;
--
--      for (i = 0; i < num_regs; i++) {
--
--              status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
--              status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
--
--              for_each_set_bit(bit, &status, 32) {
--                      irq = irq_linear_revmap(ipu->domain,
--                                              regs[i] * 32 + bit);
--                      if (irq)
--                              generic_handle_irq(irq);
--              }
--      }
--}
--
--static void ipu_irq_handler(struct irq_desc *desc)
--{
--      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
--
--      chained_irq_enter(chip, desc);
--
--      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
--
--      chained_irq_exit(chip, desc);
--}
--
--static void ipu_err_irq_handler(struct irq_desc *desc)
--{
--      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      static const int int_reg[] = { 4, 5, 8, 9};
--
--      chained_irq_enter(chip, desc);
--
--      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
--
--      chained_irq_exit(chip, desc);
--}
--
--int ipu_map_irq(struct ipu_soc *ipu, int irq)
--{
--      int virq;
--
--      virq = irq_linear_revmap(ipu->domain, irq);
--      if (!virq)
--              virq = irq_create_mapping(ipu->domain, irq);
--
--      return virq;
--}
--EXPORT_SYMBOL_GPL(ipu_map_irq);
--
--int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
--              enum ipu_channel_irq irq_type)
--{
--      return ipu_map_irq(ipu, irq_type + channel->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
--
--static void ipu_submodules_exit(struct ipu_soc *ipu)
--{
--      ipu_smfc_exit(ipu);
--      ipu_dp_exit(ipu);
--      ipu_dmfc_exit(ipu);
--      ipu_dc_exit(ipu);
--      ipu_di_exit(ipu, 1);
--      ipu_di_exit(ipu, 0);
--      ipu_image_convert_exit(ipu);
--      ipu_vdi_exit(ipu);
--      ipu_ic_exit(ipu);
--      ipu_csi_exit(ipu, 1);
--      ipu_csi_exit(ipu, 0);
--      ipu_cpmem_exit(ipu);
--}
--
--static int platform_remove_devices_fn(struct device *dev, void *unused)
--{
--      struct platform_device *pdev = to_platform_device(dev);
--
--      platform_device_unregister(pdev);
--
--      return 0;
--}
--
--static void platform_device_unregister_children(struct platform_device *pdev)
--{
--      device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
--}
--
--struct ipu_platform_reg {
--      struct ipu_client_platformdata pdata;
--      const char *name;
--};
--
--/* These must be in the order of the corresponding device tree port nodes */
--static struct ipu_platform_reg client_reg[] = {
--      {
--              .pdata = {
--                      .csi = 0,
--                      .dma[0] = IPUV3_CHANNEL_CSI0,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-csi",
--      }, {
--              .pdata = {
--                      .csi = 1,
--                      .dma[0] = IPUV3_CHANNEL_CSI1,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-csi",
--      }, {
--              .pdata = {
--                      .di = 0,
--                      .dc = 5,
--                      .dp = IPU_DP_FLOW_SYNC_BG,
--                      .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
--                      .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
--              },
--              .name = "imx-ipuv3-crtc",
--      }, {
--              .pdata = {
--                      .di = 1,
--                      .dc = 1,
--                      .dp = -EINVAL,
--                      .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-crtc",
--      },
--};
--
--static DEFINE_MUTEX(ipu_client_id_mutex);
--static int ipu_client_id;
--
--static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
--{
--      struct device *dev = ipu->dev;
--      unsigned i;
--      int id, ret;
--
--      mutex_lock(&ipu_client_id_mutex);
--      id = ipu_client_id;
--      ipu_client_id += ARRAY_SIZE(client_reg);
--      mutex_unlock(&ipu_client_id_mutex);
--
--      for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
--              struct ipu_platform_reg *reg = &client_reg[i];
--              struct platform_device *pdev;
--              struct device_node *of_node;
--
--              /* Associate subdevice with the corresponding port node */
--              of_node = of_graph_get_port_by_id(dev->of_node, i);
--              if (!of_node) {
--                      dev_info(dev,
--                               "no port@%d node in %pOF, not using %s%d\n",
--                               i, dev->of_node,
--                               (i / 2) ? "DI" : "CSI", i % 2);
--                      continue;
--              }
--
--              pdev = platform_device_alloc(reg->name, id++);
--              if (!pdev) {
--                      ret = -ENOMEM;
--                      goto err_register;
--              }
--
--              pdev->dev.parent = dev;
--
--              reg->pdata.of_node = of_node;
--              ret = platform_device_add_data(pdev, &reg->pdata,
--                                             sizeof(reg->pdata));
--              if (!ret)
--                      ret = platform_device_add(pdev);
--              if (ret) {
--                      platform_device_put(pdev);
--                      goto err_register;
--              }
--      }
--
--      return 0;
--
--err_register:
--      platform_device_unregister_children(to_platform_device(dev));
--
--      return ret;
--}
--
--
--static int ipu_irq_init(struct ipu_soc *ipu)
--{
--      struct irq_chip_generic *gc;
--      struct irq_chip_type *ct;
--      unsigned long unused[IPU_NUM_IRQS / 32] = {
--              0x400100d0, 0xffe000fd,
--              0x400100d0, 0xffe000fd,
--              0x400100d0, 0xffe000fd,
--              0x4077ffff, 0xffe7e1fd,
--              0x23fffffe, 0x8880fff0,
--              0xf98fe7d0, 0xfff81fff,
--              0x400100d0, 0xffe000fd,
--              0x00000000,
--      };
--      int ret, i;
--
--      ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
--                                          &irq_generic_chip_ops, ipu);
--      if (!ipu->domain) {
--              dev_err(ipu->dev, "failed to add irq domain\n");
--              return -ENODEV;
--      }
--
--      ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
--                                           handle_level_irq, 0, 0, 0);
--      if (ret < 0) {
--              dev_err(ipu->dev, "failed to alloc generic irq chips\n");
--              irq_domain_remove(ipu->domain);
--              return ret;
--      }
--
--      /* Mask and clear all interrupts */
--      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
--              ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
--              ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
--      }
--
--      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
--              gc = irq_get_domain_generic_chip(ipu->domain, i);
--              gc->reg_base = ipu->cm_reg;
--              gc->unused = unused[i / 32];
--              ct = gc->chip_types;
--              ct->chip.irq_ack = irq_gc_ack_set_bit;
--              ct->chip.irq_mask = irq_gc_mask_clr_bit;
--              ct->chip.irq_unmask = irq_gc_mask_set_bit;
--              ct->regs.ack = IPU_INT_STAT(i / 32);
--              ct->regs.mask = IPU_INT_CTRL(i / 32);
--      }
--
--      irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
--      irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
--                                       ipu);
--
--      return 0;
--}
--
--static void ipu_irq_exit(struct ipu_soc *ipu)
--{
--      int i, irq;
--
--      irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
--      irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
--
--      /* TODO: remove irq_domain_generic_chips */
--
--      for (i = 0; i < IPU_NUM_IRQS; i++) {
--              irq = irq_linear_revmap(ipu->domain, i);
--              if (irq)
--                      irq_dispose_mapping(irq);
--      }
--
--      irq_domain_remove(ipu->domain);
--}
--
--void ipu_dump(struct ipu_soc *ipu)
--{
--      int i;
--
--      dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CONF));
--      dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CONF));
--      dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
--      dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
--      dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
--      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
--      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
--      dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
--      for (i = 0; i < 15; i++)
--              dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
--                      ipu_cm_read(ipu, IPU_INT_CTRL(i)));
--}
--EXPORT_SYMBOL_GPL(ipu_dump);
--
--static int ipu_probe(struct platform_device *pdev)
--{
--      struct device_node *np = pdev->dev.of_node;
--      struct ipu_soc *ipu;
--      struct resource *res;
--      unsigned long ipu_base;
--      int ret, irq_sync, irq_err;
--      const struct ipu_devtype *devtype;
--
--      devtype = of_device_get_match_data(&pdev->dev);
--      if (!devtype)
--              return -EINVAL;
--
--      irq_sync = platform_get_irq(pdev, 0);
--      irq_err = platform_get_irq(pdev, 1);
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--
--      dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
--                      irq_sync, irq_err);
--
--      if (!res || irq_sync < 0 || irq_err < 0)
--              return -ENODEV;
--
--      ipu_base = res->start;
--
--      ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
--      if (!ipu)
--              return -ENODEV;
--
--      ipu->id = of_alias_get_id(np, "ipu");
--      if (ipu->id < 0)
--              ipu->id = 0;
--
--      if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
--          IS_ENABLED(CONFIG_DRM)) {
--              ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
--                                                        "fsl,prg", ipu->id);
--              if (!ipu->prg_priv)
--                      return -EPROBE_DEFER;
--      }
--
--      ipu->devtype = devtype;
--      ipu->ipu_type = devtype->type;
--
--      spin_lock_init(&ipu->lock);
--      mutex_init(&ipu->channel_lock);
--      INIT_LIST_HEAD(&ipu->channels);
--
--      dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
--                      ipu_base + devtype->cm_ofs);
--      dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
--      dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
--                      ipu_base + devtype->cpmem_ofs);
--      dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
--                      ipu_base + devtype->csi0_ofs);
--      dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
--                      ipu_base + devtype->csi1_ofs);
--      dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
--                      ipu_base + devtype->ic_ofs);
--      dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
--                      ipu_base + devtype->disp0_ofs);
--      dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
--                      ipu_base + devtype->disp1_ofs);
--      dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
--                      ipu_base + devtype->srm_ofs);
--      dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
--                      ipu_base + devtype->tpm_ofs);
--      dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
--      dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
--      dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
--      dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
--                      ipu_base + devtype->vdi_ofs);
--
--      ipu->cm_reg = devm_ioremap(&pdev->dev,
--                      ipu_base + devtype->cm_ofs, PAGE_SIZE);
--      ipu->idmac_reg = devm_ioremap(&pdev->dev,
--                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
--                      PAGE_SIZE);
--
--      if (!ipu->cm_reg || !ipu->idmac_reg)
--              return -ENOMEM;
--
--      ipu->clk = devm_clk_get(&pdev->dev, "bus");
--      if (IS_ERR(ipu->clk)) {
--              ret = PTR_ERR(ipu->clk);
--              dev_err(&pdev->dev, "clk_get failed with %d", ret);
--              return ret;
--      }
--
--      platform_set_drvdata(pdev, ipu);
--
--      ret = clk_prepare_enable(ipu->clk);
--      if (ret) {
--              dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
--              return ret;
--      }
--
--      ipu->dev = &pdev->dev;
--      ipu->irq_sync = irq_sync;
--      ipu->irq_err = irq_err;
--
--      ret = device_reset(&pdev->dev);
--      if (ret) {
--              dev_err(&pdev->dev, "failed to reset: %d\n", ret);
--              goto out_failed_reset;
--      }
--      ret = ipu_memory_reset(ipu);
--      if (ret)
--              goto out_failed_reset;
--
--      ret = ipu_irq_init(ipu);
--      if (ret)
--              goto out_failed_irq;
--
--      /* Set MCU_T to divide MCU access window into 2 */
--      ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
--                      IPU_DISP_GEN);
--
--      ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
--      if (ret)
--              goto failed_submodules_init;
--
--      ret = ipu_add_client_devices(ipu, ipu_base);
--      if (ret) {
--              dev_err(&pdev->dev, "adding client devices failed with %d\n",
--                              ret);
--              goto failed_add_clients;
--      }
--
--      dev_info(&pdev->dev, "%s probed\n", devtype->name);
--
--      return 0;
--
--failed_add_clients:
--      ipu_submodules_exit(ipu);
--failed_submodules_init:
--      ipu_irq_exit(ipu);
--out_failed_irq:
--out_failed_reset:
--      clk_disable_unprepare(ipu->clk);
--      return ret;
--}
--
--static int ipu_remove(struct platform_device *pdev)
--{
--      struct ipu_soc *ipu = platform_get_drvdata(pdev);
--
--      platform_device_unregister_children(pdev);
--      ipu_submodules_exit(ipu);
--      ipu_irq_exit(ipu);
--
--      clk_disable_unprepare(ipu->clk);
--
--      return 0;
--}
--
--static struct platform_driver imx_ipu_driver = {
--      .driver = {
--              .name = "imx-ipuv3",
--              .of_match_table = imx_ipu_dt_ids,
--      },
--      .probe = ipu_probe,
--      .remove = ipu_remove,
--};
--
--static struct platform_driver * const drivers[] = {
--#if IS_ENABLED(CONFIG_DRM)
--      &ipu_pre_drv,
--      &ipu_prg_drv,
--#endif
--      &imx_ipu_driver,
--};
--
--static int __init imx_ipu_init(void)
--{
--      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_init(imx_ipu_init);
--
--static void __exit imx_ipu_exit(void)
--{
--      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_exit(imx_ipu_exit);
--
--MODULE_ALIAS("platform:imx-ipuv3");
--MODULE_DESCRIPTION("i.MX IPU v3 driver");
--MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
--MODULE_LICENSE("GPL");
---- a/drivers/gpu/ipu-v3/ipu-cpmem.c
-+++ /dev/null
-@@ -1,976 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012 Mentor Graphics Inc.
-- * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--#include <linux/types.h>
--#include <linux/bitrev.h>
--#include <linux/io.h>
--#include <linux/sizes.h>
--#include <drm/drm_fourcc.h>
--#include "ipu-prv.h"
--
--struct ipu_cpmem_word {
--      u32 data[5];
--      u32 res[3];
--};
--
--struct ipu_ch_param {
--      struct ipu_cpmem_word word[2];
--};
--
--struct ipu_cpmem {
--      struct ipu_ch_param __iomem *base;
--      u32 module;
--      spinlock_t lock;
--      int use_count;
--      struct ipu_soc *ipu;
--};
--
--#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
--
--#define IPU_FIELD_UBO         IPU_CPMEM_WORD(0, 46, 22)
--#define IPU_FIELD_VBO         IPU_CPMEM_WORD(0, 68, 22)
--#define IPU_FIELD_IOX         IPU_CPMEM_WORD(0, 90, 4)
--#define IPU_FIELD_RDRW                IPU_CPMEM_WORD(0, 94, 1)
--#define IPU_FIELD_SO          IPU_CPMEM_WORD(0, 113, 1)
--#define IPU_FIELD_SLY         IPU_CPMEM_WORD(1, 102, 14)
--#define IPU_FIELD_SLUV                IPU_CPMEM_WORD(1, 128, 14)
--
--#define IPU_FIELD_XV          IPU_CPMEM_WORD(0, 0, 10)
--#define IPU_FIELD_YV          IPU_CPMEM_WORD(0, 10, 9)
--#define IPU_FIELD_XB          IPU_CPMEM_WORD(0, 19, 13)
--#define IPU_FIELD_YB          IPU_CPMEM_WORD(0, 32, 12)
--#define IPU_FIELD_NSB_B               IPU_CPMEM_WORD(0, 44, 1)
--#define IPU_FIELD_CF          IPU_CPMEM_WORD(0, 45, 1)
--#define IPU_FIELD_SX          IPU_CPMEM_WORD(0, 46, 12)
--#define IPU_FIELD_SY          IPU_CPMEM_WORD(0, 58, 11)
--#define IPU_FIELD_NS          IPU_CPMEM_WORD(0, 69, 10)
--#define IPU_FIELD_SDX         IPU_CPMEM_WORD(0, 79, 7)
--#define IPU_FIELD_SM          IPU_CPMEM_WORD(0, 86, 10)
--#define IPU_FIELD_SCC         IPU_CPMEM_WORD(0, 96, 1)
--#define IPU_FIELD_SCE         IPU_CPMEM_WORD(0, 97, 1)
--#define IPU_FIELD_SDY         IPU_CPMEM_WORD(0, 98, 7)
--#define IPU_FIELD_SDRX                IPU_CPMEM_WORD(0, 105, 1)
--#define IPU_FIELD_SDRY                IPU_CPMEM_WORD(0, 106, 1)
--#define IPU_FIELD_BPP         IPU_CPMEM_WORD(0, 107, 3)
--#define IPU_FIELD_DEC_SEL     IPU_CPMEM_WORD(0, 110, 2)
--#define IPU_FIELD_DIM         IPU_CPMEM_WORD(0, 112, 1)
--#define IPU_FIELD_BNDM                IPU_CPMEM_WORD(0, 114, 3)
--#define IPU_FIELD_BM          IPU_CPMEM_WORD(0, 117, 2)
--#define IPU_FIELD_ROT         IPU_CPMEM_WORD(0, 119, 1)
--#define IPU_FIELD_ROT_HF_VF   IPU_CPMEM_WORD(0, 119, 3)
--#define IPU_FIELD_HF          IPU_CPMEM_WORD(0, 120, 1)
--#define IPU_FIELD_VF          IPU_CPMEM_WORD(0, 121, 1)
--#define IPU_FIELD_THE         IPU_CPMEM_WORD(0, 122, 1)
--#define IPU_FIELD_CAP         IPU_CPMEM_WORD(0, 123, 1)
--#define IPU_FIELD_CAE         IPU_CPMEM_WORD(0, 124, 1)
--#define IPU_FIELD_FW          IPU_CPMEM_WORD(0, 125, 13)
--#define IPU_FIELD_FH          IPU_CPMEM_WORD(0, 138, 12)
--#define IPU_FIELD_EBA0                IPU_CPMEM_WORD(1, 0, 29)
--#define IPU_FIELD_EBA1                IPU_CPMEM_WORD(1, 29, 29)
--#define IPU_FIELD_ILO         IPU_CPMEM_WORD(1, 58, 20)
--#define IPU_FIELD_NPB         IPU_CPMEM_WORD(1, 78, 7)
--#define IPU_FIELD_PFS         IPU_CPMEM_WORD(1, 85, 4)
--#define IPU_FIELD_ALU         IPU_CPMEM_WORD(1, 89, 1)
--#define IPU_FIELD_ALBM                IPU_CPMEM_WORD(1, 90, 3)
--#define IPU_FIELD_ID          IPU_CPMEM_WORD(1, 93, 2)
--#define IPU_FIELD_TH          IPU_CPMEM_WORD(1, 95, 7)
--#define IPU_FIELD_SL          IPU_CPMEM_WORD(1, 102, 14)
--#define IPU_FIELD_WID0                IPU_CPMEM_WORD(1, 116, 3)
--#define IPU_FIELD_WID1                IPU_CPMEM_WORD(1, 119, 3)
--#define IPU_FIELD_WID2                IPU_CPMEM_WORD(1, 122, 3)
--#define IPU_FIELD_WID3                IPU_CPMEM_WORD(1, 125, 3)
--#define IPU_FIELD_OFS0                IPU_CPMEM_WORD(1, 128, 5)
--#define IPU_FIELD_OFS1                IPU_CPMEM_WORD(1, 133, 5)
--#define IPU_FIELD_OFS2                IPU_CPMEM_WORD(1, 138, 5)
--#define IPU_FIELD_OFS3                IPU_CPMEM_WORD(1, 143, 5)
--#define IPU_FIELD_SXYS                IPU_CPMEM_WORD(1, 148, 1)
--#define IPU_FIELD_CRE         IPU_CPMEM_WORD(1, 149, 1)
--#define IPU_FIELD_DEC_SEL2    IPU_CPMEM_WORD(1, 150, 1)
--
--static inline struct ipu_ch_param __iomem *
--ipu_get_cpmem(struct ipuv3_channel *ch)
--{
--      struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
--
--      return cpmem->base + ch->num;
--}
--
--static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
--{
--      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
--      u32 bit = (wbs >> 8) % 160;
--      u32 size = wbs & 0xff;
--      u32 word = (wbs >> 8) / 160;
--      u32 i = bit / 32;
--      u32 ofs = bit % 32;
--      u32 mask = (1 << size) - 1;
--      u32 val;
--
--      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
--
--      val = readl(&base->word[word].data[i]);
--      val &= ~(mask << ofs);
--      val |= v << ofs;
--      writel(val, &base->word[word].data[i]);
--
--      if ((bit + size - 1) / 32 > i) {
--              val = readl(&base->word[word].data[i + 1]);
--              val &= ~(mask >> (ofs ? (32 - ofs) : 0));
--              val |= v >> (ofs ? (32 - ofs) : 0);
--              writel(val, &base->word[word].data[i + 1]);
--      }
--}
--
--static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
--{
--      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
--      u32 bit = (wbs >> 8) % 160;
--      u32 size = wbs & 0xff;
--      u32 word = (wbs >> 8) / 160;
--      u32 i = bit / 32;
--      u32 ofs = bit % 32;
--      u32 mask = (1 << size) - 1;
--      u32 val = 0;
--
--      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
--
--      val = (readl(&base->word[word].data[i]) >> ofs) & mask;
--
--      if ((bit + size - 1) / 32 > i) {
--              u32 tmp;
--
--              tmp = readl(&base->word[word].data[i + 1]);
--              tmp &= mask >> (ofs ? (32 - ofs) : 0);
--              val |= tmp << (ofs ? (32 - ofs) : 0);
--      }
--
--      return val;
--}
--
--/*
-- * The V4L2 spec defines packed RGB formats in memory byte order, which from
-- * point of view of the IPU corresponds to little-endian words with the first
-- * component in the least significant bits.
-- * The DRM pixel formats and IPU internal representation are ordered the other
-- * way around, with the first named component ordered at the most significant
-- * bits. Further, V4L2 formats are not well defined:
-- *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
-- * We choose the interpretation which matches GStreamer behavior.
-- */
--static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_RGB565:
--              /*
--               * Here we choose the 'corrected' interpretation of RGBP, a
--               * little-endian 16-bit word with the red component at the most
--               * significant bits:
--               * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
--               */
--              return DRM_FORMAT_RGB565;
--      case V4L2_PIX_FMT_BGR24:
--              /* B G R <=> [24:0] R:G:B */
--              return DRM_FORMAT_RGB888;
--      case V4L2_PIX_FMT_RGB24:
--              /* R G B <=> [24:0] B:G:R */
--              return DRM_FORMAT_BGR888;
--      case V4L2_PIX_FMT_BGR32:
--              /* B G R A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_XRGB8888;
--      case V4L2_PIX_FMT_RGB32:
--              /* R G B A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_XBGR8888;
--      case V4L2_PIX_FMT_ABGR32:
--              /* B G R A <=> [32:0] A:R:G:B */
--              return DRM_FORMAT_ARGB8888;
--      case V4L2_PIX_FMT_XBGR32:
--              /* B G R X <=> [32:0] X:R:G:B */
--              return DRM_FORMAT_XRGB8888;
--      case V4L2_PIX_FMT_BGRA32:
--              /* A B G R <=> [32:0] R:G:B:A */
--              return DRM_FORMAT_RGBA8888;
--      case V4L2_PIX_FMT_BGRX32:
--              /* X B G R <=> [32:0] R:G:B:X */
--              return DRM_FORMAT_RGBX8888;
--      case V4L2_PIX_FMT_RGBA32:
--              /* R G B A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_ABGR8888;
--      case V4L2_PIX_FMT_RGBX32:
--              /* R G B X <=> [32:0] X:B:G:R */
--              return DRM_FORMAT_XBGR8888;
--      case V4L2_PIX_FMT_ARGB32:
--              /* A R G B <=> [32:0] B:G:R:A */
--              return DRM_FORMAT_BGRA8888;
--      case V4L2_PIX_FMT_XRGB32:
--              /* X R G B <=> [32:0] B:G:R:X */
--              return DRM_FORMAT_BGRX8888;
--      case V4L2_PIX_FMT_UYVY:
--              return DRM_FORMAT_UYVY;
--      case V4L2_PIX_FMT_YUYV:
--              return DRM_FORMAT_YUYV;
--      case V4L2_PIX_FMT_YUV420:
--              return DRM_FORMAT_YUV420;
--      case V4L2_PIX_FMT_YUV422P:
--              return DRM_FORMAT_YUV422;
--      case V4L2_PIX_FMT_YVU420:
--              return DRM_FORMAT_YVU420;
--      case V4L2_PIX_FMT_NV12:
--              return DRM_FORMAT_NV12;
--      case V4L2_PIX_FMT_NV16:
--              return DRM_FORMAT_NV16;
--      }
--
--      return -EINVAL;
--}
--
--void ipu_cpmem_zero(struct ipuv3_channel *ch)
--{
--      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
--      void __iomem *base = p;
--      int i;
--
--      for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
--              writel(0, base + i * sizeof(u32));
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
--
--void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
--
--void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
--
--void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
--
--void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
--{
--      struct ipu_soc *ipu = ch->ipu;
--      u32 val;
--
--      if (ipu->ipu_type == IPUV3EX)
--              ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
--
--      val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
--      val |= 1 << (ch->num % 32);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
--
--void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
--{
--      WARN_ON_ONCE(buf & 0x7);
--
--      if (bufnum)
--              ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
--      else
--              ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
--
--void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
--{
--      WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
--      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
--
--void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
--                             u32 pixelformat)
--{
--      u32 ilo, sly, sluv;
--
--      if (stride < 0) {
--              stride = -stride;
--              ilo = 0x100000 - (stride / 8);
--      } else {
--              ilo = stride / 8;
--      }
--
--      sly = (stride * 2) - 1;
--
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--              sluv = stride / 2 - 1;
--              break;
--      case V4L2_PIX_FMT_NV12:
--              sluv = stride - 1;
--              break;
--      case V4L2_PIX_FMT_YUV422P:
--              sluv = stride - 1;
--              break;
--      case V4L2_PIX_FMT_NV16:
--              sluv = stride * 2 - 1;
--              break;
--      default:
--              sluv = 0;
--              break;
--      }
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
--      if (sluv)
--              ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
--
--void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
--{
--      id &= 0x3;
--      ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
--
--int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
--{
--      return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
--
--void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
--
--void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
--
--void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
--                          enum ipu_rotate_mode rot)
--{
--      u32 temp_rot = bitrev8(rot) >> 5;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
--
--int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
--                           const struct ipu_rgb *rgb)
--{
--      int bpp = 0, npb = 0, ro, go, bo, to;
--
--      ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
--      go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
--      bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
--      to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
--
--      if (rgb->transp.length) {
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
--                              rgb->transp.length - 1);
--              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
--      } else {
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
--              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
--                              rgb->bits_per_pixel);
--      }
--
--      switch (rgb->bits_per_pixel) {
--      case 32:
--              bpp = 0;
--              npb = 15;
--              break;
--      case 24:
--              bpp = 1;
--              npb = 19;
--              break;
--      case 16:
--              bpp = 3;
--              npb = 31;
--              break;
--      case 8:
--              bpp = 5;
--              npb = 63;
--              break;
--      default:
--              return -EINVAL;
--      }
--      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
--      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
--
--int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
--{
--      int bpp = 0, npb = 0;
--
--      switch (width) {
--      case 32:
--              bpp = 0;
--              npb = 15;
--              break;
--      case 24:
--              bpp = 1;
--              npb = 19;
--              break;
--      case 16:
--              bpp = 3;
--              npb = 31;
--              break;
--      case 8:
--              bpp = 5;
--              npb = 63;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
--      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
--
--void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
--{
--      switch (pixel_format) {
--      case V4L2_PIX_FMT_UYVY:
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
--              break;
--      case V4L2_PIX_FMT_YUYV:
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
--              break;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
--
--void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
--                                 unsigned int uv_stride,
--                                 unsigned int u_offset, unsigned int v_offset)
--{
--      WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
--      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
--
--static const struct ipu_rgb def_xrgb_32 = {
--      .red    = { .offset = 16, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset =  0, .length = 8, },
--      .transp = { .offset = 24, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_xbgr_32 = {
--      .red    = { .offset =  0, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset = 16, .length = 8, },
--      .transp = { .offset = 24, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_rgbx_32 = {
--      .red    = { .offset = 24, .length = 8, },
--      .green  = { .offset = 16, .length = 8, },
--      .blue   = { .offset =  8, .length = 8, },
--      .transp = { .offset =  0, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_bgrx_32 = {
--      .red    = { .offset =  8, .length = 8, },
--      .green  = { .offset = 16, .length = 8, },
--      .blue   = { .offset = 24, .length = 8, },
--      .transp = { .offset =  0, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_rgb_24 = {
--      .red    = { .offset = 16, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset =  0, .length = 8, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 24,
--};
--
--static const struct ipu_rgb def_bgr_24 = {
--      .red    = { .offset =  0, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset = 16, .length = 8, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 24,
--};
--
--static const struct ipu_rgb def_rgb_16 = {
--      .red    = { .offset = 11, .length = 5, },
--      .green  = { .offset =  5, .length = 6, },
--      .blue   = { .offset =  0, .length = 5, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_bgr_16 = {
--      .red    = { .offset =  0, .length = 5, },
--      .green  = { .offset =  5, .length = 6, },
--      .blue   = { .offset = 11, .length = 5, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_argb_16 = {
--      .red    = { .offset = 10, .length = 5, },
--      .green  = { .offset =  5, .length = 5, },
--      .blue   = { .offset =  0, .length = 5, },
--      .transp = { .offset = 15, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_argb_16_4444 = {
--      .red    = { .offset =  8, .length = 4, },
--      .green  = { .offset =  4, .length = 4, },
--      .blue   = { .offset =  0, .length = 4, },
--      .transp = { .offset = 12, .length = 4, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_abgr_16 = {
--      .red    = { .offset =  0, .length = 5, },
--      .green  = { .offset =  5, .length = 5, },
--      .blue   = { .offset = 10, .length = 5, },
--      .transp = { .offset = 15, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_rgba_16 = {
--      .red    = { .offset = 11, .length = 5, },
--      .green  = { .offset =  6, .length = 5, },
--      .blue   = { .offset =  1, .length = 5, },
--      .transp = { .offset =  0, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_bgra_16 = {
--      .red    = { .offset =  1, .length = 5, },
--      .green  = { .offset =  6, .length = 5, },
--      .blue   = { .offset = 11, .length = 5, },
--      .transp = { .offset =  0, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--#define Y_OFFSET(pix, x, y)   ((x) + pix->width * (y))
--#define U_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
--                               (pix->width * ((y) / 2) / 2) + (x) / 2)
--#define V_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
--                               (pix->width * pix->height / 4) +       \
--                               (pix->width * ((y) / 2) / 2) + (x) / 2)
--#define U2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
--                               (pix->width * (y) / 2) + (x) / 2)
--#define V2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
--                               (pix->width * pix->height / 2) +       \
--                               (pix->width * (y) / 2) + (x) / 2)
--#define UV_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
--                               (pix->width * ((y) / 2)) + (x))
--#define UV2_OFFSET(pix, x, y) ((pix->width * pix->height) +   \
--                               (pix->width * y) + (x))
--
--#define NUM_ALPHA_CHANNELS    7
--
--/* See Table 37-12. Alpha channels mapping. */
--static int ipu_channel_albm(int ch_num)
--{
--      switch (ch_num) {
--      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
--      case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
--      case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
--      case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
--      case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
--      case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
--      case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
--      default:
--              return -EINVAL;
--      }
--}
--
--static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
--{
--      struct ipu_soc *ipu = ch->ipu;
--      int albm;
--      u32 val;
--
--      albm = ipu_channel_albm(ch->num);
--      if (albm < 0)
--              return;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
--      ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
--
--      val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
--      val |= BIT(ch->num);
--      ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
--}
--
--int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
--{
--      switch (drm_fourcc) {
--      case DRM_FORMAT_YUV420:
--      case DRM_FORMAT_YVU420:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUV422:
--      case DRM_FORMAT_YVU422:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUV444:
--      case DRM_FORMAT_YVU444:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_NV12:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_NV16:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_UYVY:
--              /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUYV:
--              /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_ABGR8888:
--      case DRM_FORMAT_XBGR8888:
--              ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
--              break;
--      case DRM_FORMAT_ARGB8888:
--      case DRM_FORMAT_XRGB8888:
--              ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
--              break;
--      case DRM_FORMAT_RGBA8888:
--      case DRM_FORMAT_RGBX8888:
--      case DRM_FORMAT_RGBX8888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
--              break;
--      case DRM_FORMAT_BGRA8888:
--      case DRM_FORMAT_BGRX8888:
--      case DRM_FORMAT_BGRX8888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
--              break;
--      case DRM_FORMAT_BGR888:
--      case DRM_FORMAT_BGR888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
--              break;
--      case DRM_FORMAT_RGB888:
--      case DRM_FORMAT_RGB888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
--              break;
--      case DRM_FORMAT_RGB565:
--      case DRM_FORMAT_RGB565_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
--              break;
--      case DRM_FORMAT_BGR565:
--      case DRM_FORMAT_BGR565_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
--              break;
--      case DRM_FORMAT_ARGB1555:
--              ipu_cpmem_set_format_rgb(ch, &def_argb_16);
--              break;
--      case DRM_FORMAT_ABGR1555:
--              ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
--              break;
--      case DRM_FORMAT_RGBA5551:
--              ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
--              break;
--      case DRM_FORMAT_BGRA5551:
--              ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
--              break;
--      case DRM_FORMAT_ARGB4444:
--              ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      switch (drm_fourcc) {
--      case DRM_FORMAT_RGB565_A8:
--      case DRM_FORMAT_BGR565_A8:
--      case DRM_FORMAT_RGB888_A8:
--      case DRM_FORMAT_BGR888_A8:
--      case DRM_FORMAT_RGBX8888_A8:
--      case DRM_FORMAT_BGRX8888_A8:
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
--              ipu_cpmem_set_separate_alpha(ch);
--              break;
--      default:
--              break;
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
--
--int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
--{
--      struct v4l2_pix_format *pix = &image->pix;
--      int offset, u_offset, v_offset;
--      int ret = 0;
--
--      pr_debug("%s: resolution: %dx%d stride: %d\n",
--               __func__, pix->width, pix->height,
--               pix->bytesperline);
--
--      ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
--      ipu_cpmem_set_stride(ch, pix->bytesperline);
--
--      ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
--
--      switch (pix->pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : U_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : V_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_YVU420:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : V_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : U_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_YUV422P:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : U2_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : V2_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_NV12:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : UV_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--              v_offset = image->v_offset ? image->v_offset : 0;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_NV16:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : UV2_OFFSET(pix, image->rect.left,
--                                                   image->rect.top) - offset;
--              v_offset = image->v_offset ? image->v_offset : 0;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_UYVY:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_RGB565:
--              offset = image->rect.left * 2 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_RGB32:
--      case V4L2_PIX_FMT_BGR32:
--      case V4L2_PIX_FMT_ABGR32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_BGRA32:
--      case V4L2_PIX_FMT_BGRX32:
--      case V4L2_PIX_FMT_RGBA32:
--      case V4L2_PIX_FMT_RGBX32:
--      case V4L2_PIX_FMT_ARGB32:
--      case V4L2_PIX_FMT_XRGB32:
--              offset = image->rect.left * 4 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_RGB24:
--      case V4L2_PIX_FMT_BGR24:
--              offset = image->rect.left * 3 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_SBGGR8:
--      case V4L2_PIX_FMT_SGBRG8:
--      case V4L2_PIX_FMT_SGRBG8:
--      case V4L2_PIX_FMT_SRGGB8:
--      case V4L2_PIX_FMT_GREY:
--              offset = image->rect.left + image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_SBGGR16:
--      case V4L2_PIX_FMT_SGBRG16:
--      case V4L2_PIX_FMT_SGRBG16:
--      case V4L2_PIX_FMT_SRGGB16:
--      case V4L2_PIX_FMT_Y16:
--              offset = image->rect.left * 2 +
--                       image->rect.top * pix->bytesperline;
--              break;
--      default:
--              /* This should not happen */
--              WARN_ON(1);
--              offset = 0;
--              ret = -EINVAL;
--      }
--
--      ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
--      ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
--
--void ipu_cpmem_dump(struct ipuv3_channel *ch)
--{
--      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
--      struct ipu_soc *ipu = ch->ipu;
--      int chno = ch->num;
--
--      dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
--              readl(&p->word[0].data[0]),
--              readl(&p->word[0].data[1]),
--              readl(&p->word[0].data[2]),
--              readl(&p->word[0].data[3]),
--              readl(&p->word[0].data[4]));
--      dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
--              readl(&p->word[1].data[0]),
--              readl(&p->word[1].data[1]),
--              readl(&p->word[1].data[2]),
--              readl(&p->word[1].data[3]),
--              readl(&p->word[1].data[4]));
--      dev_dbg(ipu->dev, "PFS 0x%x, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
--      dev_dbg(ipu->dev, "BPP 0x%x, ",
--              ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
--      dev_dbg(ipu->dev, "NPB 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
--
--      dev_dbg(ipu->dev, "FW %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_FW));
--      dev_dbg(ipu->dev, "FH %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_FH));
--      dev_dbg(ipu->dev, "EBA0 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
--      dev_dbg(ipu->dev, "EBA1 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
--      dev_dbg(ipu->dev, "Stride %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SL));
--      dev_dbg(ipu->dev, "scan_order %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SO));
--      dev_dbg(ipu->dev, "uv_stride %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
--      dev_dbg(ipu->dev, "u_offset 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
--      dev_dbg(ipu->dev, "v_offset 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
--
--      dev_dbg(ipu->dev, "Width0 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
--      dev_dbg(ipu->dev, "Width1 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
--      dev_dbg(ipu->dev, "Width2 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
--      dev_dbg(ipu->dev, "Width3 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
--      dev_dbg(ipu->dev, "Offset0 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
--      dev_dbg(ipu->dev, "Offset1 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
--      dev_dbg(ipu->dev, "Offset2 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
--      dev_dbg(ipu->dev, "Offset3 %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
--
--int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
--{
--      struct ipu_cpmem *cpmem;
--
--      cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
--      if (!cpmem)
--              return -ENOMEM;
--
--      ipu->cpmem_priv = cpmem;
--
--      spin_lock_init(&cpmem->lock);
--      cpmem->base = devm_ioremap(dev, base, SZ_128K);
--      if (!cpmem->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
--              base, cpmem->base);
--      cpmem->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_cpmem_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-csi.c
-+++ /dev/null
-@@ -1,821 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2014 Mentor Graphics Inc.
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/delay.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/platform_device.h>
--#include <linux/videodev2.h>
--#include <uapi/linux/v4l2-mediabus.h>
--#include <linux/clk.h>
--#include <linux/clk-provider.h>
--#include <linux/clkdev.h>
--
--#include "ipu-prv.h"
--
--struct ipu_csi {
--      void __iomem *base;
--      int id;
--      u32 module;
--      struct clk *clk_ipu;    /* IPU bus clock */
--      spinlock_t lock;
--      bool inuse;
--      struct ipu_soc *ipu;
--};
--
--/* CSI Register Offsets */
--#define CSI_SENS_CONF         0x0000
--#define CSI_SENS_FRM_SIZE     0x0004
--#define CSI_ACT_FRM_SIZE      0x0008
--#define CSI_OUT_FRM_CTRL      0x000c
--#define CSI_TST_CTRL          0x0010
--#define CSI_CCIR_CODE_1               0x0014
--#define CSI_CCIR_CODE_2               0x0018
--#define CSI_CCIR_CODE_3               0x001c
--#define CSI_MIPI_DI           0x0020
--#define CSI_SKIP              0x0024
--#define CSI_CPD_CTRL          0x0028
--#define CSI_CPD_RC(n)         (0x002c + ((n)*4))
--#define CSI_CPD_RS(n)         (0x004c + ((n)*4))
--#define CSI_CPD_GRC(n)                (0x005c + ((n)*4))
--#define CSI_CPD_GRS(n)                (0x007c + ((n)*4))
--#define CSI_CPD_GBC(n)                (0x008c + ((n)*4))
--#define CSI_CPD_GBS(n)                (0x00Ac + ((n)*4))
--#define CSI_CPD_BC(n)         (0x00Bc + ((n)*4))
--#define CSI_CPD_BS(n)         (0x00Dc + ((n)*4))
--#define CSI_CPD_OFFSET1               0x00ec
--#define CSI_CPD_OFFSET2               0x00f0
--
--/* CSI Register Fields */
--#define CSI_SENS_CONF_DATA_FMT_SHIFT          8
--#define CSI_SENS_CONF_DATA_FMT_MASK           0x00000700
--#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444     0L
--#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV    1L
--#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY    2L
--#define CSI_SENS_CONF_DATA_FMT_BAYER          3L
--#define CSI_SENS_CONF_DATA_FMT_RGB565         4L
--#define CSI_SENS_CONF_DATA_FMT_RGB555         5L
--#define CSI_SENS_CONF_DATA_FMT_RGB444         6L
--#define CSI_SENS_CONF_DATA_FMT_JPEG           7L
--
--#define CSI_SENS_CONF_VSYNC_POL_SHIFT         0
--#define CSI_SENS_CONF_HSYNC_POL_SHIFT         1
--#define CSI_SENS_CONF_DATA_POL_SHIFT          2
--#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT               3
--#define CSI_SENS_CONF_SENS_PRTCL_MASK         0x00000070
--#define CSI_SENS_CONF_SENS_PRTCL_SHIFT                4
--#define CSI_SENS_CONF_PACK_TIGHT_SHIFT                7
--#define CSI_SENS_CONF_DATA_WIDTH_SHIFT                11
--#define CSI_SENS_CONF_EXT_VSYNC_SHIFT         15
--#define CSI_SENS_CONF_DIVRATIO_SHIFT          16
--
--#define CSI_SENS_CONF_DIVRATIO_MASK           0x00ff0000
--#define CSI_SENS_CONF_DATA_DEST_SHIFT         24
--#define CSI_SENS_CONF_DATA_DEST_MASK          0x07000000
--#define CSI_SENS_CONF_JPEG8_EN_SHIFT          27
--#define CSI_SENS_CONF_JPEG_EN_SHIFT           28
--#define CSI_SENS_CONF_FORCE_EOF_SHIFT         29
--#define CSI_SENS_CONF_DATA_EN_POL_SHIFT               31
--
--#define CSI_DATA_DEST_IC                      2
--#define CSI_DATA_DEST_IDMAC                   4
--
--#define CSI_CCIR_ERR_DET_EN                   0x01000000
--#define CSI_HORI_DOWNSIZE_EN                  0x80000000
--#define CSI_VERT_DOWNSIZE_EN                  0x40000000
--#define CSI_TEST_GEN_MODE_EN                  0x01000000
--
--#define CSI_HSC_MASK                          0x1fff0000
--#define CSI_HSC_SHIFT                         16
--#define CSI_VSC_MASK                          0x00000fff
--#define CSI_VSC_SHIFT                         0
--
--#define CSI_TEST_GEN_R_MASK                   0x000000ff
--#define CSI_TEST_GEN_R_SHIFT                  0
--#define CSI_TEST_GEN_G_MASK                   0x0000ff00
--#define CSI_TEST_GEN_G_SHIFT                  8
--#define CSI_TEST_GEN_B_MASK                   0x00ff0000
--#define CSI_TEST_GEN_B_SHIFT                  16
--
--#define CSI_MAX_RATIO_SKIP_SMFC_MASK          0x00000007
--#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT         0
--#define CSI_SKIP_SMFC_MASK                    0x000000f8
--#define CSI_SKIP_SMFC_SHIFT                   3
--#define CSI_ID_2_SKIP_MASK                    0x00000300
--#define CSI_ID_2_SKIP_SHIFT                   8
--
--#define CSI_COLOR_FIRST_ROW_MASK              0x00000002
--#define CSI_COLOR_FIRST_COMP_MASK             0x00000001
--
--/* MIPI CSI-2 data types */
--#define MIPI_DT_YUV420                0x18 /* YYY.../UYVY.... */
--#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY...   */
--#define MIPI_DT_YUV422                0x1e /* UYVY...         */
--#define MIPI_DT_RGB444                0x20
--#define MIPI_DT_RGB555                0x21
--#define MIPI_DT_RGB565                0x22
--#define MIPI_DT_RGB666                0x23
--#define MIPI_DT_RGB888                0x24
--#define MIPI_DT_RAW6          0x28
--#define MIPI_DT_RAW7          0x29
--#define MIPI_DT_RAW8          0x2a
--#define MIPI_DT_RAW10         0x2b
--#define MIPI_DT_RAW12         0x2c
--#define MIPI_DT_RAW14         0x2d
--
--/*
-- * Bitfield of CSI bus signal polarities and modes.
-- */
--struct ipu_csi_bus_config {
--      unsigned data_width:4;
--      unsigned clk_mode:3;
--      unsigned ext_vsync:1;
--      unsigned vsync_pol:1;
--      unsigned hsync_pol:1;
--      unsigned pixclk_pol:1;
--      unsigned data_pol:1;
--      unsigned sens_clksrc:1;
--      unsigned pack_tight:1;
--      unsigned force_eof:1;
--      unsigned data_en_pol:1;
--
--      unsigned data_fmt;
--      unsigned mipi_dt;
--};
--
--/*
-- * Enumeration of CSI data bus widths.
-- */
--enum ipu_csi_data_width {
--      IPU_CSI_DATA_WIDTH_4   = 0,
--      IPU_CSI_DATA_WIDTH_8   = 1,
--      IPU_CSI_DATA_WIDTH_10  = 3,
--      IPU_CSI_DATA_WIDTH_12  = 5,
--      IPU_CSI_DATA_WIDTH_16  = 9,
--};
--
--/*
-- * Enumeration of CSI clock modes.
-- */
--enum ipu_csi_clk_mode {
--      IPU_CSI_CLK_MODE_GATED_CLK,
--      IPU_CSI_CLK_MODE_NONGATED_CLK,
--      IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
--      IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
--      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
--      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
--      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
--      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
--};
--
--static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
--{
--      return readl(csi->base + offset);
--}
--
--static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
--                               unsigned offset)
--{
--      writel(value, csi->base + offset);
--}
--
--/*
-- * Set mclk division ratio for generating test mode mclk. Only used
-- * for test generator.
-- */
--static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
--                                      u32 ipu_clk)
--{
--      u32 temp;
--      int div_ratio;
--
--      div_ratio = (ipu_clk / pixel_clk) - 1;
--
--      if (div_ratio > 0xFF || div_ratio < 0) {
--              dev_err(csi->ipu->dev,
--                      "value of pixel_clk extends normal range\n");
--              return -EINVAL;
--      }
--
--      temp = ipu_csi_read(csi, CSI_SENS_CONF);
--      temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
--      ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
--                        CSI_SENS_CONF);
--
--      return 0;
--}
--
--/*
-- * Find the CSI data format and data width for the given V4L2 media
-- * bus pixel format code.
-- */
--static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
--                              enum v4l2_mbus_type mbus_type)
--{
--      switch (mbus_code) {
--      case MEDIA_BUS_FMT_BGR565_2X8_BE:
--      case MEDIA_BUS_FMT_BGR565_2X8_LE:
--      case MEDIA_BUS_FMT_RGB565_2X8_BE:
--      case MEDIA_BUS_FMT_RGB565_2X8_LE:
--              if (mbus_type == V4L2_MBUS_CSI2_DPHY)
--                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
--              else
--                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RGB565;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
--              cfg->mipi_dt = MIPI_DT_RGB444;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
--              cfg->mipi_dt = MIPI_DT_RGB555;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB888_1X24:
--      case MEDIA_BUS_FMT_BGR888_1X24:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
--              cfg->mipi_dt = MIPI_DT_RGB888;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_UYVY8_2X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_YUYV8_2X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_UYVY8_1X16:
--      case MEDIA_BUS_FMT_YUYV8_1X16:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_16;
--              break;
--      case MEDIA_BUS_FMT_SBGGR8_1X8:
--      case MEDIA_BUS_FMT_SGBRG8_1X8:
--      case MEDIA_BUS_FMT_SGRBG8_1X8:
--      case MEDIA_BUS_FMT_SRGGB8_1X8:
--      case MEDIA_BUS_FMT_Y8_1X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW8;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW10;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_SBGGR10_1X10:
--      case MEDIA_BUS_FMT_SGBRG10_1X10:
--      case MEDIA_BUS_FMT_SGRBG10_1X10:
--      case MEDIA_BUS_FMT_SRGGB10_1X10:
--      case MEDIA_BUS_FMT_Y10_1X10:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW10;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_10;
--              break;
--      case MEDIA_BUS_FMT_SBGGR12_1X12:
--      case MEDIA_BUS_FMT_SGBRG12_1X12:
--      case MEDIA_BUS_FMT_SGRBG12_1X12:
--      case MEDIA_BUS_FMT_SRGGB12_1X12:
--      case MEDIA_BUS_FMT_Y12_1X12:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW12;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_12;
--              break;
--      case MEDIA_BUS_FMT_JPEG_1X8:
--              /* TODO */
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
--              cfg->mipi_dt = MIPI_DT_RAW8;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      return 0;
--}
--
--/* translate alternate field mode based on given standard */
--static inline enum v4l2_field
--ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
--{
--      return (field != V4L2_FIELD_ALTERNATE) ? field :
--              ((std & V4L2_STD_525_60) ?
--               V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
--}
--
--/*
-- * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
-- */
--static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
--                          const struct v4l2_mbus_config *mbus_cfg,
--                          const struct v4l2_mbus_framefmt *mbus_fmt)
--{
--      int ret;
--
--      memset(csicfg, 0, sizeof(*csicfg));
--
--      ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
--      if (ret < 0)
--              return ret;
--
--      switch (mbus_cfg->type) {
--      case V4L2_MBUS_PARALLEL:
--              csicfg->ext_vsync = 1;
--              csicfg->vsync_pol = (mbus_cfg->flags &
--                                   V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
--              csicfg->hsync_pol = (mbus_cfg->flags &
--                                   V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
--              csicfg->pixclk_pol = (mbus_cfg->flags &
--                                    V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
--              csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
--              break;
--      case V4L2_MBUS_BT656:
--              csicfg->ext_vsync = 0;
--              if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
--                  mbus_fmt->field == V4L2_FIELD_ALTERNATE)
--                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
--              else
--                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
--              break;
--      case V4L2_MBUS_CSI2_DPHY:
--              /*
--               * MIPI CSI-2 requires non gated clock mode, all other
--               * parameters are not applicable for MIPI CSI-2 bus.
--               */
--              csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
--              break;
--      default:
--              /* will never get here, keep compiler quiet */
--              break;
--      }
--
--      return 0;
--}
--
--static int
--ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
--                              const struct v4l2_mbus_framefmt *infmt,
--                              const struct v4l2_mbus_framefmt *outfmt,
--                              v4l2_std_id std)
--{
--      enum v4l2_field infield, outfield;
--      bool swap_fields;
--
--      /* get translated field type of input and output */
--      infield = ipu_csi_translate_field(infmt->field, std);
--      outfield = ipu_csi_translate_field(outfmt->field, std);
--
--      /*
--       * Write the H-V-F codes the CSI will match against the
--       * incoming data for start/end of active and blanking
--       * field intervals. If input and output field types are
--       * sequential but not the same (one is SEQ_BT and the other
--       * is SEQ_TB), swap the F-bit so that the CSI will capture
--       * field 1 lines before field 0 lines.
--       */
--      swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
--                     V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
--                     infield != outfield);
--
--      if (!swap_fields) {
--              /*
--               * Field0BlankEnd  = 110, Field0BlankStart  = 010
--               * Field0ActiveEnd = 100, Field0ActiveStart = 000
--               * Field1BlankEnd  = 111, Field1BlankStart  = 011
--               * Field1ActiveEnd = 101, Field1ActiveStart = 001
--               */
--              ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
--                            CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
--      } else {
--              dev_dbg(csi->ipu->dev, "capture field swap\n");
--
--              /* same as above but with F-bit inverted */
--              ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
--                            CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
--      }
--
--      ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--
--      return 0;
--}
--
--
--int ipu_csi_init_interface(struct ipu_csi *csi,
--                         const struct v4l2_mbus_config *mbus_cfg,
--                         const struct v4l2_mbus_framefmt *infmt,
--                         const struct v4l2_mbus_framefmt *outfmt)
--{
--      struct ipu_csi_bus_config cfg;
--      unsigned long flags;
--      u32 width, height, data = 0;
--      v4l2_std_id std;
--      int ret;
--
--      ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
--      if (ret < 0)
--              return ret;
--
--      /* set default sensor frame width and height */
--      width = infmt->width;
--      height = infmt->height;
--      if (infmt->field == V4L2_FIELD_ALTERNATE)
--              height *= 2;
--
--      /* Set the CSI_SENS_CONF register remaining fields */
--      data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
--              cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
--              cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
--              cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
--              cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
--              cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
--              cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
--              cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
--              cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
--              cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
--              cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      ipu_csi_write(csi, data, CSI_SENS_CONF);
--
--      /* Set CCIR registers */
--
--      switch (cfg.clk_mode) {
--      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
--              ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--              break;
--      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
--              if (width == 720 && height == 480) {
--                      std = V4L2_STD_NTSC;
--                      height = 525;
--              } else if (width == 720 && height == 576) {
--                      std = V4L2_STD_PAL;
--                      height = 625;
--              } else {
--                      dev_err(csi->ipu->dev,
--                              "Unsupported interlaced video mode\n");
--                      ret = -EINVAL;
--                      goto out_unlock;
--              }
--
--              ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
--              if (ret)
--                      goto out_unlock;
--              break;
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
--              ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
--                                 CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--              break;
--      case IPU_CSI_CLK_MODE_GATED_CLK:
--      case IPU_CSI_CLK_MODE_NONGATED_CLK:
--              ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
--              break;
--      }
--
--      /* Setup sensor frame size */
--      ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
--                    CSI_SENS_FRM_SIZE);
--
--      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
--              ipu_csi_read(csi, CSI_SENS_CONF));
--      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
--              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
--
--out_unlock:
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
--
--bool ipu_csi_is_interlaced(struct ipu_csi *csi)
--{
--      unsigned long flags;
--      u32 sensor_protocol;
--
--      spin_lock_irqsave(&csi->lock, flags);
--      sensor_protocol =
--              (ipu_csi_read(csi, CSI_SENS_CONF) &
--               CSI_SENS_CONF_SENS_PRTCL_MASK) >>
--              CSI_SENS_CONF_SENS_PRTCL_SHIFT;
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      switch (sensor_protocol) {
--      case IPU_CSI_CLK_MODE_GATED_CLK:
--      case IPU_CSI_CLK_MODE_NONGATED_CLK:
--      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
--              return false;
--      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
--              return true;
--      default:
--              dev_err(csi->ipu->dev,
--                      "CSI %d sensor protocol unsupported\n", csi->id);
--              return false;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
--
--void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
--      w->width = (reg & 0xFFFF) + 1;
--      w->height = (reg >> 16 & 0xFFFF) + 1;
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
--      w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_get_window);
--
--void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
--                        CSI_ACT_FRM_SIZE);
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
--      reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
--      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_window);
--
--void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
--      reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
--             (vert ? CSI_VERT_DOWNSIZE_EN : 0);
--      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
--
--void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
--                              u32 r_value, u32 g_value, u32 b_value,
--                              u32 pix_clk)
--{
--      unsigned long flags;
--      u32 ipu_clk = clk_get_rate(csi->clk_ipu);
--      u32 temp;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_TST_CTRL);
--
--      if (!active) {
--              temp &= ~CSI_TEST_GEN_MODE_EN;
--              ipu_csi_write(csi, temp, CSI_TST_CTRL);
--      } else {
--              /* Set sensb_mclk div_ratio */
--              ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
--
--              temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
--                        CSI_TEST_GEN_B_MASK);
--              temp |= CSI_TEST_GEN_MODE_EN;
--              temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
--                      (g_value << CSI_TEST_GEN_G_SHIFT) |
--                      (b_value << CSI_TEST_GEN_B_SHIFT);
--              ipu_csi_write(csi, temp, CSI_TST_CTRL);
--      }
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
--
--int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
--                            struct v4l2_mbus_framefmt *mbus_fmt)
--{
--      struct ipu_csi_bus_config cfg;
--      unsigned long flags;
--      u32 temp;
--      int ret;
--
--      if (vc > 3)
--              return -EINVAL;
--
--      ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
--      if (ret < 0)
--              return ret;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_MIPI_DI);
--      temp &= ~(0xff << (vc * 8));
--      temp |= (cfg.mipi_dt << (vc * 8));
--      ipu_csi_write(csi, temp, CSI_MIPI_DI);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
--
--int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
--                        u32 max_ratio, u32 id)
--{
--      unsigned long flags;
--      u32 temp;
--
--      if (max_ratio > 5 || id > 3)
--              return -EINVAL;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_SKIP);
--      temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
--                CSI_SKIP_SMFC_MASK);
--      temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
--              (id << CSI_ID_2_SKIP_SHIFT) |
--              (skip << CSI_SKIP_SMFC_SHIFT);
--      ipu_csi_write(csi, temp, CSI_SKIP);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
--
--int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
--{
--      unsigned long flags;
--      u32 csi_sens_conf, dest;
--
--      if (csi_dest == IPU_CSI_DEST_IDMAC)
--              dest = CSI_DATA_DEST_IDMAC;
--      else
--              dest = CSI_DATA_DEST_IC; /* IC or VDIC */
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
--      csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
--      csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
--      ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
--
--int ipu_csi_enable(struct ipu_csi *csi)
--{
--      ipu_module_enable(csi->ipu, csi->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_enable);
--
--int ipu_csi_disable(struct ipu_csi *csi)
--{
--      ipu_module_disable(csi->ipu, csi->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_disable);
--
--struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
--{
--      unsigned long flags;
--      struct ipu_csi *csi, *ret;
--
--      if (id > 1)
--              return ERR_PTR(-EINVAL);
--
--      csi = ipu->csi_priv[id];
--      ret = csi;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      if (csi->inuse) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      csi->inuse = true;
--unlock:
--      spin_unlock_irqrestore(&csi->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_get);
--
--void ipu_csi_put(struct ipu_csi *csi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&csi->lock, flags);
--      csi->inuse = false;
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_put);
--
--int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
--               unsigned long base, u32 module, struct clk *clk_ipu)
--{
--      struct ipu_csi *csi;
--
--      if (id > 1)
--              return -ENODEV;
--
--      csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
--      if (!csi)
--              return -ENOMEM;
--
--      ipu->csi_priv[id] = csi;
--
--      spin_lock_init(&csi->lock);
--      csi->module = module;
--      csi->id = id;
--      csi->clk_ipu = clk_ipu;
--      csi->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!csi->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
--              id, base, csi->base);
--      csi->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_csi_exit(struct ipu_soc *ipu, int id)
--{
--}
--
--void ipu_csi_dump(struct ipu_csi *csi)
--{
--      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
--              ipu_csi_read(csi, CSI_SENS_CONF));
--      dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
--              ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
--      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
--              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
--      dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
--              ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
--      dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
--              ipu_csi_read(csi, CSI_TST_CTRL));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_1));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_2));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_3));
--      dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
--              ipu_csi_read(csi, CSI_MIPI_DI));
--      dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
--              ipu_csi_read(csi, CSI_SKIP));
--}
--EXPORT_SYMBOL_GPL(ipu_csi_dump);
---- a/drivers/gpu/ipu-v3/ipu-dc.c
-+++ /dev/null
-@@ -1,420 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/delay.h>
--#include <linux/interrupt.h>
--#include <linux/io.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DC_MAP_CONF_PTR(n)    (0x108 + ((n) & ~0x1) * 2)
--#define DC_MAP_CONF_VAL(n)    (0x144 + ((n) & ~0x1) * 2)
--
--#define DC_EVT_NF             0
--#define DC_EVT_NL             1
--#define DC_EVT_EOF            2
--#define DC_EVT_NFIELD         3
--#define DC_EVT_EOL            4
--#define DC_EVT_EOFIELD                5
--#define DC_EVT_NEW_ADDR               6
--#define DC_EVT_NEW_CHAN               7
--#define DC_EVT_NEW_DATA               8
--
--#define DC_EVT_NEW_ADDR_W_0   0
--#define DC_EVT_NEW_ADDR_W_1   1
--#define DC_EVT_NEW_CHAN_W_0   2
--#define DC_EVT_NEW_CHAN_W_1   3
--#define DC_EVT_NEW_DATA_W_0   4
--#define DC_EVT_NEW_DATA_W_1   5
--#define DC_EVT_NEW_ADDR_R_0   6
--#define DC_EVT_NEW_ADDR_R_1   7
--#define DC_EVT_NEW_CHAN_R_0   8
--#define DC_EVT_NEW_CHAN_R_1   9
--#define DC_EVT_NEW_DATA_R_0   10
--#define DC_EVT_NEW_DATA_R_1   11
--
--#define DC_WR_CH_CONF         0x0
--#define DC_WR_CH_ADDR         0x4
--#define DC_RL_CH(evt)         (8 + ((evt) & ~0x1) * 2)
--
--#define DC_GEN                        0xd4
--#define DC_DISP_CONF1(disp)   (0xd8 + (disp) * 4)
--#define DC_DISP_CONF2(disp)   (0xe8 + (disp) * 4)
--#define DC_STAT                       0x1c8
--
--#define WROD(lf)              (0x18 | ((lf) << 1))
--#define WRG                   0x01
--#define WCLK                  0xc9
--
--#define SYNC_WAVE 0
--#define NULL_WAVE (-1)
--
--#define DC_GEN_SYNC_1_6_SYNC  (2 << 1)
--#define DC_GEN_SYNC_PRIORITY_1        (1 << 7)
--
--#define DC_WR_CH_CONF_WORD_SIZE_8             (0 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_16            (1 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_24            (2 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_32            (3 << 0)
--#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)     (((i) & 0x1) << 3)
--#define DC_WR_CH_CONF_DISP_ID_SERIAL          (2 << 3)
--#define DC_WR_CH_CONF_DISP_ID_ASYNC           (3 << 4)
--#define DC_WR_CH_CONF_FIELD_MODE              (1 << 9)
--#define DC_WR_CH_CONF_PROG_TYPE_NORMAL                (4 << 5)
--#define DC_WR_CH_CONF_PROG_TYPE_MASK          (7 << 5)
--#define DC_WR_CH_CONF_PROG_DI_ID              (1 << 2)
--#define DC_WR_CH_CONF_PROG_DISP_ID(i)         (((i) & 0x1) << 3)
--
--#define IPU_DC_NUM_CHANNELS   10
--
--struct ipu_dc_priv;
--
--enum ipu_dc_map {
--      IPU_DC_MAP_RGB24,
--      IPU_DC_MAP_RGB565,
--      IPU_DC_MAP_GBR24, /* TVEv2 */
--      IPU_DC_MAP_BGR666,
--      IPU_DC_MAP_LVDS666,
--      IPU_DC_MAP_BGR24,
--};
--
--struct ipu_dc {
--      /* The display interface number assigned to this dc channel */
--      unsigned int            di;
--      void __iomem            *base;
--      struct ipu_dc_priv      *priv;
--      int                     chno;
--      bool                    in_use;
--};
--
--struct ipu_dc_priv {
--      void __iomem            *dc_reg;
--      void __iomem            *dc_tmpl_reg;
--      struct ipu_soc          *ipu;
--      struct device           *dev;
--      struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
--      struct mutex            mutex;
--      struct completion       comp;
--      int                     use_count;
--};
--
--static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
--{
--      u32 reg;
--
--      reg = readl(dc->base + DC_RL_CH(event));
--      reg &= ~(0xffff << (16 * (event & 0x1)));
--      reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
--      writel(reg, dc->base + DC_RL_CH(event));
--}
--
--static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
--              int map, int wave, int glue, int sync, int stop)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--      u32 reg1, reg2;
--
--      if (opcode == WCLK) {
--              reg1 = (operand << 20) & 0xfff00000;
--              reg2 = operand >> 12 | opcode << 1 | stop << 9;
--      } else if (opcode == WRG) {
--              reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
--              reg2 = operand >> 17 | opcode << 7 | stop << 9;
--      } else {
--              reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
--              reg2 = operand >> 12 | opcode << 4 | stop << 9;
--      }
--      writel(reg1, priv->dc_tmpl_reg + word * 8);
--      writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
--}
--
--static int ipu_bus_format_to_map(u32 fmt)
--{
--      switch (fmt) {
--      default:
--              WARN_ON(1);
--              /* fall-through */
--      case MEDIA_BUS_FMT_RGB888_1X24:
--              return IPU_DC_MAP_RGB24;
--      case MEDIA_BUS_FMT_RGB565_1X16:
--              return IPU_DC_MAP_RGB565;
--      case MEDIA_BUS_FMT_GBR888_1X24:
--              return IPU_DC_MAP_GBR24;
--      case MEDIA_BUS_FMT_RGB666_1X18:
--              return IPU_DC_MAP_BGR666;
--      case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
--              return IPU_DC_MAP_LVDS666;
--      case MEDIA_BUS_FMT_BGR888_1X24:
--              return IPU_DC_MAP_BGR24;
--      }
--}
--
--int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
--              u32 bus_format, u32 width)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--      int addr, sync;
--      u32 reg = 0;
--      int map;
--
--      dc->di = ipu_di_get_num(di);
--
--      map = ipu_bus_format_to_map(bus_format);
--
--      /*
--       * In interlaced mode we need more counters to create the asymmetric
--       * per-field VSYNC signals. The pixel active signal synchronising DC
--       * to DI moves to signal generator #6 (see ipu-di.c). In progressive
--       * mode counter #5 is used.
--       */
--      sync = interlaced ? 6 : 5;
--
--      /* Reserve 5 microcode template words for each DI */
--      if (dc->di)
--              addr = 5;
--      else
--              addr = 0;
--
--      if (interlaced) {
--              dc_link_event(dc, DC_EVT_NL, addr, 3);
--              dc_link_event(dc, DC_EVT_EOL, addr, 2);
--              dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
--
--              /* Init template microcode */
--              dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
--      } else {
--              dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
--              dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
--              dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
--
--              /* Init template microcode */
--              dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
--              dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
--              dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
--              dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
--      }
--
--      dc_link_event(dc, DC_EVT_NF, 0, 0);
--      dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
--      dc_link_event(dc, DC_EVT_EOF, 0, 0);
--      dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
--      dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
--      dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
--
--      reg = readl(dc->base + DC_WR_CH_CONF);
--      if (interlaced)
--              reg |= DC_WR_CH_CONF_FIELD_MODE;
--      else
--              reg &= ~DC_WR_CH_CONF_FIELD_MODE;
--      writel(reg, dc->base + DC_WR_CH_CONF);
--
--      writel(0x0, dc->base + DC_WR_CH_ADDR);
--      writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
--
--void ipu_dc_enable(struct ipu_soc *ipu)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_enable);
--
--void ipu_dc_enable_channel(struct ipu_dc *dc)
--{
--      u32 reg;
--
--      reg = readl(dc->base + DC_WR_CH_CONF);
--      reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
--      writel(reg, dc->base + DC_WR_CH_CONF);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
--
--void ipu_dc_disable_channel(struct ipu_dc *dc)
--{
--      u32 val;
--
--      val = readl(dc->base + DC_WR_CH_CONF);
--      val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
--      writel(val, dc->base + DC_WR_CH_CONF);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
--
--void ipu_dc_disable(struct ipu_soc *ipu)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_disable);
--
--static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
--              int byte_num, int offset, int mask)
--{
--      int ptr = map * 3 + byte_num;
--      u32 reg;
--
--      reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
--      reg &= ~(0xffff << (16 * (ptr & 0x1)));
--      reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
--      writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
--
--      reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
--      reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
--      reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
--      writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
--}
--
--static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
--{
--      u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
--
--      writel(reg & ~(0xffff << (16 * (map & 0x1))),
--                   priv->dc_reg + DC_MAP_CONF_PTR(map));
--}
--
--struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--      struct ipu_dc *dc;
--
--      if (channel >= IPU_DC_NUM_CHANNELS)
--              return ERR_PTR(-ENODEV);
--
--      dc = &priv->channels[channel];
--
--      mutex_lock(&priv->mutex);
--
--      if (dc->in_use) {
--              mutex_unlock(&priv->mutex);
--              return ERR_PTR(-EBUSY);
--      }
--
--      dc->in_use = true;
--
--      mutex_unlock(&priv->mutex);
--
--      return dc;
--}
--EXPORT_SYMBOL_GPL(ipu_dc_get);
--
--void ipu_dc_put(struct ipu_dc *dc)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--
--      mutex_lock(&priv->mutex);
--      dc->in_use = false;
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_put);
--
--int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long template_base)
--{
--      struct ipu_dc_priv *priv;
--      static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
--              0x78, 0, 0x94, 0xb4};
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      mutex_init(&priv->mutex);
--
--      priv->dev = dev;
--      priv->ipu = ipu;
--      priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
--      priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
--      if (!priv->dc_reg || !priv->dc_tmpl_reg)
--              return -ENOMEM;
--
--      for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
--              priv->channels[i].chno = i;
--              priv->channels[i].priv = priv;
--              priv->channels[i].base = priv->dc_reg + channel_offsets[i];
--      }
--
--      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
--                      DC_WR_CH_CONF_PROG_DI_ID,
--                      priv->channels[1].base + DC_WR_CH_CONF);
--      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
--                      priv->channels[5].base + DC_WR_CH_CONF);
--
--      writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
--              priv->dc_reg + DC_GEN);
--
--      ipu->dc_priv = priv;
--
--      dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
--                      base, template_base);
--
--      /* rgb24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
--
--      /* rgb565 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
--
--      /* gbr24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
--
--      /* bgr666 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
--
--      /* lvds666 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
--
--      /* bgr24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
--
--      return 0;
--}
--
--void ipu_dc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-di.c
-+++ /dev/null
-@@ -1,745 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/platform_device.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--struct ipu_di {
--      void __iomem *base;
--      int id;
--      u32 module;
--      struct clk *clk_di;     /* display input clock */
--      struct clk *clk_ipu;    /* IPU bus clock */
--      struct clk *clk_di_pixel; /* resulting pixel clock */
--      bool inuse;
--      struct ipu_soc *ipu;
--};
--
--static DEFINE_MUTEX(di_mutex);
--
--struct di_sync_config {
--      int run_count;
--      int run_src;
--      int offset_count;
--      int offset_src;
--      int repeat_count;
--      int cnt_clr_src;
--      int cnt_polarity_gen_en;
--      int cnt_polarity_clr_src;
--      int cnt_polarity_trigger_src;
--      int cnt_up;
--      int cnt_down;
--};
--
--enum di_pins {
--      DI_PIN11 = 0,
--      DI_PIN12 = 1,
--      DI_PIN13 = 2,
--      DI_PIN14 = 3,
--      DI_PIN15 = 4,
--      DI_PIN16 = 5,
--      DI_PIN17 = 6,
--      DI_PIN_CS = 7,
--
--      DI_PIN_SER_CLK = 0,
--      DI_PIN_SER_RS = 1,
--};
--
--enum di_sync_wave {
--      DI_SYNC_NONE = 0,
--      DI_SYNC_CLK = 1,
--      DI_SYNC_INT_HSYNC = 2,
--      DI_SYNC_HSYNC = 3,
--      DI_SYNC_VSYNC = 4,
--      DI_SYNC_DE = 6,
--
--      DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
--      DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
--      DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
--};
--
--#define SYNC_WAVE 0
--
--#define DI_GENERAL            0x0000
--#define DI_BS_CLKGEN0         0x0004
--#define DI_BS_CLKGEN1         0x0008
--#define DI_SW_GEN0(gen)               (0x000c + 4 * ((gen) - 1))
--#define DI_SW_GEN1(gen)               (0x0030 + 4 * ((gen) - 1))
--#define DI_STP_REP(gen)               (0x0148 + 4 * (((gen) - 1)/2))
--#define DI_SYNC_AS_GEN                0x0054
--#define DI_DW_GEN(gen)                (0x0058 + 4 * (gen))
--#define DI_DW_SET(gen, set)   (0x0088 + 4 * ((gen) + 0xc * (set)))
--#define DI_SER_CONF           0x015c
--#define DI_SSC                        0x0160
--#define DI_POL                        0x0164
--#define DI_AW0                        0x0168
--#define DI_AW1                        0x016c
--#define DI_SCR_CONF           0x0170
--#define DI_STAT                       0x0174
--
--#define DI_SW_GEN0_RUN_COUNT(x)                       ((x) << 19)
--#define DI_SW_GEN0_RUN_SRC(x)                 ((x) << 16)
--#define DI_SW_GEN0_OFFSET_COUNT(x)            ((x) << 3)
--#define DI_SW_GEN0_OFFSET_SRC(x)              ((x) << 0)
--
--#define DI_SW_GEN1_CNT_POL_GEN_EN(x)          ((x) << 29)
--#define DI_SW_GEN1_CNT_CLR_SRC(x)             ((x) << 25)
--#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)     ((x) << 12)
--#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)         ((x) << 9)
--#define DI_SW_GEN1_CNT_DOWN(x)                        ((x) << 16)
--#define DI_SW_GEN1_CNT_UP(x)                  (x)
--#define DI_SW_GEN1_AUTO_RELOAD                        (0x10000000)
--
--#define DI_DW_GEN_ACCESS_SIZE_OFFSET          24
--#define DI_DW_GEN_COMPONENT_SIZE_OFFSET               16
--
--#define DI_GEN_POLARITY_1                     (1 << 0)
--#define DI_GEN_POLARITY_2                     (1 << 1)
--#define DI_GEN_POLARITY_3                     (1 << 2)
--#define DI_GEN_POLARITY_4                     (1 << 3)
--#define DI_GEN_POLARITY_5                     (1 << 4)
--#define DI_GEN_POLARITY_6                     (1 << 5)
--#define DI_GEN_POLARITY_7                     (1 << 6)
--#define DI_GEN_POLARITY_8                     (1 << 7)
--#define DI_GEN_POLARITY_DISP_CLK              (1 << 17)
--#define DI_GEN_DI_CLK_EXT                     (1 << 20)
--#define DI_GEN_DI_VSYNC_EXT                   (1 << 21)
--
--#define DI_POL_DRDY_DATA_POLARITY             (1 << 7)
--#define DI_POL_DRDY_POLARITY_15                       (1 << 4)
--
--#define DI_VSYNC_SEL_OFFSET                   13
--
--static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
--{
--      return readl(di->base + offset);
--}
--
--static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
--{
--      writel(value, di->base + offset);
--}
--
--static void ipu_di_data_wave_config(struct ipu_di *di,
--                                   int wave_gen,
--                                   int access_size, int component_size)
--{
--      u32 reg;
--      reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
--          (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
--      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
--}
--
--static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
--              int set, int up, int down)
--{
--      u32 reg;
--
--      reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
--      reg &= ~(0x3 << (di_pin * 2));
--      reg |= set << (di_pin * 2);
--      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
--
--      ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
--}
--
--static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
--              int start, int count)
--{
--      u32 reg;
--      int i;
--
--      for (i = 0; i < count; i++) {
--              struct di_sync_config *c = &config[i];
--              int wave_gen = start + i + 1;
--
--              if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
--                              (c->repeat_count >= 0x1000) ||
--                              (c->cnt_up >= 0x400) ||
--                              (c->cnt_down >= 0x400)) {
--                      dev_err(di->ipu->dev, "DI%d counters out of range.\n",
--                                      di->id);
--                      return;
--              }
--
--              reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
--                      DI_SW_GEN0_RUN_SRC(c->run_src) |
--                      DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
--                      DI_SW_GEN0_OFFSET_SRC(c->offset_src);
--              ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
--
--              reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
--                      DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
--                      DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
--                                      c->cnt_polarity_trigger_src) |
--                      DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
--                      DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
--                      DI_SW_GEN1_CNT_UP(c->cnt_up);
--
--              /* Enable auto reload */
--              if (c->repeat_count == 0)
--                      reg |= DI_SW_GEN1_AUTO_RELOAD;
--
--              ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
--
--              reg = ipu_di_read(di, DI_STP_REP(wave_gen));
--              reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
--              reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
--              ipu_di_write(di, reg, DI_STP_REP(wave_gen));
--      }
--}
--
--static void ipu_di_sync_config_interlaced(struct ipu_di *di,
--              struct ipu_di_signal_cfg *sig)
--{
--      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
--              sig->mode.hback_porch + sig->mode.hfront_porch;
--      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
--              sig->mode.vback_porch + sig->mode.vfront_porch;
--      struct di_sync_config cfg[] = {
--              {
--                      /* 1: internal VSYNC for each frame */
--                      .run_count = v_total * 2 - 1,
--                      .run_src = 3,                   /* == counter 7 */
--              }, {
--                      /* PIN2: HSYNC waveform */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              }, {
--                      /* PIN3: VSYNC waveform */
--                      .run_count = v_total - 1,
--                      .run_src = 4,                   /* == counter 7 */
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = 4,  /* == counter 7 */
--                      .cnt_down = sig->mode.vsync_len * 2,
--                      .cnt_clr_src = DI_SYNC_CNT1,
--              }, {
--                      /* 4: Field */
--                      .run_count = v_total / 2,
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = h_total / 2,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = 2,
--                      .cnt_clr_src = DI_SYNC_CNT1,
--              }, {
--                      /* 5: Active lines */
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = (sig->mode.vsync_len +
--                                       sig->mode.vback_porch) / 2,
--                      .offset_src = DI_SYNC_HSYNC,
--                      .repeat_count = sig->mode.vactive / 2,
--                      .cnt_clr_src = DI_SYNC_CNT4,
--              }, {
--                      /* 6: Active pixel, referenced by DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = DI_SYNC_CNT5,
--              }, {
--                      /* 7: Half line HSYNC */
--                      .run_count = h_total / 2 - 1,
--                      .run_src = DI_SYNC_CLK,
--              }
--      };
--
--      ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
--
--      ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
--}
--
--static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
--              struct ipu_di_signal_cfg *sig, int div)
--{
--      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
--              sig->mode.hback_porch + sig->mode.hfront_porch;
--      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
--              sig->mode.vback_porch + sig->mode.vfront_porch;
--      struct di_sync_config cfg[] = {
--              {
--                      /* 1: INT_HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--              } , {
--                      /* PIN2: HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync,
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* PIN3: VSYNC */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* 4: Line Active */
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = sig->mode.vsync_len +
--                                      sig->mode.vback_porch,
--                      .offset_src = DI_SYNC_HSYNC,
--                      .repeat_count = sig->mode.vactive,
--                      .cnt_clr_src = DI_SYNC_VSYNC,
--              } , {
--                      /* 5: Pixel Active, referenced by DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = 5, /* Line Active */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              },
--      };
--      /* can't use #7 and #8 for line active and pixel active counters */
--      struct di_sync_config cfg_vga[] = {
--              {
--                      /* 1: INT_HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--              } , {
--                      /* 2: VSYNC */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--              } , {
--                      /* 3: Line Active */
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = sig->mode.vsync_len +
--                                      sig->mode.vback_porch,
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .repeat_count = sig->mode.vactive,
--                      .cnt_clr_src = 3 /* VSYNC */,
--              } , {
--                      /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* 5: Pixel Active signal to DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = 4, /* Line Active */
--              } , {
--                      /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = 1, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = 1, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* unused */
--              },
--      };
--
--      ipu_di_write(di, v_total - 1, DI_SCR_CONF);
--      if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
--              ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
--      else
--              ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
--}
--
--static void ipu_di_config_clock(struct ipu_di *di,
--      const struct ipu_di_signal_cfg *sig)
--{
--      struct clk *clk;
--      unsigned clkgen0;
--      uint32_t val;
--
--      if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
--              /*
--               * CLKMODE_EXT means we must use the DI clock: this is
--               * needed for things like LVDS which needs to feed the
--               * DI and LDB with the same pixel clock.
--               */
--              clk = di->clk_di;
--
--              if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
--                      /*
--                       * CLKMODE_SYNC means that we want the DI to be
--                       * clocked at the same rate as the parent clock.
--                       * This is needed (eg) for LDB which needs to be
--                       * fed with the same pixel clock.  We assume that
--                       * the LDB clock has already been set correctly.
--                       */
--                      clkgen0 = 1 << 4;
--              } else {
--                      /*
--                       * We can use the divider.  We should really have
--                       * a flag here indicating whether the bridge can
--                       * cope with a fractional divider or not.  For the
--                       * time being, let's go for simplicitly and
--                       * reliability.
--                       */
--                      unsigned long in_rate;
--                      unsigned div;
--
--                      clk_set_rate(clk, sig->mode.pixelclock);
--
--                      in_rate = clk_get_rate(clk);
--                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
--                      div = clamp(div, 1U, 255U);
--
--                      clkgen0 = div << 4;
--              }
--      } else {
--              /*
--               * For other interfaces, we can arbitarily select between
--               * the DI specific clock and the internal IPU clock.  See
--               * DI_GENERAL bit 20.  We select the IPU clock if it can
--               * give us a clock rate within 1% of the requested frequency,
--               * otherwise we use the DI clock.
--               */
--              unsigned long rate, clkrate;
--              unsigned div, error;
--
--              clkrate = clk_get_rate(di->clk_ipu);
--              div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
--              div = clamp(div, 1U, 255U);
--              rate = clkrate / div;
--
--              error = rate / (sig->mode.pixelclock / 1000);
--
--              dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
--                      rate, div, (signed)(error - 1000) / 10, error % 10);
--
--              /* Allow a 1% error */
--              if (error < 1010 && error >= 990) {
--                      clk = di->clk_ipu;
--
--                      clkgen0 = div << 4;
--              } else {
--                      unsigned long in_rate;
--                      unsigned div;
--
--                      clk = di->clk_di;
--
--                      clk_set_rate(clk, sig->mode.pixelclock);
--
--                      in_rate = clk_get_rate(clk);
--                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
--                      div = clamp(div, 1U, 255U);
--
--                      clkgen0 = div << 4;
--              }
--      }
--
--      di->clk_di_pixel = clk;
--
--      /* Set the divider */
--      ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
--
--      /*
--       * Set the high/low periods.  Bits 24:16 give us the falling edge,
--       * and bits 8:0 give the rising edge.  LSB is fraction, and is
--       * based on the divider above.  We want a 50% duty cycle, so set
--       * the falling edge to be half the divider.
--       */
--      ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
--
--      /* Finally select the input clock */
--      val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
--      if (clk == di->clk_di)
--              val |= DI_GEN_DI_CLK_EXT;
--      ipu_di_write(di, val, DI_GENERAL);
--
--      dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
--              sig->mode.pixelclock,
--              clk_get_rate(di->clk_ipu),
--              clk_get_rate(di->clk_di),
--              clk == di->clk_di ? "DI" : "IPU",
--              clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
--}
--
--/*
-- * This function is called to adjust a video mode to IPU restrictions.
-- * It is meant to be called from drm crtc mode_fixup() methods.
-- */
--int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
--{
--      u32 diff;
--
--      if (mode->vfront_porch >= 2)
--              return 0;
--
--      diff = 2 - mode->vfront_porch;
--
--      if (mode->vback_porch >= diff) {
--              mode->vfront_porch = 2;
--              mode->vback_porch -= diff;
--      } else if (mode->vsync_len > diff) {
--              mode->vfront_porch = 2;
--              mode->vsync_len = mode->vsync_len - diff;
--      } else {
--              dev_warn(di->ipu->dev, "failed to adjust videomode\n");
--              return -EINVAL;
--      }
--
--      dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
--
--static u32 ipu_di_gen_polarity(int pin)
--{
--      switch (pin) {
--      case 1:
--              return DI_GEN_POLARITY_1;
--      case 2:
--              return DI_GEN_POLARITY_2;
--      case 3:
--              return DI_GEN_POLARITY_3;
--      case 4:
--              return DI_GEN_POLARITY_4;
--      case 5:
--              return DI_GEN_POLARITY_5;
--      case 6:
--              return DI_GEN_POLARITY_6;
--      case 7:
--              return DI_GEN_POLARITY_7;
--      case 8:
--              return DI_GEN_POLARITY_8;
--      }
--      return 0;
--}
--
--int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
--{
--      u32 reg;
--      u32 di_gen, vsync_cnt;
--      u32 div;
--
--      dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
--              di->id, sig->mode.hactive, sig->mode.vactive);
--
--      dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
--              clk_get_rate(di->clk_ipu),
--              clk_get_rate(di->clk_di),
--              sig->mode.pixelclock);
--
--      mutex_lock(&di_mutex);
--
--      ipu_di_config_clock(di, sig);
--
--      div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
--      div = div / 16;         /* Now divider is integer portion */
--
--      /* Setup pixel clock timing */
--      /* Down time is half of period */
--      ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
--
--      ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
--      ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
--
--      di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
--      di_gen |= DI_GEN_DI_VSYNC_EXT;
--
--      if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
--              ipu_di_sync_config_interlaced(di, sig);
--
--              /* set y_sel = 1 */
--              di_gen |= 0x10000000;
--
--              vsync_cnt = 3;
--      } else {
--              ipu_di_sync_config_noninterlaced(di, sig, div);
--
--              vsync_cnt = 3;
--              if (di->id == 1)
--                      /*
--                       * TODO: change only for TVEv2, parallel display
--                       * uses pin 2 / 3
--                       */
--                      if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
--                              vsync_cnt = 6;
--      }
--
--      if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
--              di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
--      if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
--              di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
--
--      if (sig->clk_pol)
--              di_gen |= DI_GEN_POLARITY_DISP_CLK;
--
--      ipu_di_write(di, di_gen, DI_GENERAL);
--
--      ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
--                   DI_SYNC_AS_GEN);
--
--      reg = ipu_di_read(di, DI_POL);
--      reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
--
--      if (sig->enable_pol)
--              reg |= DI_POL_DRDY_POLARITY_15;
--      if (sig->data_pol)
--              reg |= DI_POL_DRDY_DATA_POLARITY;
--
--      ipu_di_write(di, reg, DI_POL);
--
--      mutex_unlock(&di_mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
--
--int ipu_di_enable(struct ipu_di *di)
--{
--      int ret;
--
--      WARN_ON(IS_ERR(di->clk_di_pixel));
--
--      ret = clk_prepare_enable(di->clk_di_pixel);
--      if (ret)
--              return ret;
--
--      ipu_module_enable(di->ipu, di->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_enable);
--
--int ipu_di_disable(struct ipu_di *di)
--{
--      WARN_ON(IS_ERR(di->clk_di_pixel));
--
--      ipu_module_disable(di->ipu, di->module);
--
--      clk_disable_unprepare(di->clk_di_pixel);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_disable);
--
--int ipu_di_get_num(struct ipu_di *di)
--{
--      return di->id;
--}
--EXPORT_SYMBOL_GPL(ipu_di_get_num);
--
--static DEFINE_MUTEX(ipu_di_lock);
--
--struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
--{
--      struct ipu_di *di;
--
--      if (disp > 1)
--              return ERR_PTR(-EINVAL);
--
--      di = ipu->di_priv[disp];
--
--      mutex_lock(&ipu_di_lock);
--
--      if (di->inuse) {
--              di = ERR_PTR(-EBUSY);
--              goto out;
--      }
--
--      di->inuse = true;
--out:
--      mutex_unlock(&ipu_di_lock);
--
--      return di;
--}
--EXPORT_SYMBOL_GPL(ipu_di_get);
--
--void ipu_di_put(struct ipu_di *di)
--{
--      mutex_lock(&ipu_di_lock);
--
--      di->inuse = false;
--
--      mutex_unlock(&ipu_di_lock);
--}
--EXPORT_SYMBOL_GPL(ipu_di_put);
--
--int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
--              unsigned long base,
--              u32 module, struct clk *clk_ipu)
--{
--      struct ipu_di *di;
--
--      if (id > 1)
--              return -ENODEV;
--
--      di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
--      if (!di)
--              return -ENOMEM;
--
--      ipu->di_priv[id] = di;
--
--      di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
--      if (IS_ERR(di->clk_di))
--              return PTR_ERR(di->clk_di);
--
--      di->module = module;
--      di->id = id;
--      di->clk_ipu = clk_ipu;
--      di->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!di->base)
--              return -ENOMEM;
--
--      ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
--
--      dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
--                      id, base, di->base);
--      di->inuse = false;
--      di->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_di_exit(struct ipu_soc *ipu, int id)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-dmfc.c
-+++ /dev/null
-@@ -1,214 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DMFC_RD_CHAN          0x0000
--#define DMFC_WR_CHAN          0x0004
--#define DMFC_WR_CHAN_DEF      0x0008
--#define DMFC_DP_CHAN          0x000c
--#define DMFC_DP_CHAN_DEF      0x0010
--#define DMFC_GENERAL1         0x0014
--#define DMFC_GENERAL2         0x0018
--#define DMFC_IC_CTRL          0x001c
--#define DMFC_WR_CHAN_ALT      0x0020
--#define DMFC_WR_CHAN_DEF_ALT  0x0024
--#define DMFC_DP_CHAN_ALT      0x0028
--#define DMFC_DP_CHAN_DEF_ALT  0x002c
--#define DMFC_GENERAL1_ALT     0x0030
--#define DMFC_STAT             0x0034
--
--#define DMFC_WR_CHAN_1_28             0
--#define DMFC_WR_CHAN_2_41             8
--#define DMFC_WR_CHAN_1C_42            16
--#define DMFC_WR_CHAN_2C_43            24
--
--#define DMFC_DP_CHAN_5B_23            0
--#define DMFC_DP_CHAN_5F_27            8
--#define DMFC_DP_CHAN_6B_24            16
--#define DMFC_DP_CHAN_6F_29            24
--
--struct dmfc_channel_data {
--      int             ipu_channel;
--      unsigned long   channel_reg;
--      unsigned long   shift;
--      unsigned        eot_shift;
--      unsigned        max_fifo_lines;
--};
--
--static const struct dmfc_channel_data dmfcdata[] = {
--      {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_5B_23,
--              .eot_shift      = 20,
--              .max_fifo_lines = 3,
--      }, {
--              .ipu_channel    = 24,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_6B_24,
--              .eot_shift      = 22,
--              .max_fifo_lines = 1,
--      }, {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_5F_27,
--              .eot_shift      = 21,
--              .max_fifo_lines = 2,
--      }, {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
--              .channel_reg    = DMFC_WR_CHAN,
--              .shift          = DMFC_WR_CHAN_1_28,
--              .eot_shift      = 16,
--              .max_fifo_lines = 2,
--      }, {
--              .ipu_channel    = 29,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_6F_29,
--              .eot_shift      = 23,
--              .max_fifo_lines = 1,
--      },
--};
--
--#define DMFC_NUM_CHANNELS     ARRAY_SIZE(dmfcdata)
--
--struct ipu_dmfc_priv;
--
--struct dmfc_channel {
--      unsigned                        slots;
--      struct ipu_soc                  *ipu;
--      struct ipu_dmfc_priv            *priv;
--      const struct dmfc_channel_data  *data;
--};
--
--struct ipu_dmfc_priv {
--      struct ipu_soc *ipu;
--      struct device *dev;
--      struct dmfc_channel channels[DMFC_NUM_CHANNELS];
--      struct mutex mutex;
--      void __iomem *base;
--      int use_count;
--};
--
--int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
--
--void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
--
--void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--      u32 dmfc_gen1;
--
--      mutex_lock(&priv->mutex);
--
--      dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
--
--      if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
--              dmfc_gen1 |= 1 << dmfc->data->eot_shift;
--      else
--              dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
--
--      writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
--
--struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
--{
--      struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
--      int i;
--
--      for (i = 0; i < DMFC_NUM_CHANNELS; i++)
--              if (dmfcdata[i].ipu_channel == ipu_channel)
--                      return &priv->channels[i];
--      return ERR_PTR(-ENODEV);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_get);
--
--void ipu_dmfc_put(struct dmfc_channel *dmfc)
--{
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_put);
--
--int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              struct clk *ipu_clk)
--{
--      struct ipu_dmfc_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      priv->dev = dev;
--      priv->ipu = ipu;
--      mutex_init(&priv->mutex);
--
--      ipu->dmfc_priv = priv;
--
--      for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
--              priv->channels[i].priv = priv;
--              priv->channels[i].ipu = ipu;
--              priv->channels[i].data = &dmfcdata[i];
--
--              if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
--                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
--                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
--                      priv->channels[i].slots = 2;
--      }
--
--      writel(0x00000050, priv->base + DMFC_WR_CHAN);
--      writel(0x00005654, priv->base + DMFC_DP_CHAN);
--      writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
--      writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
--      writel(0x00000003, priv->base + DMFC_GENERAL1);
--
--      return 0;
--}
--
--void ipu_dmfc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-dp.c
-+++ /dev/null
-@@ -1,357 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/kernel.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--#include <linux/err.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DP_SYNC 0
--#define DP_ASYNC0 0x60
--#define DP_ASYNC1 0xBC
--
--#define DP_COM_CONF           0x0
--#define DP_GRAPH_WIND_CTRL    0x0004
--#define DP_FG_POS             0x0008
--#define DP_CSC_A_0            0x0044
--#define DP_CSC_A_1            0x0048
--#define DP_CSC_A_2            0x004C
--#define DP_CSC_A_3            0x0050
--#define DP_CSC_0              0x0054
--#define DP_CSC_1              0x0058
--
--#define DP_COM_CONF_FG_EN             (1 << 0)
--#define DP_COM_CONF_GWSEL             (1 << 1)
--#define DP_COM_CONF_GWAM              (1 << 2)
--#define DP_COM_CONF_GWCKE             (1 << 3)
--#define DP_COM_CONF_CSC_DEF_MASK      (3 << 8)
--#define DP_COM_CONF_CSC_DEF_OFFSET    8
--#define DP_COM_CONF_CSC_DEF_FG                (3 << 8)
--#define DP_COM_CONF_CSC_DEF_BG                (2 << 8)
--#define DP_COM_CONF_CSC_DEF_BOTH      (1 << 8)
--
--#define IPUV3_NUM_FLOWS               3
--
--struct ipu_dp_priv;
--
--struct ipu_dp {
--      u32 flow;
--      bool in_use;
--      bool foreground;
--      enum ipu_color_space in_cs;
--};
--
--struct ipu_flow {
--      struct ipu_dp foreground;
--      struct ipu_dp background;
--      enum ipu_color_space out_cs;
--      void __iomem *base;
--      struct ipu_dp_priv *priv;
--};
--
--struct ipu_dp_priv {
--      struct ipu_soc *ipu;
--      struct device *dev;
--      void __iomem *base;
--      struct ipu_flow flow[IPUV3_NUM_FLOWS];
--      struct mutex mutex;
--      int use_count;
--};
--
--static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
--
--static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
--{
--      if (dp->foreground)
--              return container_of(dp, struct ipu_flow, foreground);
--      else
--              return container_of(dp, struct ipu_flow, background);
--}
--
--int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
--              u8 alpha, bool bg_chan)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      if (bg_chan)
--              reg &= ~DP_COM_CONF_GWSEL;
--      else
--              reg |= DP_COM_CONF_GWSEL;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      if (enable) {
--              reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
--              writel(reg | ((u32) alpha << 24),
--                           flow->base + DP_GRAPH_WIND_CTRL);
--
--              reg = readl(flow->base + DP_COM_CONF);
--              writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
--      } else {
--              reg = readl(flow->base + DP_COM_CONF);
--              writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
--      }
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
--
--int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--
--      writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
--
--static void ipu_dp_csc_init(struct ipu_flow *flow,
--              enum ipu_color_space in,
--              enum ipu_color_space out,
--              u32 place)
--{
--      u32 reg;
--
--      reg = readl(flow->base + DP_COM_CONF);
--      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
--
--      if (in == out) {
--              writel(reg, flow->base + DP_COM_CONF);
--              return;
--      }
--
--      if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
--              writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
--              writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
--              writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
--              writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
--              writel(0x3d6 | (0x0000 << 16) | (2 << 30),
--                              flow->base + DP_CSC_0);
--              writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
--                              flow->base + DP_CSC_1);
--      } else {
--              writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
--              writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
--              writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
--              writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
--              writel(0x000 | (0x3e42 << 16) | (1 << 30),
--                              flow->base + DP_CSC_0);
--              writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
--                              flow->base + DP_CSC_1);
--      }
--
--      reg |= place;
--
--      writel(reg, flow->base + DP_COM_CONF);
--}
--
--int ipu_dp_setup_channel(struct ipu_dp *dp,
--              enum ipu_color_space in,
--              enum ipu_color_space out)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--
--      mutex_lock(&priv->mutex);
--
--      dp->in_cs = in;
--
--      if (!dp->foreground)
--              flow->out_cs = out;
--
--      if (flow->foreground.in_cs == flow->background.in_cs) {
--              /*
--               * foreground and background are of same colorspace, put
--               * colorspace converter after combining unit.
--               */
--              ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
--                              DP_COM_CONF_CSC_DEF_BOTH);
--      } else {
--              if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
--                  flow->foreground.in_cs == flow->out_cs)
--                      /*
--                       * foreground identical to output, apply color
--                       * conversion on background
--                       */
--                      ipu_dp_csc_init(flow, flow->background.in_cs,
--                                      flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
--              else
--                      ipu_dp_csc_init(flow, flow->foreground.in_cs,
--                                      flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
--      }
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
--
--int ipu_dp_enable(struct ipu_soc *ipu)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_enable);
--
--int ipu_dp_enable_channel(struct ipu_dp *dp)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg;
--
--      if (!dp->foreground)
--              return 0;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      reg |= DP_COM_CONF_FG_EN;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
--
--void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg, csc;
--
--      dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
--
--      if (!dp->foreground)
--              return;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      csc = reg & DP_COM_CONF_CSC_DEF_MASK;
--      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
--      if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
--              reg |= DP_COM_CONF_CSC_DEF_BG;
--
--      reg &= ~DP_COM_CONF_FG_EN;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      writel(0, flow->base + DP_FG_POS);
--      ipu_srm_dp_update(priv->ipu, sync);
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
--
--void ipu_dp_disable(struct ipu_soc *ipu)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dp_disable);
--
--struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--      struct ipu_dp *dp;
--
--      if ((flow >> 1) >= IPUV3_NUM_FLOWS)
--              return ERR_PTR(-EINVAL);
--
--      if (flow & 1)
--              dp = &priv->flow[flow >> 1].foreground;
--      else
--              dp = &priv->flow[flow >> 1].background;
--
--      if (dp->in_use)
--              return ERR_PTR(-EBUSY);
--
--      dp->in_use = true;
--
--      return dp;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_get);
--
--void ipu_dp_put(struct ipu_dp *dp)
--{
--      dp->in_use = false;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_put);
--
--int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
--{
--      struct ipu_dp_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--      priv->dev = dev;
--      priv->ipu = ipu;
--
--      ipu->dp_priv = priv;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      mutex_init(&priv->mutex);
--
--      for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
--              priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
--              priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
--              priv->flow[i].foreground.foreground = true;
--              priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
--              priv->flow[i].priv = priv;
--      }
--
--      return 0;
--}
--
--void ipu_dp_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-ic.c
-+++ /dev/null
-@@ -1,761 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2014 Mentor Graphics Inc.
-- * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--
--#include <linux/types.h>
--#include <linux/init.h>
--#include <linux/errno.h>
--#include <linux/spinlock.h>
--#include <linux/bitrev.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/sizes.h>
--#include "ipu-prv.h"
--
--/* IC Register Offsets */
--#define IC_CONF                 0x0000
--#define IC_PRP_ENC_RSC          0x0004
--#define IC_PRP_VF_RSC           0x0008
--#define IC_PP_RSC               0x000C
--#define IC_CMBP_1               0x0010
--#define IC_CMBP_2               0x0014
--#define IC_IDMAC_1              0x0018
--#define IC_IDMAC_2              0x001C
--#define IC_IDMAC_3              0x0020
--#define IC_IDMAC_4              0x0024
--
--/* IC Register Fields */
--#define IC_CONF_PRPENC_EN       (1 << 0)
--#define IC_CONF_PRPENC_CSC1     (1 << 1)
--#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
--#define IC_CONF_PRPVF_EN        (1 << 8)
--#define IC_CONF_PRPVF_CSC1      (1 << 9)
--#define IC_CONF_PRPVF_CSC2      (1 << 10)
--#define IC_CONF_PRPVF_CMB       (1 << 11)
--#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
--#define IC_CONF_PP_EN           (1 << 16)
--#define IC_CONF_PP_CSC1         (1 << 17)
--#define IC_CONF_PP_CSC2         (1 << 18)
--#define IC_CONF_PP_CMB          (1 << 19)
--#define IC_CONF_PP_ROT_EN       (1 << 20)
--#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
--#define IC_CONF_KEY_COLOR_EN    (1 << 29)
--#define IC_CONF_RWS_EN          (1 << 30)
--#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
--
--#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
--#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
--#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
--#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
--#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
--#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
--#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
--#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
--#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
--#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
--#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
--#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
--#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
--#define IC_IDMAC_1_PP_ROT_OFFSET        17
--#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
--#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
--#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
--
--#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
--#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
--#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
--#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
--#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
--#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
--
--#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
--#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
--#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
--#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
--#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
--#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
--
--struct ic_task_regoffs {
--      u32 rsc;
--      u32 tpmem_csc[2];
--};
--
--struct ic_task_bitfields {
--      u32 ic_conf_en;
--      u32 ic_conf_rot_en;
--      u32 ic_conf_cmb_en;
--      u32 ic_conf_csc1_en;
--      u32 ic_conf_csc2_en;
--      u32 ic_cmb_galpha_bit;
--};
--
--static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
--      [IC_TASK_ENCODER] = {
--              .rsc = IC_PRP_ENC_RSC,
--              .tpmem_csc = {0x2008, 0},
--      },
--      [IC_TASK_VIEWFINDER] = {
--              .rsc = IC_PRP_VF_RSC,
--              .tpmem_csc = {0x4028, 0x4040},
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .rsc = IC_PP_RSC,
--              .tpmem_csc = {0x6060, 0x6078},
--      },
--};
--
--static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
--      [IC_TASK_ENCODER] = {
--              .ic_conf_en = IC_CONF_PRPENC_EN,
--              .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
--              .ic_conf_cmb_en = 0,    /* NA */
--              .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
--              .ic_conf_csc2_en = 0,   /* NA */
--              .ic_cmb_galpha_bit = 0, /* NA */
--      },
--      [IC_TASK_VIEWFINDER] = {
--              .ic_conf_en = IC_CONF_PRPVF_EN,
--              .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
--              .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
--              .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
--              .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
--              .ic_cmb_galpha_bit = 0,
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .ic_conf_en = IC_CONF_PP_EN,
--              .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
--              .ic_conf_cmb_en = IC_CONF_PP_CMB,
--              .ic_conf_csc1_en = IC_CONF_PP_CSC1,
--              .ic_conf_csc2_en = IC_CONF_PP_CSC2,
--              .ic_cmb_galpha_bit = 8,
--      },
--};
--
--struct ipu_ic_priv;
--
--struct ipu_ic {
--      enum ipu_ic_task task;
--      const struct ic_task_regoffs *reg;
--      const struct ic_task_bitfields *bit;
--
--      struct ipu_ic_colorspace in_cs;
--      struct ipu_ic_colorspace g_in_cs;
--      struct ipu_ic_colorspace out_cs;
--
--      bool graphics;
--      bool rotation;
--      bool in_use;
--
--      struct ipu_ic_priv *priv;
--};
--
--struct ipu_ic_priv {
--      void __iomem *base;
--      void __iomem *tpmem_base;
--      spinlock_t lock;
--      struct ipu_soc *ipu;
--      int use_count;
--      int irt_use_count;
--      struct ipu_ic task[IC_NUM_TASKS];
--};
--
--static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
--{
--      return readl(ic->priv->base + offset);
--}
--
--static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
--{
--      writel(value, ic->priv->base + offset);
--}
--
--static int init_csc(struct ipu_ic *ic,
--                  const struct ipu_ic_csc *csc,
--                  int csc_index)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      u32 __iomem *base;
--      const u16 (*c)[3];
--      const u16 *a;
--      u32 param;
--
--      base = (u32 __iomem *)
--              (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
--
--      /* Cast to unsigned */
--      c = (const u16 (*)[3])csc->params.coeff;
--      a = (const u16 *)csc->params.offset;
--
--      param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
--              ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
--              (csc->params.sat << 10);
--      writel(param, base++);
--
--      param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
--              ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[1] & 0x1fe0) >> 5);
--      writel(param, base++);
--
--      param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
--              ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[2] & 0x1fe0) >> 5);
--      writel(param, base++);
--
--      return 0;
--}
--
--static int calc_resize_coeffs(struct ipu_ic *ic,
--                            u32 in_size, u32 out_size,
--                            u32 *resize_coeff,
--                            u32 *downsize_coeff)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--      u32 temp_size, temp_downsize;
--
--      /*
--       * Input size cannot be more than 4096, and output size cannot
--       * be more than 1024
--       */
--      if (in_size > 4096) {
--              dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
--              return -EINVAL;
--      }
--      if (out_size > 1024) {
--              dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
--              return -EINVAL;
--      }
--
--      /* Cannot downsize more than 4:1 */
--      if ((out_size << 2) < in_size) {
--              dev_err(ipu->dev, "Unsupported downsize\n");
--              return -EINVAL;
--      }
--
--      /* Compute downsizing coefficient */
--      temp_downsize = 0;
--      temp_size = in_size;
--      while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
--             (temp_downsize < 2)) {
--              temp_size >>= 1;
--              temp_downsize++;
--      }
--      *downsize_coeff = temp_downsize;
--
--      /*
--       * compute resizing coefficient using the following equation:
--       * resize_coeff = M * (SI - 1) / (SO - 1)
--       * where M = 2^13, SI = input size, SO = output size
--       */
--      *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
--      if (*resize_coeff >= 16384L) {
--              dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
--              *resize_coeff = 0x3FFF;
--      }
--
--      return 0;
--}
--
--void ipu_ic_task_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--      u32 ic_conf;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      ic_conf |= ic->bit->ic_conf_en;
--
--      if (ic->rotation)
--              ic_conf |= ic->bit->ic_conf_rot_en;
--
--      if (ic->in_cs.cs != ic->out_cs.cs)
--              ic_conf |= ic->bit->ic_conf_csc1_en;
--
--      if (ic->graphics) {
--              ic_conf |= ic->bit->ic_conf_cmb_en;
--              ic_conf |= ic->bit->ic_conf_csc1_en;
--
--              if (ic->g_in_cs.cs != ic->out_cs.cs)
--                      ic_conf |= ic->bit->ic_conf_csc2_en;
--      }
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
--
--void ipu_ic_task_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--      u32 ic_conf;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      ic_conf &= ~(ic->bit->ic_conf_en |
--                   ic->bit->ic_conf_csc1_en |
--                   ic->bit->ic_conf_rot_en);
--      if (ic->bit->ic_conf_csc2_en)
--              ic_conf &= ~ic->bit->ic_conf_csc2_en;
--      if (ic->bit->ic_conf_cmb_en)
--              ic_conf &= ~ic->bit->ic_conf_cmb_en;
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
--
--int ipu_ic_task_graphics_init(struct ipu_ic *ic,
--                            const struct ipu_ic_colorspace *g_in_cs,
--                            bool galpha_en, u32 galpha,
--                            bool colorkey_en, u32 colorkey)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_ic_csc csc2;
--      unsigned long flags;
--      u32 reg, ic_conf;
--      int ret = 0;
--
--      if (ic->task == IC_TASK_ENCODER)
--              return -EINVAL;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
--              struct ipu_ic_csc csc1;
--
--              ret = ipu_ic_calc_csc(&csc1,
--                                    V4L2_YCBCR_ENC_601,
--                                    V4L2_QUANTIZATION_FULL_RANGE,
--                                    IPUV3_COLORSPACE_RGB,
--                                    V4L2_YCBCR_ENC_601,
--                                    V4L2_QUANTIZATION_FULL_RANGE,
--                                    IPUV3_COLORSPACE_RGB);
--              if (ret)
--                      goto unlock;
--
--              /* need transparent CSC1 conversion */
--              ret = init_csc(ic, &csc1, 0);
--              if (ret)
--                      goto unlock;
--      }
--
--      ic->g_in_cs = *g_in_cs;
--      csc2.in_cs = ic->g_in_cs;
--      csc2.out_cs = ic->out_cs;
--
--      ret = __ipu_ic_calc_csc(&csc2);
--      if (ret)
--              goto unlock;
--
--      ret = init_csc(ic, &csc2, 1);
--      if (ret)
--              goto unlock;
--
--      if (galpha_en) {
--              ic_conf |= IC_CONF_IC_GLB_LOC_A;
--              reg = ipu_ic_read(ic, IC_CMBP_1);
--              reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
--              reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
--              ipu_ic_write(ic, reg, IC_CMBP_1);
--      } else
--              ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
--
--      if (colorkey_en) {
--              ic_conf |= IC_CONF_KEY_COLOR_EN;
--              ipu_ic_write(ic, colorkey, IC_CMBP_2);
--      } else
--              ic_conf &= ~IC_CONF_KEY_COLOR_EN;
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      ic->graphics = true;
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
--
--int ipu_ic_task_init_rsc(struct ipu_ic *ic,
--                       const struct ipu_ic_csc *csc,
--                       int in_width, int in_height,
--                       int out_width, int out_height,
--                       u32 rsc)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      u32 downsize_coeff, resize_coeff;
--      unsigned long flags;
--      int ret = 0;
--
--      if (!rsc) {
--              /* Setup vertical resizing */
--
--              ret = calc_resize_coeffs(ic, in_height, out_height,
--                                       &resize_coeff, &downsize_coeff);
--              if (ret)
--                      return ret;
--
--              rsc = (downsize_coeff << 30) | (resize_coeff << 16);
--
--              /* Setup horizontal resizing */
--              ret = calc_resize_coeffs(ic, in_width, out_width,
--                                       &resize_coeff, &downsize_coeff);
--              if (ret)
--                      return ret;
--
--              rsc |= (downsize_coeff << 14) | resize_coeff;
--      }
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ipu_ic_write(ic, rsc, ic->reg->rsc);
--
--      /* Setup color space conversion */
--      ic->in_cs = csc->in_cs;
--      ic->out_cs = csc->out_cs;
--
--      ret = init_csc(ic, csc, 0);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--
--int ipu_ic_task_init(struct ipu_ic *ic,
--                   const struct ipu_ic_csc *csc,
--                   int in_width, int in_height,
--                   int out_width, int out_height)
--{
--      return ipu_ic_task_init_rsc(ic, csc,
--                                  in_width, in_height,
--                                  out_width, out_height, 0);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_init);
--
--int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
--                        u32 width, u32 height, int burst_size,
--                        enum ipu_rotate_mode rot)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--      u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
--      u32 temp_rot = bitrev8(rot) >> 5;
--      bool need_hor_flip = false;
--      unsigned long flags;
--      int ret = 0;
--
--      if ((burst_size != 8) && (burst_size != 16)) {
--              dev_err(ipu->dev, "Illegal burst length for IC\n");
--              return -EINVAL;
--      }
--
--      width--;
--      height--;
--
--      if (temp_rot & 0x2)     /* Need horizontal flip */
--              need_hor_flip = true;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
--      ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
--      ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
--
--      switch (channel->num) {
--      case IPUV3_CHANNEL_IC_PP_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_IC_PP:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_PP:
--              ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_IC_PRP_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
--              break;
--      case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_ENC:
--              ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_IC_PRP_VF_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_VF:
--              ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
--              break;
--      case IPUV3_CHANNEL_G_MEM_IC_PP:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
--              break;
--      case IPUV3_CHANNEL_VDI_MEM_IC_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
--              break;
--      default:
--              goto unlock;
--      }
--
--      ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
--      ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
--      ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
--
--      if (ipu_rot_mode_is_irt(rot))
--              ic->rotation = true;
--
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
--
--static void ipu_irt_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--
--      if (!priv->irt_use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
--
--      priv->irt_use_count++;
--}
--
--static void ipu_irt_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--
--      if (priv->irt_use_count) {
--              if (!--priv->irt_use_count)
--                      ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
--      }
--}
--
--int ipu_ic_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
--
--      priv->use_count++;
--
--      if (ic->rotation)
--              ipu_irt_enable(ic);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_enable);
--
--int ipu_ic_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      if (ic->rotation)
--              ipu_irt_disable(ic);
--
--      ic->rotation = ic->graphics = false;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_disable);
--
--struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
--{
--      struct ipu_ic_priv *priv = ipu->ic_priv;
--      unsigned long flags;
--      struct ipu_ic *ic, *ret;
--
--      if (task >= IC_NUM_TASKS)
--              return ERR_PTR(-EINVAL);
--
--      ic = &priv->task[task];
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (ic->in_use) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      ic->in_use = true;
--      ret = ic;
--
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_get);
--
--void ipu_ic_put(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--      ic->in_use = false;
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_put);
--
--int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long tpmem_base)
--{
--      struct ipu_ic_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->ic_priv = priv;
--
--      spin_lock_init(&priv->lock);
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--      priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
--      if (!priv->tpmem_base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
--
--      priv->ipu = ipu;
--
--      for (i = 0; i < IC_NUM_TASKS; i++) {
--              priv->task[i].task = i;
--              priv->task[i].priv = priv;
--              priv->task[i].reg = &ic_task_reg[i];
--              priv->task[i].bit = &ic_task_bit[i];
--      }
--
--      return 0;
--}
--
--void ipu_ic_exit(struct ipu_soc *ipu)
--{
--}
--
--void ipu_ic_dump(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--
--      dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CONF));
--      dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PRP_ENC_RSC));
--      dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PRP_VF_RSC));
--      dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PP_RSC));
--      dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CMBP_1));
--      dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CMBP_2));
--      dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_1));
--      dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_2));
--      dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_3));
--      dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_4));
--}
--EXPORT_SYMBOL_GPL(ipu_ic_dump);
---- a/drivers/gpu/ipu-v3/ipu-image-convert.c
-+++ /dev/null
-@@ -1,2475 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2016 Mentor Graphics Inc.
-- *
-- * Queued image conversion support, with tiling and rotation.
-- */
--
--#include <linux/interrupt.h>
--#include <linux/dma-mapping.h>
--#include <video/imx-ipu-image-convert.h>
--#include "ipu-prv.h"
--
--/*
-- * The IC Resizer has a restriction that the output frame from the
-- * resizer must be 1024 or less in both width (pixels) and height
-- * (lines).
-- *
-- * The image converter attempts to split up a conversion when
-- * the desired output (converted) frame resolution exceeds the
-- * IC resizer limit of 1024 in either dimension.
-- *
-- * If either dimension of the output frame exceeds the limit, the
-- * dimension is split into 1, 2, or 4 equal stripes, for a maximum
-- * of 4*4 or 16 tiles. A conversion is then carried out for each
-- * tile (but taking care to pass the full frame stride length to
-- * the DMA channel's parameter memory!). IDMA double-buffering is used
-- * to convert each tile back-to-back when possible (see note below
-- * when double_buffering boolean is set).
-- *
-- * Note that the input frame must be split up into the same number
-- * of tiles as the output frame:
-- *
-- *                       +---------+-----+
-- *   +-----+---+         |  A      | B   |
-- *   | A   | B |         |         |     |
-- *   +-----+---+   -->   +---------+-----+
-- *   | C   | D |         |  C      | D   |
-- *   +-----+---+         |         |     |
-- *                       +---------+-----+
-- *
-- * Clockwise 90° rotations are handled by first rescaling into a
-- * reusable temporary tile buffer and then rotating with the 8x8
-- * block rotator, writing to the correct destination:
-- *
-- *                                         +-----+-----+
-- *                                         |     |     |
-- *   +-----+---+         +---------+       | C   | A   |
-- *   | A   | B |         | A,B, |  |       |     |     |
-- *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
-- *   | C   | D |         +---------+       +-----+-----+
-- *   +-----+---+                           | D   | B   |
-- *                                         |     |     |
-- *                                         +-----+-----+
-- *
-- * If the 8x8 block rotator is used, horizontal or vertical flipping
-- * is done during the rotation step, otherwise flipping is done
-- * during the scaling step.
-- * With rotation or flipping, tile order changes between input and
-- * output image. Tiles are numbered row major from top left to bottom
-- * right for both input and output image.
-- */
--
--#define MAX_STRIPES_W    4
--#define MAX_STRIPES_H    4
--#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
--
--#define MIN_W     16
--#define MIN_H     8
--#define MAX_W     4096
--#define MAX_H     4096
--
--enum ipu_image_convert_type {
--      IMAGE_CONVERT_IN = 0,
--      IMAGE_CONVERT_OUT,
--};
--
--struct ipu_image_convert_dma_buf {
--      void          *virt;
--      dma_addr_t    phys;
--      unsigned long len;
--};
--
--struct ipu_image_convert_dma_chan {
--      int in;
--      int out;
--      int rot_in;
--      int rot_out;
--      int vdi_in_p;
--      int vdi_in;
--      int vdi_in_n;
--};
--
--/* dimensions of one tile */
--struct ipu_image_tile {
--      u32 width;
--      u32 height;
--      u32 left;
--      u32 top;
--      /* size and strides are in bytes */
--      u32 size;
--      u32 stride;
--      u32 rot_stride;
--      /* start Y or packed offset of this tile */
--      u32 offset;
--      /* offset from start to tile in U plane, for planar formats */
--      u32 u_off;
--      /* offset from start to tile in V plane, for planar formats */
--      u32 v_off;
--};
--
--struct ipu_image_convert_image {
--      struct ipu_image base;
--      enum ipu_image_convert_type type;
--
--      const struct ipu_image_pixfmt *fmt;
--      unsigned int stride;
--
--      /* # of rows (horizontal stripes) if dest height is > 1024 */
--      unsigned int num_rows;
--      /* # of columns (vertical stripes) if dest width is > 1024 */
--      unsigned int num_cols;
--
--      struct ipu_image_tile tile[MAX_TILES];
--};
--
--struct ipu_image_pixfmt {
--      u32     fourcc;        /* V4L2 fourcc */
--      int     bpp;           /* total bpp */
--      int     uv_width_dec;  /* decimation in width for U/V planes */
--      int     uv_height_dec; /* decimation in height for U/V planes */
--      bool    planar;        /* planar format */
--      bool    uv_swapped;    /* U and V planes are swapped */
--      bool    uv_packed;     /* partial planar (U and V in same plane) */
--};
--
--struct ipu_image_convert_ctx;
--struct ipu_image_convert_chan;
--struct ipu_image_convert_priv;
--
--struct ipu_image_convert_ctx {
--      struct ipu_image_convert_chan *chan;
--
--      ipu_image_convert_cb_t complete;
--      void *complete_context;
--
--      /* Source/destination image data and rotation mode */
--      struct ipu_image_convert_image in;
--      struct ipu_image_convert_image out;
--      struct ipu_ic_csc csc;
--      enum ipu_rotate_mode rot_mode;
--      u32 downsize_coeff_h;
--      u32 downsize_coeff_v;
--      u32 image_resize_coeff_h;
--      u32 image_resize_coeff_v;
--      u32 resize_coeffs_h[MAX_STRIPES_W];
--      u32 resize_coeffs_v[MAX_STRIPES_H];
--
--      /* intermediate buffer for rotation */
--      struct ipu_image_convert_dma_buf rot_intermediate[2];
--
--      /* current buffer number for double buffering */
--      int cur_buf_num;
--
--      bool aborting;
--      struct completion aborted;
--
--      /* can we use double-buffering for this conversion operation? */
--      bool double_buffering;
--      /* num_rows * num_cols */
--      unsigned int num_tiles;
--      /* next tile to process */
--      unsigned int next_tile;
--      /* where to place converted tile in dest image */
--      unsigned int out_tile_map[MAX_TILES];
--
--      struct list_head list;
--};
--
--struct ipu_image_convert_chan {
--      struct ipu_image_convert_priv *priv;
--
--      enum ipu_ic_task ic_task;
--      const struct ipu_image_convert_dma_chan *dma_ch;
--
--      struct ipu_ic *ic;
--      struct ipuv3_channel *in_chan;
--      struct ipuv3_channel *out_chan;
--      struct ipuv3_channel *rotation_in_chan;
--      struct ipuv3_channel *rotation_out_chan;
--
--      /* the IPU end-of-frame irqs */
--      int out_eof_irq;
--      int rot_out_eof_irq;
--
--      spinlock_t irqlock;
--
--      /* list of convert contexts */
--      struct list_head ctx_list;
--      /* queue of conversion runs */
--      struct list_head pending_q;
--      /* queue of completed runs */
--      struct list_head done_q;
--
--      /* the current conversion run */
--      struct ipu_image_convert_run *current_run;
--};
--
--struct ipu_image_convert_priv {
--      struct ipu_image_convert_chan chan[IC_NUM_TASKS];
--      struct ipu_soc *ipu;
--};
--
--static const struct ipu_image_convert_dma_chan
--image_convert_dma_chan[IC_NUM_TASKS] = {
--      [IC_TASK_VIEWFINDER] = {
--              .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
--              .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
--              .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
--              .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
--              .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
--              .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
--              .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .in = IPUV3_CHANNEL_MEM_IC_PP,
--              .out = IPUV3_CHANNEL_IC_PP_MEM,
--              .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
--              .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
--      },
--};
--
--static const struct ipu_image_pixfmt image_convert_formats[] = {
--      {
--              .fourcc = V4L2_PIX_FMT_RGB565,
--              .bpp    = 16,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGB24,
--              .bpp    = 24,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGR24,
--              .bpp    = 24,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGB32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGR32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_XRGB32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_XBGR32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGRX32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGBX32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUYV,
--              .bpp    = 16,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_UYVY,
--              .bpp    = 16,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUV420,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YVU420,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--              .uv_swapped = true,
--      }, {
--              .fourcc = V4L2_PIX_FMT_NV12,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--              .uv_packed = true,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUV422P,
--              .bpp    = 16,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_NV16,
--              .bpp    = 16,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--              .uv_packed = true,
--      },
--};
--
--static const struct ipu_image_pixfmt *get_format(u32 fourcc)
--{
--      const struct ipu_image_pixfmt *ret = NULL;
--      unsigned int i;
--
--      for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
--              if (image_convert_formats[i].fourcc == fourcc) {
--                      ret = &image_convert_formats[i];
--                      break;
--              }
--      }
--
--      return ret;
--}
--
--static void dump_format(struct ipu_image_convert_ctx *ctx,
--                      struct ipu_image_convert_image *ic_image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev,
--              "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
--              chan->ic_task, ctx,
--              ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
--              ic_image->base.pix.width, ic_image->base.pix.height,
--              ic_image->num_cols, ic_image->num_rows,
--              ic_image->fmt->fourcc & 0xff,
--              (ic_image->fmt->fourcc >> 8) & 0xff,
--              (ic_image->fmt->fourcc >> 16) & 0xff,
--              (ic_image->fmt->fourcc >> 24) & 0xff);
--}
--
--int ipu_image_convert_enum_format(int index, u32 *fourcc)
--{
--      const struct ipu_image_pixfmt *fmt;
--
--      if (index >= (int)ARRAY_SIZE(image_convert_formats))
--              return -EINVAL;
--
--      /* Format found */
--      fmt = &image_convert_formats[index];
--      *fourcc = fmt->fourcc;
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
--
--static void free_dma_buf(struct ipu_image_convert_priv *priv,
--                       struct ipu_image_convert_dma_buf *buf)
--{
--      if (buf->virt)
--              dma_free_coherent(priv->ipu->dev,
--                                buf->len, buf->virt, buf->phys);
--      buf->virt = NULL;
--      buf->phys = 0;
--}
--
--static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
--                       struct ipu_image_convert_dma_buf *buf,
--                       int size)
--{
--      buf->len = PAGE_ALIGN(size);
--      buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
--                                     GFP_DMA | GFP_KERNEL);
--      if (!buf->virt) {
--              dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
--              return -ENOMEM;
--      }
--
--      return 0;
--}
--
--static inline int num_stripes(int dim)
--{
--      return (dim - 1) / 1024 + 1;
--}
--
--/*
-- * Calculate downsizing coefficients, which are the same for all tiles,
-- * and initial bilinear resizing coefficients, which are used to find the
-- * best seam positions.
-- * Also determine the number of tiles necessary to guarantee that no tile
-- * is larger than 1024 pixels in either dimension at the output and between
-- * IC downsizing and main processing sections.
-- */
--static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
--                                        struct ipu_image *in,
--                                        struct ipu_image *out)
--{
--      u32 downsized_width = in->rect.width;
--      u32 downsized_height = in->rect.height;
--      u32 downsize_coeff_v = 0;
--      u32 downsize_coeff_h = 0;
--      u32 resized_width = out->rect.width;
--      u32 resized_height = out->rect.height;
--      u32 resize_coeff_h;
--      u32 resize_coeff_v;
--      u32 cols;
--      u32 rows;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              resized_width = out->rect.height;
--              resized_height = out->rect.width;
--      }
--
--      /* Do not let invalid input lead to an endless loop below */
--      if (WARN_ON(resized_width == 0 || resized_height == 0))
--              return -EINVAL;
--
--      while (downsized_width >= resized_width * 2) {
--              downsized_width >>= 1;
--              downsize_coeff_h++;
--      }
--
--      while (downsized_height >= resized_height * 2) {
--              downsized_height >>= 1;
--              downsize_coeff_v++;
--      }
--
--      /*
--       * Calculate the bilinear resizing coefficients that could be used if
--       * we were converting with a single tile. The bottom right output pixel
--       * should sample as close as possible to the bottom right input pixel
--       * out of the decimator, but not overshoot it:
--       */
--      resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
--      resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
--
--      /*
--       * Both the output of the IC downsizing section before being passed to
--       * the IC main processing section and the final output of the IC main
--       * processing section must be <= 1024 pixels in both dimensions.
--       */
--      cols = num_stripes(max_t(u32, downsized_width, resized_width));
--      rows = num_stripes(max_t(u32, downsized_height, resized_height));
--
--      dev_dbg(ctx->chan->priv->ipu->dev,
--              "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
--              __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
--              resize_coeff_v, cols, rows);
--
--      if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
--          resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
--              return -EINVAL;
--
--      ctx->downsize_coeff_h = downsize_coeff_h;
--      ctx->downsize_coeff_v = downsize_coeff_v;
--      ctx->image_resize_coeff_h = resize_coeff_h;
--      ctx->image_resize_coeff_v = resize_coeff_v;
--      ctx->in.num_cols = cols;
--      ctx->in.num_rows = rows;
--
--      return 0;
--}
--
--#define round_closest(x, y) round_down((x) + (y)/2, (y))
--
--/*
-- * Find the best aligned seam position for the given column / row index.
-- * Rotation and image offsets are out of scope.
-- *
-- * @index: column / row index, used to calculate valid interval
-- * @in_edge: input right / bottom edge
-- * @out_edge: output right / bottom edge
-- * @in_align: input alignment, either horizontal 8-byte line start address
-- *            alignment, or pixel alignment due to image format
-- * @out_align: output alignment, either horizontal 8-byte line start address
-- *             alignment, or pixel alignment due to image format or rotator
-- *             block size
-- * @in_burst: horizontal input burst size in case of horizontal flip
-- * @out_burst: horizontal output burst size or rotator block size
-- * @downsize_coeff: downsizing section coefficient
-- * @resize_coeff: main processing section resizing coefficient
-- * @_in_seam: aligned input seam position return value
-- * @_out_seam: aligned output seam position return value
-- */
--static void find_best_seam(struct ipu_image_convert_ctx *ctx,
--                         unsigned int index,
--                         unsigned int in_edge,
--                         unsigned int out_edge,
--                         unsigned int in_align,
--                         unsigned int out_align,
--                         unsigned int in_burst,
--                         unsigned int out_burst,
--                         unsigned int downsize_coeff,
--                         unsigned int resize_coeff,
--                         u32 *_in_seam,
--                         u32 *_out_seam)
--{
--      struct device *dev = ctx->chan->priv->ipu->dev;
--      unsigned int out_pos;
--      /* Input / output seam position candidates */
--      unsigned int out_seam = 0;
--      unsigned int in_seam = 0;
--      unsigned int min_diff = UINT_MAX;
--      unsigned int out_start;
--      unsigned int out_end;
--      unsigned int in_start;
--      unsigned int in_end;
--
--      /* Start within 1024 pixels of the right / bottom edge */
--      out_start = max_t(int, index * out_align, out_edge - 1024);
--      /* End before having to add more columns to the left / rows above */
--      out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
--
--      /*
--       * Limit input seam position to make sure that the downsized input tile
--       * to the right or bottom does not exceed 1024 pixels.
--       */
--      in_start = max_t(int, index * in_align,
--                       in_edge - (1024 << downsize_coeff));
--      in_end = min_t(unsigned int, in_edge,
--                     index * (1024 << downsize_coeff) + 1);
--
--      /*
--       * Output tiles must start at a multiple of 8 bytes horizontally and
--       * possibly at an even line horizontally depending on the pixel format.
--       * Only consider output aligned positions for the seam.
--       */
--      out_start = round_up(out_start, out_align);
--      for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
--              unsigned int in_pos;
--              unsigned int in_pos_aligned;
--              unsigned int in_pos_rounded;
--              unsigned int abs_diff;
--
--              /*
--               * Tiles in the right row / bottom column may not be allowed to
--               * overshoot horizontally / vertically. out_burst may be the
--               * actual DMA burst size, or the rotator block size.
--               */
--              if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
--                      continue;
--
--              /*
--               * Input sample position, corresponding to out_pos, 19.13 fixed
--               * point.
--               */
--              in_pos = (out_pos * resize_coeff) << downsize_coeff;
--              /*
--               * The closest input sample position that we could actually
--               * start the input tile at, 19.13 fixed point.
--               */
--              in_pos_aligned = round_closest(in_pos, 8192U * in_align);
--              /* Convert 19.13 fixed point to integer */
--              in_pos_rounded = in_pos_aligned / 8192U;
--
--              if (in_pos_rounded < in_start)
--                      continue;
--              if (in_pos_rounded >= in_end)
--                      break;
--
--              if ((in_burst > 1) &&
--                  (in_edge - in_pos_rounded) % in_burst)
--                      continue;
--
--              if (in_pos < in_pos_aligned)
--                      abs_diff = in_pos_aligned - in_pos;
--              else
--                      abs_diff = in_pos - in_pos_aligned;
--
--              if (abs_diff < min_diff) {
--                      in_seam = in_pos_rounded;
--                      out_seam = out_pos;
--                      min_diff = abs_diff;
--              }
--      }
--
--      *_out_seam = out_seam;
--      *_in_seam = in_seam;
--
--      dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
--              __func__, out_seam, out_align, out_start, out_end,
--              in_seam, in_align, in_start, in_end, min_diff / 8192,
--              DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
--}
--
--/*
-- * Tile left edges are required to be aligned to multiples of 8 bytes
-- * by the IDMAC.
-- */
--static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
--{
--      if (fmt->planar)
--              return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
--      else
--              return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
--}
--
--/*
-- * Tile top edge alignment is only limited by chroma subsampling.
-- */
--static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
--{
--      return fmt->uv_height_dec > 1 ? 2 : 1;
--}
--
--static inline u32 tile_width_align(enum ipu_image_convert_type type,
--                                 const struct ipu_image_pixfmt *fmt,
--                                 enum ipu_rotate_mode rot_mode)
--{
--      if (type == IMAGE_CONVERT_IN) {
--              /*
--               * The IC burst reads 8 pixels at a time. Reading beyond the
--               * end of the line is usually acceptable. Those pixels are
--               * ignored, unless the IC has to write the scaled line in
--               * reverse.
--               */
--              return (!ipu_rot_mode_is_irt(rot_mode) &&
--                      (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
--      }
--
--      /*
--       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
--       * formats to guarantee 8-byte aligned line start addresses in the
--       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
--       * for all other formats.
--       */
--      return (ipu_rot_mode_is_irt(rot_mode) &&
--              fmt->planar && !fmt->uv_packed) ?
--              8 * fmt->uv_width_dec : 8;
--}
--
--static inline u32 tile_height_align(enum ipu_image_convert_type type,
--                                  const struct ipu_image_pixfmt *fmt,
--                                  enum ipu_rotate_mode rot_mode)
--{
--      if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
--              return 2;
--
--      /*
--       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
--       * formats to guarantee 8-byte aligned line start addresses in the
--       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
--       * for all other formats.
--       */
--      return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
--}
--
--/*
-- * Fill in left position and width and for all tiles in an input column, and
-- * for all corresponding output tiles. If the 90° rotator is used, the output
-- * tiles are in a row, and output tile top position and height are set.
-- */
--static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
--                           unsigned int col,
--                           struct ipu_image_convert_image *in,
--                           unsigned int in_left, unsigned int in_width,
--                           struct ipu_image_convert_image *out,
--                           unsigned int out_left, unsigned int out_width)
--{
--      unsigned int row, tile_idx;
--      struct ipu_image_tile *in_tile, *out_tile;
--
--      for (row = 0; row < in->num_rows; row++) {
--              tile_idx = in->num_cols * row + col;
--              in_tile = &in->tile[tile_idx];
--              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
--
--              in_tile->left = in_left;
--              in_tile->width = in_width;
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--                      out_tile->top = out_left;
--                      out_tile->height = out_width;
--              } else {
--                      out_tile->left = out_left;
--                      out_tile->width = out_width;
--              }
--      }
--}
--
--/*
-- * Fill in top position and height and for all tiles in an input row, and
-- * for all corresponding output tiles. If the 90° rotator is used, the output
-- * tiles are in a column, and output tile left position and width are set.
-- */
--static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
--                        struct ipu_image_convert_image *in,
--                        unsigned int in_top, unsigned int in_height,
--                        struct ipu_image_convert_image *out,
--                        unsigned int out_top, unsigned int out_height)
--{
--      unsigned int col, tile_idx;
--      struct ipu_image_tile *in_tile, *out_tile;
--
--      for (col = 0; col < in->num_cols; col++) {
--              tile_idx = in->num_cols * row + col;
--              in_tile = &in->tile[tile_idx];
--              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
--
--              in_tile->top = in_top;
--              in_tile->height = in_height;
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--                      out_tile->left = out_top;
--                      out_tile->width = out_height;
--              } else {
--                      out_tile->top = out_top;
--                      out_tile->height = out_height;
--              }
--      }
--}
--
--/*
-- * Find the best horizontal and vertical seam positions to split into tiles.
-- * Minimize the fractional part of the input sampling position for the
-- * top / left pixels of each tile.
-- */
--static void find_seams(struct ipu_image_convert_ctx *ctx,
--                     struct ipu_image_convert_image *in,
--                     struct ipu_image_convert_image *out)
--{
--      struct device *dev = ctx->chan->priv->ipu->dev;
--      unsigned int resized_width = out->base.rect.width;
--      unsigned int resized_height = out->base.rect.height;
--      unsigned int col;
--      unsigned int row;
--      unsigned int in_left_align = tile_left_align(in->fmt);
--      unsigned int in_top_align = tile_top_align(in->fmt);
--      unsigned int out_left_align = tile_left_align(out->fmt);
--      unsigned int out_top_align = tile_top_align(out->fmt);
--      unsigned int out_width_align = tile_width_align(out->type, out->fmt,
--                                                      ctx->rot_mode);
--      unsigned int out_height_align = tile_height_align(out->type, out->fmt,
--                                                        ctx->rot_mode);
--      unsigned int in_right = in->base.rect.width;
--      unsigned int in_bottom = in->base.rect.height;
--      unsigned int out_right = out->base.rect.width;
--      unsigned int out_bottom = out->base.rect.height;
--      unsigned int flipped_out_left;
--      unsigned int flipped_out_top;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* Switch width/height and align top left to IRT block size */
--              resized_width = out->base.rect.height;
--              resized_height = out->base.rect.width;
--              out_left_align = out_height_align;
--              out_top_align = out_width_align;
--              out_width_align = out_left_align;
--              out_height_align = out_top_align;
--              out_right = out->base.rect.height;
--              out_bottom = out->base.rect.width;
--      }
--
--      for (col = in->num_cols - 1; col > 0; col--) {
--              bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
--                                        !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              bool allow_out_overshoot = (col < in->num_cols - 1) &&
--                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              unsigned int in_left;
--              unsigned int out_left;
--
--              /*
--               * Align input width to burst length if the scaling step flips
--               * horizontally.
--               */
--
--              find_best_seam(ctx, col,
--                             in_right, out_right,
--                             in_left_align, out_left_align,
--                             allow_in_overshoot ? 1 : 8 /* burst length */,
--                             allow_out_overshoot ? 1 : out_width_align,
--                             ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
--                             &in_left, &out_left);
--
--              if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
--                      flipped_out_left = resized_width - out_right;
--              else
--                      flipped_out_left = out_left;
--
--              fill_tile_column(ctx, col, in, in_left, in_right - in_left,
--                               out, flipped_out_left, out_right - out_left);
--
--              dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
--                      in_left, in_right - in_left,
--                      flipped_out_left, out_right - out_left);
--
--              in_right = in_left;
--              out_right = out_left;
--      }
--
--      flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
--                         resized_width - out_right : 0;
--
--      fill_tile_column(ctx, 0, in, 0, in_right,
--                       out, flipped_out_left, out_right);
--
--      dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
--              in_right, flipped_out_left, out_right);
--
--      for (row = in->num_rows - 1; row > 0; row--) {
--              bool allow_overshoot = row < in->num_rows - 1;
--              unsigned int in_top;
--              unsigned int out_top;
--
--              find_best_seam(ctx, row,
--                             in_bottom, out_bottom,
--                             in_top_align, out_top_align,
--                             1, allow_overshoot ? 1 : out_height_align,
--                             ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
--                             &in_top, &out_top);
--
--              if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
--                  ipu_rot_mode_is_irt(ctx->rot_mode))
--                      flipped_out_top = resized_height - out_bottom;
--              else
--                      flipped_out_top = out_top;
--
--              fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
--                            out, flipped_out_top, out_bottom - out_top);
--
--              dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
--                      in_top, in_bottom - in_top,
--                      flipped_out_top, out_bottom - out_top);
--
--              in_bottom = in_top;
--              out_bottom = out_top;
--      }
--
--      if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
--          ipu_rot_mode_is_irt(ctx->rot_mode))
--              flipped_out_top = resized_height - out_bottom;
--      else
--              flipped_out_top = 0;
--
--      fill_tile_row(ctx, 0, in, 0, in_bottom,
--                    out, flipped_out_top, out_bottom);
--
--      dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
--              in_bottom, flipped_out_top, out_bottom);
--}
--
--static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
--                              struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      unsigned int max_width = 1024;
--      unsigned int max_height = 1024;
--      unsigned int i;
--
--      if (image->type == IMAGE_CONVERT_IN) {
--              /* Up to 4096x4096 input tile size */
--              max_width <<= ctx->downsize_coeff_h;
--              max_height <<= ctx->downsize_coeff_v;
--      }
--
--      for (i = 0; i < ctx->num_tiles; i++) {
--              struct ipu_image_tile *tile;
--              const unsigned int row = i / image->num_cols;
--              const unsigned int col = i % image->num_cols;
--
--              if (image->type == IMAGE_CONVERT_OUT)
--                      tile = &image->tile[ctx->out_tile_map[i]];
--              else
--                      tile = &image->tile[i];
--
--              tile->size = ((tile->height * image->fmt->bpp) >> 3) *
--                      tile->width;
--
--              if (image->fmt->planar) {
--                      tile->stride = tile->width;
--                      tile->rot_stride = tile->height;
--              } else {
--                      tile->stride =
--                              (image->fmt->bpp * tile->width) >> 3;
--                      tile->rot_stride =
--                              (image->fmt->bpp * tile->height) >> 3;
--              }
--
--              dev_dbg(priv->ipu->dev,
--                      "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
--                      chan->ic_task, ctx,
--                      image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
--                      row, col,
--                      tile->width, tile->height, tile->left, tile->top);
--
--              if (!tile->width || tile->width > max_width ||
--                  !tile->height || tile->height > max_height) {
--                      dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
--                              image->type == IMAGE_CONVERT_IN ? "input" :
--                              "output", tile->width, tile->height);
--                      return -EINVAL;
--              }
--      }
--
--      return 0;
--}
--
--/*
-- * Use the rotation transformation to find the tile coordinates
-- * (row, col) of a tile in the destination frame that corresponds
-- * to the given tile coordinates of a source frame. The destination
-- * coordinate is then converted to a tile index.
-- */
--static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
--                              int src_row, int src_col)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      int dst_row, dst_col;
--
--      /* with no rotation it's a 1:1 mapping */
--      if (ctx->rot_mode == IPU_ROTATE_NONE)
--              return src_row * s_image->num_cols + src_col;
--
--      /*
--       * before doing the transform, first we have to translate
--       * source row,col for an origin in the center of s_image
--       */
--      src_row = src_row * 2 - (s_image->num_rows - 1);
--      src_col = src_col * 2 - (s_image->num_cols - 1);
--
--      /* do the rotation transform */
--      if (ctx->rot_mode & IPU_ROT_BIT_90) {
--              dst_col = -src_row;
--              dst_row = src_col;
--      } else {
--              dst_col = src_col;
--              dst_row = src_row;
--      }
--
--      /* apply flip */
--      if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
--              dst_col = -dst_col;
--      if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
--              dst_row = -dst_row;
--
--      dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
--              chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
--
--      /*
--       * finally translate dest row,col using an origin in upper
--       * left of d_image
--       */
--      dst_row += d_image->num_rows - 1;
--      dst_col += d_image->num_cols - 1;
--      dst_row /= 2;
--      dst_col /= 2;
--
--      return dst_row * d_image->num_cols + dst_col;
--}
--
--/*
-- * Fill the out_tile_map[] with transformed destination tile indeces.
-- */
--static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      unsigned int row, col, tile = 0;
--
--      for (row = 0; row < s_image->num_rows; row++) {
--              for (col = 0; col < s_image->num_cols; col++) {
--                      ctx->out_tile_map[tile] =
--                              transform_tile_index(ctx, row, col);
--                      tile++;
--              }
--      }
--}
--
--static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
--                                  struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      const struct ipu_image_pixfmt *fmt = image->fmt;
--      unsigned int row, col, tile = 0;
--      u32 H, top, y_stride, uv_stride;
--      u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
--      u32 y_row_off, y_col_off, y_off;
--      u32 y_size, uv_size;
--
--      /* setup some convenience vars */
--      H = image->base.pix.height;
--
--      y_stride = image->stride;
--      uv_stride = y_stride / fmt->uv_width_dec;
--      if (fmt->uv_packed)
--              uv_stride *= 2;
--
--      y_size = H * y_stride;
--      uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
--
--      for (row = 0; row < image->num_rows; row++) {
--              top = image->tile[tile].top;
--              y_row_off = top * y_stride;
--              uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
--
--              for (col = 0; col < image->num_cols; col++) {
--                      y_col_off = image->tile[tile].left;
--                      uv_col_off = y_col_off / fmt->uv_width_dec;
--                      if (fmt->uv_packed)
--                              uv_col_off *= 2;
--
--                      y_off = y_row_off + y_col_off;
--                      uv_off = uv_row_off + uv_col_off;
--
--                      u_off = y_size - y_off + uv_off;
--                      v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
--                      if (fmt->uv_swapped) {
--                              tmp = u_off;
--                              u_off = v_off;
--                              v_off = tmp;
--                      }
--
--                      image->tile[tile].offset = y_off;
--                      image->tile[tile].u_off = u_off;
--                      image->tile[tile++].v_off = v_off;
--
--                      if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
--                              dev_err(priv->ipu->dev,
--                                      "task %u: ctx %p: %s@[%d,%d]: "
--                                      "y_off %08x, u_off %08x, v_off %08x\n",
--                                      chan->ic_task, ctx,
--                                      image->type == IMAGE_CONVERT_IN ?
--                                      "Input" : "Output", row, col,
--                                      y_off, u_off, v_off);
--                              return -EINVAL;
--                      }
--              }
--      }
--
--      return 0;
--}
--
--static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
--                                  struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      const struct ipu_image_pixfmt *fmt = image->fmt;
--      unsigned int row, col, tile = 0;
--      u32 bpp, stride, offset;
--      u32 row_off, col_off;
--
--      /* setup some convenience vars */
--      stride = image->stride;
--      bpp = fmt->bpp;
--
--      for (row = 0; row < image->num_rows; row++) {
--              row_off = image->tile[tile].top * stride;
--
--              for (col = 0; col < image->num_cols; col++) {
--                      col_off = (image->tile[tile].left * bpp) >> 3;
--
--                      offset = row_off + col_off;
--
--                      image->tile[tile].offset = offset;
--                      image->tile[tile].u_off = 0;
--                      image->tile[tile++].v_off = 0;
--
--                      if (offset & 0x7) {
--                              dev_err(priv->ipu->dev,
--                                      "task %u: ctx %p: %s@[%d,%d]: "
--                                      "phys %08x\n",
--                                      chan->ic_task, ctx,
--                                      image->type == IMAGE_CONVERT_IN ?
--                                      "Input" : "Output", row, col,
--                                      row_off + col_off);
--                              return -EINVAL;
--                      }
--              }
--      }
--
--      return 0;
--}
--
--static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
--                            struct ipu_image_convert_image *image)
--{
--      if (image->fmt->planar)
--              return calc_tile_offsets_planar(ctx, image);
--
--      return calc_tile_offsets_packed(ctx, image);
--}
--
--/*
-- * Calculate the resizing ratio for the IC main processing section given input
-- * size, fixed downsizing coefficient, and output size.
-- * Either round to closest for the next tile's first pixel to minimize seams
-- * and distortion (for all but right column / bottom row), or round down to
-- * avoid sampling beyond the edges of the input image for this tile's last
-- * pixel.
-- * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
-- */
--static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
--                           u32 output_size, bool allow_overshoot)
--{
--      u32 downsized = input_size >> downsize_coeff;
--
--      if (allow_overshoot)
--              return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
--      else
--              return 8192 * (downsized - 1) / (output_size - 1);
--}
--
--/*
-- * Slightly modify resize coefficients per tile to hide the bilinear
-- * interpolator reset at tile borders, shifting the right / bottom edge
-- * by up to a half input pixel. This removes noticeable seams between
-- * tiles at higher upscaling factors.
-- */
--static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_tile *in_tile, *out_tile;
--      unsigned int col, row, tile_idx;
--      unsigned int last_output;
--
--      for (col = 0; col < ctx->in.num_cols; col++) {
--              bool closest = (col < ctx->in.num_cols - 1) &&
--                             !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              u32 resized_width;
--              u32 resize_coeff_h;
--              u32 in_width;
--
--              tile_idx = col;
--              in_tile = &ctx->in.tile[tile_idx];
--              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      resized_width = out_tile->height;
--              else
--                      resized_width = out_tile->width;
--
--              resize_coeff_h = calc_resize_coeff(in_tile->width,
--                                                 ctx->downsize_coeff_h,
--                                                 resized_width, closest);
--
--              dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
--                      __func__, col, resize_coeff_h);
--
--              /*
--               * With the horizontal scaling factor known, round up resized
--               * width (output width or height) to burst size.
--               */
--              resized_width = round_up(resized_width, 8);
--
--              /*
--               * Calculate input width from the last accessed input pixel
--               * given resized width and scaling coefficients. Round up to
--               * burst size.
--               */
--              last_output = resized_width - 1;
--              if (closest && ((last_output * resize_coeff_h) % 8192))
--                      last_output++;
--              in_width = round_up(
--                      (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
--                      << ctx->downsize_coeff_h, 8);
--
--              for (row = 0; row < ctx->in.num_rows; row++) {
--                      tile_idx = row * ctx->in.num_cols + col;
--                      in_tile = &ctx->in.tile[tile_idx];
--                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                              out_tile->height = resized_width;
--                      else
--                              out_tile->width = resized_width;
--
--                      in_tile->width = in_width;
--              }
--
--              ctx->resize_coeffs_h[col] = resize_coeff_h;
--      }
--
--      for (row = 0; row < ctx->in.num_rows; row++) {
--              bool closest = (row < ctx->in.num_rows - 1) &&
--                             !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
--              u32 resized_height;
--              u32 resize_coeff_v;
--              u32 in_height;
--
--              tile_idx = row * ctx->in.num_cols;
--              in_tile = &ctx->in.tile[tile_idx];
--              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      resized_height = out_tile->width;
--              else
--                      resized_height = out_tile->height;
--
--              resize_coeff_v = calc_resize_coeff(in_tile->height,
--                                                 ctx->downsize_coeff_v,
--                                                 resized_height, closest);
--
--              dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
--                      __func__, row, resize_coeff_v);
--
--              /*
--               * With the vertical scaling factor known, round up resized
--               * height (output width or height) to IDMAC limitations.
--               */
--              resized_height = round_up(resized_height, 2);
--
--              /*
--               * Calculate input width from the last accessed input pixel
--               * given resized height and scaling coefficients. Align to
--               * IDMAC restrictions.
--               */
--              last_output = resized_height - 1;
--              if (closest && ((last_output * resize_coeff_v) % 8192))
--                      last_output++;
--              in_height = round_up(
--                      (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
--                      << ctx->downsize_coeff_v, 2);
--
--              for (col = 0; col < ctx->in.num_cols; col++) {
--                      tile_idx = row * ctx->in.num_cols + col;
--                      in_tile = &ctx->in.tile[tile_idx];
--                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                              out_tile->width = resized_height;
--                      else
--                              out_tile->height = resized_height;
--
--                      in_tile->height = in_height;
--              }
--
--              ctx->resize_coeffs_v[row] = resize_coeff_v;
--      }
--}
--
--/*
-- * return the number of runs in given queue (pending_q or done_q)
-- * for this context. hold irqlock when calling.
-- */
--static int get_run_count(struct ipu_image_convert_ctx *ctx,
--                       struct list_head *q)
--{
--      struct ipu_image_convert_run *run;
--      int count = 0;
--
--      lockdep_assert_held(&ctx->chan->irqlock);
--
--      list_for_each_entry(run, q, list) {
--              if (run->ctx == ctx)
--                      count++;
--      }
--
--      return count;
--}
--
--static void convert_stop(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
--              __func__, chan->ic_task, ctx, run);
--
--      /* disable IC tasks and the channels */
--      ipu_ic_task_disable(chan->ic);
--      ipu_idmac_disable_channel(chan->in_chan);
--      ipu_idmac_disable_channel(chan->out_chan);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_idmac_disable_channel(chan->rotation_in_chan);
--              ipu_idmac_disable_channel(chan->rotation_out_chan);
--              ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
--      }
--
--      ipu_ic_disable(chan->ic);
--}
--
--static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
--                             struct ipuv3_channel *channel,
--                             struct ipu_image_convert_image *image,
--                             enum ipu_rotate_mode rot_mode,
--                             bool rot_swap_width_height,
--                             unsigned int tile)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      unsigned int burst_size;
--      u32 width, height, stride;
--      dma_addr_t addr0, addr1 = 0;
--      struct ipu_image tile_image;
--      unsigned int tile_idx[2];
--
--      if (image->type == IMAGE_CONVERT_OUT) {
--              tile_idx[0] = ctx->out_tile_map[tile];
--              tile_idx[1] = ctx->out_tile_map[1];
--      } else {
--              tile_idx[0] = tile;
--              tile_idx[1] = 1;
--      }
--
--      if (rot_swap_width_height) {
--              width = image->tile[tile_idx[0]].height;
--              height = image->tile[tile_idx[0]].width;
--              stride = image->tile[tile_idx[0]].rot_stride;
--              addr0 = ctx->rot_intermediate[0].phys;
--              if (ctx->double_buffering)
--                      addr1 = ctx->rot_intermediate[1].phys;
--      } else {
--              width = image->tile[tile_idx[0]].width;
--              height = image->tile[tile_idx[0]].height;
--              stride = image->stride;
--              addr0 = image->base.phys0 +
--                      image->tile[tile_idx[0]].offset;
--              if (ctx->double_buffering)
--                      addr1 = image->base.phys0 +
--                              image->tile[tile_idx[1]].offset;
--      }
--
--      ipu_cpmem_zero(channel);
--
--      memset(&tile_image, 0, sizeof(tile_image));
--      tile_image.pix.width = tile_image.rect.width = width;
--      tile_image.pix.height = tile_image.rect.height = height;
--      tile_image.pix.bytesperline = stride;
--      tile_image.pix.pixelformat =  image->fmt->fourcc;
--      tile_image.phys0 = addr0;
--      tile_image.phys1 = addr1;
--      if (image->fmt->planar && !rot_swap_width_height) {
--              tile_image.u_offset = image->tile[tile_idx[0]].u_off;
--              tile_image.v_offset = image->tile[tile_idx[0]].v_off;
--      }
--
--      ipu_cpmem_set_image(channel, &tile_image);
--
--      if (rot_mode)
--              ipu_cpmem_set_rotation(channel, rot_mode);
--
--      /*
--       * Skip writing U and V components to odd rows in the output
--       * channels for planar 4:2:0.
--       */
--      if ((channel == chan->out_chan ||
--           channel == chan->rotation_out_chan) &&
--          image->fmt->planar && image->fmt->uv_height_dec == 2)
--              ipu_cpmem_skip_odd_chroma_rows(channel);
--
--      if (channel == chan->rotation_in_chan ||
--          channel == chan->rotation_out_chan) {
--              burst_size = 8;
--              ipu_cpmem_set_block_mode(channel);
--      } else
--              burst_size = (width % 16) ? 8 : 16;
--
--      ipu_cpmem_set_burstsize(channel, burst_size);
--
--      ipu_ic_task_idma_init(chan->ic, channel, width, height,
--                            burst_size, rot_mode);
--
--      /*
--       * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
--       * only do this when there is no PRG present.
--       */
--      if (!channel->ipu->prg_priv)
--              ipu_cpmem_set_axi_id(channel, 1);
--
--      ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
--}
--
--static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      unsigned int dst_tile = ctx->out_tile_map[tile];
--      unsigned int dest_width, dest_height;
--      unsigned int col, row;
--      u32 rsc;
--      int ret;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
--              __func__, chan->ic_task, ctx, run, tile, dst_tile);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* swap width/height for resizer */
--              dest_width = d_image->tile[dst_tile].height;
--              dest_height = d_image->tile[dst_tile].width;
--      } else {
--              dest_width = d_image->tile[dst_tile].width;
--              dest_height = d_image->tile[dst_tile].height;
--      }
--
--      row = tile / s_image->num_cols;
--      col = tile % s_image->num_cols;
--
--      rsc =  (ctx->downsize_coeff_v << 30) |
--             (ctx->resize_coeffs_v[row] << 16) |
--             (ctx->downsize_coeff_h << 14) |
--             (ctx->resize_coeffs_h[col]);
--
--      dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
--              __func__, s_image->tile[tile].width,
--              s_image->tile[tile].height, dest_width, dest_height, rsc);
--
--      /* setup the IC resizer and CSC */
--      ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
--                                 s_image->tile[tile].width,
--                                 s_image->tile[tile].height,
--                                 dest_width,
--                                 dest_height,
--                                 rsc);
--      if (ret) {
--              dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
--              return ret;
--      }
--
--      /* init the source MEM-->IC PP IDMAC channel */
--      init_idmac_channel(ctx, chan->in_chan, s_image,
--                         IPU_ROTATE_NONE, false, tile);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* init the IC PP-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->out_chan, d_image,
--                                 IPU_ROTATE_NONE, true, tile);
--
--              /* init the MEM-->IC PP ROT IDMAC channel */
--              init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
--                                 ctx->rot_mode, true, tile);
--
--              /* init the destination IC PP ROT-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
--                                 IPU_ROTATE_NONE, false, tile);
--
--              /* now link IC PP-->MEM to MEM-->IC PP ROT */
--              ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
--      } else {
--              /* init the destination IC PP-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->out_chan, d_image,
--                                 ctx->rot_mode, false, tile);
--      }
--
--      /* enable the IC */
--      ipu_ic_enable(chan->ic);
--
--      /* set buffers ready */
--      ipu_idmac_select_buffer(chan->in_chan, 0);
--      ipu_idmac_select_buffer(chan->out_chan, 0);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--              ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
--      if (ctx->double_buffering) {
--              ipu_idmac_select_buffer(chan->in_chan, 1);
--              ipu_idmac_select_buffer(chan->out_chan, 1);
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
--      }
--
--      /* enable the channels! */
--      ipu_idmac_enable_channel(chan->in_chan);
--      ipu_idmac_enable_channel(chan->out_chan);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_idmac_enable_channel(chan->rotation_in_chan);
--              ipu_idmac_enable_channel(chan->rotation_out_chan);
--      }
--
--      ipu_ic_task_enable(chan->ic);
--
--      ipu_cpmem_dump(chan->in_chan);
--      ipu_cpmem_dump(chan->out_chan);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_cpmem_dump(chan->rotation_in_chan);
--              ipu_cpmem_dump(chan->rotation_out_chan);
--      }
--
--      ipu_dump(priv->ipu);
--
--      return 0;
--}
--
--/* hold irqlock when calling */
--static int do_run(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      ctx->in.base.phys0 = run->in_phys;
--      ctx->out.base.phys0 = run->out_phys;
--
--      ctx->cur_buf_num = 0;
--      ctx->next_tile = 1;
--
--      /* remove run from pending_q and set as current */
--      list_del(&run->list);
--      chan->current_run = run;
--
--      return convert_start(run, 0);
--}
--
--/* hold irqlock when calling */
--static void run_next(struct ipu_image_convert_chan *chan)
--{
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run, *tmp;
--      int ret;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
--              /* skip contexts that are aborting */
--              if (run->ctx->aborting) {
--                      dev_dbg(priv->ipu->dev,
--                              "%s: task %u: skipping aborting ctx %p run %p\n",
--                              __func__, chan->ic_task, run->ctx, run);
--                      continue;
--              }
--
--              ret = do_run(run);
--              if (!ret)
--                      break;
--
--              /*
--               * something went wrong with start, add the run
--               * to done q and continue to the next run in the
--               * pending q.
--               */
--              run->status = ret;
--              list_add_tail(&run->list, &chan->done_q);
--              chan->current_run = NULL;
--      }
--}
--
--static void empty_done_q(struct ipu_image_convert_chan *chan)
--{
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      while (!list_empty(&chan->done_q)) {
--              run = list_entry(chan->done_q.next,
--                               struct ipu_image_convert_run,
--                               list);
--
--              list_del(&run->list);
--
--              dev_dbg(priv->ipu->dev,
--                      "%s: task %u: completing ctx %p run %p with %d\n",
--                      __func__, chan->ic_task, run->ctx, run, run->status);
--
--              /* call the completion callback and free the run */
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              run->ctx->complete(run, run->ctx->complete_context);
--              spin_lock_irqsave(&chan->irqlock, flags);
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--}
--
--/*
-- * the bottom half thread clears out the done_q, calling the
-- * completion handler for each.
-- */
--static irqreturn_t do_bh(int irq, void *dev_id)
--{
--      struct ipu_image_convert_chan *chan = dev_id;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
--              chan->ic_task);
--
--      empty_done_q(chan);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /*
--       * the done_q is cleared out, signal any contexts
--       * that are aborting that abort can complete.
--       */
--      list_for_each_entry(ctx, &chan->ctx_list, list) {
--              if (ctx->aborting) {
--                      dev_dbg(priv->ipu->dev,
--                              "%s: task %u: signaling abort for ctx %p\n",
--                              __func__, chan->ic_task, ctx);
--                      complete_all(&ctx->aborted);
--              }
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
--              chan->ic_task);
--
--      return IRQ_HANDLED;
--}
--
--static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
--{
--      unsigned int cur_tile = ctx->next_tile - 1;
--      unsigned int next_tile = ctx->next_tile;
--
--      if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
--          ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
--          ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
--          ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
--          ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
--          ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
--          ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
--          ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
--              return true;
--
--      return false;
--}
--
--/* hold irqlock when calling */
--static irqreturn_t do_irq(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_tile *src_tile, *dst_tile;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      struct ipuv3_channel *outch;
--      unsigned int dst_idx;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
--              chan->rotation_out_chan : chan->out_chan;
--
--      /*
--       * It is difficult to stop the channel DMA before the channels
--       * enter the paused state. Without double-buffering the channels
--       * are always in a paused state when the EOF irq occurs, so it
--       * is safe to stop the channels now. For double-buffering we
--       * just ignore the abort until the operation completes, when it
--       * is safe to shut down.
--       */
--      if (ctx->aborting && !ctx->double_buffering) {
--              convert_stop(run);
--              run->status = -EIO;
--              goto done;
--      }
--
--      if (ctx->next_tile == ctx->num_tiles) {
--              /*
--               * the conversion is complete
--               */
--              convert_stop(run);
--              run->status = 0;
--              goto done;
--      }
--
--      /*
--       * not done, place the next tile buffers.
--       */
--      if (!ctx->double_buffering) {
--              if (ic_settings_changed(ctx)) {
--                      convert_stop(run);
--                      convert_start(run, ctx->next_tile);
--              } else {
--                      src_tile = &s_image->tile[ctx->next_tile];
--                      dst_idx = ctx->out_tile_map[ctx->next_tile];
--                      dst_tile = &d_image->tile[dst_idx];
--
--                      ipu_cpmem_set_buffer(chan->in_chan, 0,
--                                           s_image->base.phys0 +
--                                           src_tile->offset);
--                      ipu_cpmem_set_buffer(outch, 0,
--                                           d_image->base.phys0 +
--                                           dst_tile->offset);
--                      if (s_image->fmt->planar)
--                              ipu_cpmem_set_uv_offset(chan->in_chan,
--                                                      src_tile->u_off,
--                                                      src_tile->v_off);
--                      if (d_image->fmt->planar)
--                              ipu_cpmem_set_uv_offset(outch,
--                                                      dst_tile->u_off,
--                                                      dst_tile->v_off);
--
--                      ipu_idmac_select_buffer(chan->in_chan, 0);
--                      ipu_idmac_select_buffer(outch, 0);
--              }
--      } else if (ctx->next_tile < ctx->num_tiles - 1) {
--
--              src_tile = &s_image->tile[ctx->next_tile + 1];
--              dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
--              dst_tile = &d_image->tile[dst_idx];
--
--              ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
--                                   s_image->base.phys0 + src_tile->offset);
--              ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
--                                   d_image->base.phys0 + dst_tile->offset);
--
--              ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
--              ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
--
--              ctx->cur_buf_num ^= 1;
--      }
--
--      ctx->next_tile++;
--      return IRQ_HANDLED;
--done:
--      list_add_tail(&run->list, &chan->done_q);
--      chan->current_run = NULL;
--      run_next(chan);
--      return IRQ_WAKE_THREAD;
--}
--
--static irqreturn_t norotate_irq(int irq, void *data)
--{
--      struct ipu_image_convert_chan *chan = data;
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--      irqreturn_t ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* get current run and its context */
--      run = chan->current_run;
--      if (!run) {
--              ret = IRQ_NONE;
--              goto out;
--      }
--
--      ctx = run->ctx;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* this is a rotation operation, just ignore */
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              return IRQ_HANDLED;
--      }
--
--      ret = do_irq(run);
--out:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--
--static irqreturn_t rotate_irq(int irq, void *data)
--{
--      struct ipu_image_convert_chan *chan = data;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--      irqreturn_t ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* get current run and its context */
--      run = chan->current_run;
--      if (!run) {
--              ret = IRQ_NONE;
--              goto out;
--      }
--
--      ctx = run->ctx;
--
--      if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* this was NOT a rotation operation, shouldn't happen */
--              dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              return IRQ_HANDLED;
--      }
--
--      ret = do_irq(run);
--out:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--
--/*
-- * try to force the completion of runs for this ctx. Called when
-- * abort wait times out in ipu_image_convert_abort().
-- */
--static void force_abort(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      run = chan->current_run;
--      if (run && run->ctx == ctx) {
--              convert_stop(run);
--              run->status = -EIO;
--              list_add_tail(&run->list, &chan->done_q);
--              chan->current_run = NULL;
--              run_next(chan);
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      empty_done_q(chan);
--}
--
--static void release_ipu_resources(struct ipu_image_convert_chan *chan)
--{
--      if (chan->out_eof_irq >= 0)
--              free_irq(chan->out_eof_irq, chan);
--      if (chan->rot_out_eof_irq >= 0)
--              free_irq(chan->rot_out_eof_irq, chan);
--
--      if (!IS_ERR_OR_NULL(chan->in_chan))
--              ipu_idmac_put(chan->in_chan);
--      if (!IS_ERR_OR_NULL(chan->out_chan))
--              ipu_idmac_put(chan->out_chan);
--      if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
--              ipu_idmac_put(chan->rotation_in_chan);
--      if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
--              ipu_idmac_put(chan->rotation_out_chan);
--      if (!IS_ERR_OR_NULL(chan->ic))
--              ipu_ic_put(chan->ic);
--
--      chan->in_chan = chan->out_chan = chan->rotation_in_chan =
--              chan->rotation_out_chan = NULL;
--      chan->out_eof_irq = chan->rot_out_eof_irq = -1;
--}
--
--static int get_ipu_resources(struct ipu_image_convert_chan *chan)
--{
--      const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      int ret;
--
--      /* get IC */
--      chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
--      if (IS_ERR(chan->ic)) {
--              dev_err(priv->ipu->dev, "could not acquire IC\n");
--              ret = PTR_ERR(chan->ic);
--              goto err;
--      }
--
--      /* get IDMAC channels */
--      chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
--      chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
--      if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
--              dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
--              ret = -EBUSY;
--              goto err;
--      }
--
--      chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
--      chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
--      if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
--              dev_err(priv->ipu->dev,
--                      "could not acquire idmac rotation channels\n");
--              ret = -EBUSY;
--              goto err;
--      }
--
--      /* acquire the EOF interrupts */
--      chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
--                                                chan->out_chan,
--                                                IPU_IRQ_EOF);
--
--      ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
--                                 0, "ipu-ic", chan);
--      if (ret < 0) {
--              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
--                       chan->out_eof_irq);
--              chan->out_eof_irq = -1;
--              goto err;
--      }
--
--      chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
--                                                   chan->rotation_out_chan,
--                                                   IPU_IRQ_EOF);
--
--      ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
--                                 0, "ipu-ic", chan);
--      if (ret < 0) {
--              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
--                      chan->rot_out_eof_irq);
--              chan->rot_out_eof_irq = -1;
--              goto err;
--      }
--
--      return 0;
--err:
--      release_ipu_resources(chan);
--      return ret;
--}
--
--static int fill_image(struct ipu_image_convert_ctx *ctx,
--                    struct ipu_image_convert_image *ic_image,
--                    struct ipu_image *image,
--                    enum ipu_image_convert_type type)
--{
--      struct ipu_image_convert_priv *priv = ctx->chan->priv;
--
--      ic_image->base = *image;
--      ic_image->type = type;
--
--      ic_image->fmt = get_format(image->pix.pixelformat);
--      if (!ic_image->fmt) {
--              dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
--                      type == IMAGE_CONVERT_OUT ? "Output" : "Input");
--              return -EINVAL;
--      }
--
--      if (ic_image->fmt->planar)
--              ic_image->stride = ic_image->base.pix.width;
--      else
--              ic_image->stride  = ic_image->base.pix.bytesperline;
--
--      return 0;
--}
--
--/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
--static unsigned int clamp_align(unsigned int x, unsigned int min,
--                              unsigned int max, unsigned int align)
--{
--      /* Bits that must be zero to be aligned */
--      unsigned int mask = ~((1 << align) - 1);
--
--      /* Clamp to aligned min and max */
--      x = clamp(x, (min + ~mask) & mask, max & mask);
--
--      /* Round to nearest aligned value */
--      if (align)
--              x = (x + (1 << (align - 1))) & mask;
--
--      return x;
--}
--
--/* Adjusts input/output images to IPU restrictions */
--void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
--                            enum ipu_rotate_mode rot_mode)
--{
--      const struct ipu_image_pixfmt *infmt, *outfmt;
--      u32 w_align_out, h_align_out;
--      u32 w_align_in, h_align_in;
--
--      infmt = get_format(in->pix.pixelformat);
--      outfmt = get_format(out->pix.pixelformat);
--
--      /* set some default pixel formats if needed */
--      if (!infmt) {
--              in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
--              infmt = get_format(V4L2_PIX_FMT_RGB24);
--      }
--      if (!outfmt) {
--              out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
--              outfmt = get_format(V4L2_PIX_FMT_RGB24);
--      }
--
--      /* image converter does not handle fields */
--      in->pix.field = out->pix.field = V4L2_FIELD_NONE;
--
--      /* resizer cannot downsize more than 4:1 */
--      if (ipu_rot_mode_is_irt(rot_mode)) {
--              out->pix.height = max_t(__u32, out->pix.height,
--                                      in->pix.width / 4);
--              out->pix.width = max_t(__u32, out->pix.width,
--                                     in->pix.height / 4);
--      } else {
--              out->pix.width = max_t(__u32, out->pix.width,
--                                     in->pix.width / 4);
--              out->pix.height = max_t(__u32, out->pix.height,
--                                      in->pix.height / 4);
--      }
--
--      /* align input width/height */
--      w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
--                                          rot_mode));
--      h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
--                                           rot_mode));
--      in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
--                                  w_align_in);
--      in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
--                                   h_align_in);
--
--      /* align output width/height */
--      w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
--                                           rot_mode));
--      h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
--                                            rot_mode));
--      out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
--                                   w_align_out);
--      out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
--                                    h_align_out);
--
--      /* set input/output strides and image sizes */
--      in->pix.bytesperline = infmt->planar ?
--              clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
--                          w_align_in) :
--              clamp_align((in->pix.width * infmt->bpp) >> 3,
--                          ((2 << w_align_in) * infmt->bpp) >> 3,
--                          (MAX_W * infmt->bpp) >> 3,
--                          w_align_in);
--      in->pix.sizeimage = infmt->planar ?
--              (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
--              in->pix.height * in->pix.bytesperline;
--      out->pix.bytesperline = outfmt->planar ? out->pix.width :
--              (out->pix.width * outfmt->bpp) >> 3;
--      out->pix.sizeimage = outfmt->planar ?
--              (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
--              out->pix.height * out->pix.bytesperline;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
--
--/*
-- * this is used by ipu_image_convert_prepare() to verify set input and
-- * output images are valid before starting the conversion. Clients can
-- * also call it before calling ipu_image_convert_prepare().
-- */
--int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
--                           enum ipu_rotate_mode rot_mode)
--{
--      struct ipu_image testin, testout;
--
--      testin = *in;
--      testout = *out;
--
--      ipu_image_convert_adjust(&testin, &testout, rot_mode);
--
--      if (testin.pix.width != in->pix.width ||
--          testin.pix.height != in->pix.height ||
--          testout.pix.width != out->pix.width ||
--          testout.pix.height != out->pix.height)
--              return -EINVAL;
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
--
--/*
-- * Call ipu_image_convert_prepare() to prepare for the conversion of
-- * given images and rotation mode. Returns a new conversion context.
-- */
--struct ipu_image_convert_ctx *
--ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                        struct ipu_image *in, struct ipu_image *out,
--                        enum ipu_rotate_mode rot_mode,
--                        ipu_image_convert_cb_t complete,
--                        void *complete_context)
--{
--      struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
--      struct ipu_image_convert_image *s_image, *d_image;
--      struct ipu_image_convert_chan *chan;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--      unsigned int i;
--      bool get_res;
--      int ret;
--
--      if (!in || !out || !complete ||
--          (ic_task != IC_TASK_VIEWFINDER &&
--           ic_task != IC_TASK_POST_PROCESSOR))
--              return ERR_PTR(-EINVAL);
--
--      /* verify the in/out images before continuing */
--      ret = ipu_image_convert_verify(in, out, rot_mode);
--      if (ret) {
--              dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
--                      __func__);
--              return ERR_PTR(ret);
--      }
--
--      chan = &priv->chan[ic_task];
--
--      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
--      if (!ctx)
--              return ERR_PTR(-ENOMEM);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
--              chan->ic_task, ctx);
--
--      ctx->chan = chan;
--      init_completion(&ctx->aborted);
--
--      ctx->rot_mode = rot_mode;
--
--      /* Sets ctx->in.num_rows/cols as well */
--      ret = calc_image_resize_coefficients(ctx, in, out);
--      if (ret)
--              goto out_free;
--
--      s_image = &ctx->in;
--      d_image = &ctx->out;
--
--      /* set tiling and rotation */
--      if (ipu_rot_mode_is_irt(rot_mode)) {
--              d_image->num_rows = s_image->num_cols;
--              d_image->num_cols = s_image->num_rows;
--      } else {
--              d_image->num_rows = s_image->num_rows;
--              d_image->num_cols = s_image->num_cols;
--      }
--
--      ctx->num_tiles = d_image->num_cols * d_image->num_rows;
--
--      ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
--      if (ret)
--              goto out_free;
--      ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
--      if (ret)
--              goto out_free;
--
--      calc_out_tile_map(ctx);
--
--      find_seams(ctx, s_image, d_image);
--
--      ret = calc_tile_dimensions(ctx, s_image);
--      if (ret)
--              goto out_free;
--
--      ret = calc_tile_offsets(ctx, s_image);
--      if (ret)
--              goto out_free;
--
--      calc_tile_dimensions(ctx, d_image);
--      ret = calc_tile_offsets(ctx, d_image);
--      if (ret)
--              goto out_free;
--
--      calc_tile_resize_coefficients(ctx);
--
--      ret = ipu_ic_calc_csc(&ctx->csc,
--                      s_image->base.pix.ycbcr_enc,
--                      s_image->base.pix.quantization,
--                      ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
--                      d_image->base.pix.ycbcr_enc,
--                      d_image->base.pix.quantization,
--                      ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
--      if (ret)
--              goto out_free;
--
--      dump_format(ctx, s_image);
--      dump_format(ctx, d_image);
--
--      ctx->complete = complete;
--      ctx->complete_context = complete_context;
--
--      /*
--       * Can we use double-buffering for this operation? If there is
--       * only one tile (the whole image can be converted in a single
--       * operation) there's no point in using double-buffering. Also,
--       * the IPU's IDMAC channels allow only a single U and V plane
--       * offset shared between both buffers, but these offsets change
--       * for every tile, and therefore would have to be updated for
--       * each buffer which is not possible. So double-buffering is
--       * impossible when either the source or destination images are
--       * a planar format (YUV420, YUV422P, etc.). Further, differently
--       * sized tiles or different resizing coefficients per tile
--       * prevent double-buffering as well.
--       */
--      ctx->double_buffering = (ctx->num_tiles > 1 &&
--                               !s_image->fmt->planar &&
--                               !d_image->fmt->planar);
--      for (i = 1; i < ctx->num_tiles; i++) {
--              if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
--                  ctx->in.tile[i].height != ctx->in.tile[0].height ||
--                  ctx->out.tile[i].width != ctx->out.tile[0].width ||
--                  ctx->out.tile[i].height != ctx->out.tile[0].height) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--      for (i = 1; i < ctx->in.num_cols; i++) {
--              if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--      for (i = 1; i < ctx->in.num_rows; i++) {
--              if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              unsigned long intermediate_size = d_image->tile[0].size;
--
--              for (i = 1; i < ctx->num_tiles; i++) {
--                      if (d_image->tile[i].size > intermediate_size)
--                              intermediate_size = d_image->tile[i].size;
--              }
--
--              ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
--                                  intermediate_size);
--              if (ret)
--                      goto out_free;
--              if (ctx->double_buffering) {
--                      ret = alloc_dma_buf(priv,
--                                          &ctx->rot_intermediate[1],
--                                          intermediate_size);
--                      if (ret)
--                              goto out_free_dmabuf0;
--              }
--      }
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      get_res = list_empty(&chan->ctx_list);
--
--      list_add_tail(&ctx->list, &chan->ctx_list);
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (get_res) {
--              ret = get_ipu_resources(chan);
--              if (ret)
--                      goto out_free_dmabuf1;
--      }
--
--      return ctx;
--
--out_free_dmabuf1:
--      free_dma_buf(priv, &ctx->rot_intermediate[1]);
--      spin_lock_irqsave(&chan->irqlock, flags);
--      list_del(&ctx->list);
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--out_free_dmabuf0:
--      free_dma_buf(priv, &ctx->rot_intermediate[0]);
--out_free:
--      kfree(ctx);
--      return ERR_PTR(ret);
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
--
--/*
-- * Carry out a single image conversion run. Only the physaddr's of the input
-- * and output image buffers are needed. The conversion context must have
-- * been created previously with ipu_image_convert_prepare().
-- */
--int ipu_image_convert_queue(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_chan *chan;
--      struct ipu_image_convert_priv *priv;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--      int ret = 0;
--
--      if (!run || !run->ctx || !run->in_phys || !run->out_phys)
--              return -EINVAL;
--
--      ctx = run->ctx;
--      chan = ctx->chan;
--      priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
--              chan->ic_task, ctx, run);
--
--      INIT_LIST_HEAD(&run->list);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      if (ctx->aborting) {
--              ret = -EIO;
--              goto unlock;
--      }
--
--      list_add_tail(&run->list, &chan->pending_q);
--
--      if (!chan->current_run) {
--              ret = do_run(run);
--              if (ret)
--                      chan->current_run = NULL;
--      }
--unlock:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
--
--/* Abort any active or pending conversions for this context */
--static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run, *active_run, *tmp;
--      unsigned long flags;
--      int run_count, ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* move all remaining pending runs in this context to done_q */
--      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
--              if (run->ctx != ctx)
--                      continue;
--              run->status = -EIO;
--              list_move_tail(&run->list, &chan->done_q);
--      }
--
--      run_count = get_run_count(ctx, &chan->done_q);
--      active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
--              chan->current_run : NULL;
--
--      if (active_run)
--              reinit_completion(&ctx->aborted);
--
--      ctx->aborting = true;
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (!run_count && !active_run) {
--              dev_dbg(priv->ipu->dev,
--                      "%s: task %u: no abort needed for ctx %p\n",
--                      __func__, chan->ic_task, ctx);
--              return;
--      }
--
--      if (!active_run) {
--              empty_done_q(chan);
--              return;
--      }
--
--      dev_dbg(priv->ipu->dev,
--              "%s: task %u: wait for completion: %d runs\n",
--              __func__, chan->ic_task, run_count);
--
--      ret = wait_for_completion_timeout(&ctx->aborted,
--                                        msecs_to_jiffies(10000));
--      if (ret == 0) {
--              dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
--              force_abort(ctx);
--      }
--}
--
--void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
--{
--      __ipu_image_convert_abort(ctx);
--      ctx->aborting = false;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
--
--/* Unprepare image conversion context */
--void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      unsigned long flags;
--      bool put_res;
--
--      /* make sure no runs are hanging around */
--      __ipu_image_convert_abort(ctx);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
--              chan->ic_task, ctx);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      list_del(&ctx->list);
--
--      put_res = list_empty(&chan->ctx_list);
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (put_res)
--              release_ipu_resources(chan);
--
--      free_dma_buf(priv, &ctx->rot_intermediate[1]);
--      free_dma_buf(priv, &ctx->rot_intermediate[0]);
--
--      kfree(ctx);
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
--
--/*
-- * "Canned" asynchronous single image conversion. Allocates and returns
-- * a new conversion run.  On successful return the caller must free the
-- * run and call ipu_image_convert_unprepare() after conversion completes.
-- */
--struct ipu_image_convert_run *
--ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                struct ipu_image *in, struct ipu_image *out,
--                enum ipu_rotate_mode rot_mode,
--                ipu_image_convert_cb_t complete,
--                void *complete_context)
--{
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      int ret;
--
--      ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
--                                      complete, complete_context);
--      if (IS_ERR(ctx))
--              return ERR_CAST(ctx);
--
--      run = kzalloc(sizeof(*run), GFP_KERNEL);
--      if (!run) {
--              ipu_image_convert_unprepare(ctx);
--              return ERR_PTR(-ENOMEM);
--      }
--
--      run->ctx = ctx;
--      run->in_phys = in->phys0;
--      run->out_phys = out->phys0;
--
--      ret = ipu_image_convert_queue(run);
--      if (ret) {
--              ipu_image_convert_unprepare(ctx);
--              kfree(run);
--              return ERR_PTR(ret);
--      }
--
--      return run;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert);
--
--/* "Canned" synchronous single image conversion */
--static void image_convert_sync_complete(struct ipu_image_convert_run *run,
--                                      void *data)
--{
--      struct completion *comp = data;
--
--      complete(comp);
--}
--
--int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                         struct ipu_image *in, struct ipu_image *out,
--                         enum ipu_rotate_mode rot_mode)
--{
--      struct ipu_image_convert_run *run;
--      struct completion comp;
--      int ret;
--
--      init_completion(&comp);
--
--      run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
--                              image_convert_sync_complete, &comp);
--      if (IS_ERR(run))
--              return PTR_ERR(run);
--
--      ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
--      ret = (ret == 0) ? -ETIMEDOUT : 0;
--
--      ipu_image_convert_unprepare(run->ctx);
--      kfree(run);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
--
--int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
--{
--      struct ipu_image_convert_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->image_convert_priv = priv;
--      priv->ipu = ipu;
--
--      for (i = 0; i < IC_NUM_TASKS; i++) {
--              struct ipu_image_convert_chan *chan = &priv->chan[i];
--
--              chan->ic_task = i;
--              chan->priv = priv;
--              chan->dma_ch = &image_convert_dma_chan[i];
--              chan->out_eof_irq = -1;
--              chan->rot_out_eof_irq = -1;
--
--              spin_lock_init(&chan->irqlock);
--              INIT_LIST_HEAD(&chan->ctx_list);
--              INIT_LIST_HEAD(&chan->pending_q);
--              INIT_LIST_HEAD(&chan->done_q);
--      }
--
--      return 0;
--}
--
--void ipu_image_convert_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-pre.c
-+++ /dev/null
-@@ -1,346 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-only
--/*
-- * Copyright (c) 2017 Lucas Stach, Pengutronix
-- */
--
--#include <drm/drm_fourcc.h>
--#include <linux/clk.h>
--#include <linux/err.h>
--#include <linux/genalloc.h>
--#include <linux/module.h>
--#include <linux/of.h>
--#include <linux/platform_device.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--#define IPU_PRE_MAX_WIDTH     2048
--#define IPU_PRE_NUM_SCANLINES 8
--
--#define IPU_PRE_CTRL                                  0x000
--#define IPU_PRE_CTRL_SET                              0x004
--#define  IPU_PRE_CTRL_ENABLE                          (1 << 0)
--#define  IPU_PRE_CTRL_BLOCK_EN                                (1 << 1)
--#define  IPU_PRE_CTRL_BLOCK_16                                (1 << 2)
--#define  IPU_PRE_CTRL_SDW_UPDATE                      (1 << 4)
--#define  IPU_PRE_CTRL_VFLIP                           (1 << 5)
--#define  IPU_PRE_CTRL_SO                              (1 << 6)
--#define  IPU_PRE_CTRL_INTERLACED_FIELD                        (1 << 7)
--#define  IPU_PRE_CTRL_HANDSHAKE_EN                    (1 << 8)
--#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)           ((v & 0x3) << 9)
--#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN         (1 << 11)
--#define  IPU_PRE_CTRL_EN_REPEAT                               (1 << 28)
--#define  IPU_PRE_CTRL_TPR_REST_SEL                    (1 << 29)
--#define  IPU_PRE_CTRL_CLKGATE                         (1 << 30)
--#define  IPU_PRE_CTRL_SFTRST                          (1 << 31)
--
--#define IPU_PRE_CUR_BUF                                       0x030
--
--#define IPU_PRE_NEXT_BUF                              0x040
--
--#define IPU_PRE_TPR_CTRL                              0x070
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)              ((v & 0xff) << 0)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK            0xff
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT          (1 << 0)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF               (1 << 4)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF      (1 << 5)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED     (1 << 6)
--
--#define IPU_PRE_PREFETCH_ENG_CTRL                     0x080
--#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN            (1 << 0)
--#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)                ((v & 0x7) << 1)
--#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)    ((v & 0x3) << 4)
--#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)  ((v & 0x7) << 8)
--#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS           (1 << 11)
--#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE          (1 << 12)
--#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP                (1 << 14)
--#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN     (1 << 15)
--
--#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                       0x0a0
--#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)     ((v & 0xffff) << 0)
--#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)    ((v & 0xffff) << 16)
--
--#define IPU_PRE_PREFETCH_ENG_PITCH                    0x0d0
--#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)              ((v & 0xffff) << 0)
--#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)             ((v & 0xffff) << 16)
--
--#define IPU_PRE_STORE_ENG_CTRL                                0x110
--#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN              (1 << 0)
--#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)               ((v & 0x7) << 1)
--#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)  ((v & 0x3) << 4)
--
--#define IPU_PRE_STORE_ENG_STATUS                      0x120
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK  0xffff
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK  0x3fff
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL     (1 << 30)
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD         (1 << 31)
--
--#define IPU_PRE_STORE_ENG_SIZE                                0x130
--#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)                ((v & 0xffff) << 0)
--#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)               ((v & 0xffff) << 16)
--
--#define IPU_PRE_STORE_ENG_PITCH                               0x140
--#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)         ((v & 0xffff) << 0)
--
--#define IPU_PRE_STORE_ENG_ADDR                                0x150
--
--struct ipu_pre {
--      struct list_head        list;
--      struct device           *dev;
--
--      void __iomem            *regs;
--      struct clk              *clk_axi;
--      struct gen_pool         *iram;
--
--      dma_addr_t              buffer_paddr;
--      void                    *buffer_virt;
--      bool                    in_use;
--      unsigned int            safe_window_end;
--      unsigned int            last_bufaddr;
--};
--
--static DEFINE_MUTEX(ipu_pre_list_mutex);
--static LIST_HEAD(ipu_pre_list);
--static int available_pres;
--
--int ipu_pre_get_available_count(void)
--{
--      return available_pres;
--}
--
--struct ipu_pre *
--ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
--{
--      struct device_node *pre_node = of_parse_phandle(dev->of_node,
--                                                      name, index);
--      struct ipu_pre *pre;
--
--      mutex_lock(&ipu_pre_list_mutex);
--      list_for_each_entry(pre, &ipu_pre_list, list) {
--              if (pre_node == pre->dev->of_node) {
--                      mutex_unlock(&ipu_pre_list_mutex);
--                      device_link_add(dev, pre->dev,
--                                      DL_FLAG_AUTOREMOVE_CONSUMER);
--                      of_node_put(pre_node);
--                      return pre;
--              }
--      }
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      of_node_put(pre_node);
--
--      return NULL;
--}
--
--int ipu_pre_get(struct ipu_pre *pre)
--{
--      u32 val;
--
--      if (pre->in_use)
--              return -EBUSY;
--
--      /* first get the engine out of reset and remove clock gating */
--      writel(0, pre->regs + IPU_PRE_CTRL);
--
--      /* init defaults that should be applied to all streams */
--      val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
--            IPU_PRE_CTRL_HANDSHAKE_EN |
--            IPU_PRE_CTRL_TPR_REST_SEL |
--            IPU_PRE_CTRL_SDW_UPDATE;
--      writel(val, pre->regs + IPU_PRE_CTRL);
--
--      pre->in_use = true;
--      return 0;
--}
--
--void ipu_pre_put(struct ipu_pre *pre)
--{
--      writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
--
--      pre->in_use = false;
--}
--
--void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
--                     unsigned int height, unsigned int stride, u32 format,
--                     uint64_t modifier, unsigned int bufaddr)
--{
--      const struct drm_format_info *info = drm_format_info(format);
--      u32 active_bpp = info->cpp[0] >> 1;
--      u32 val;
--
--      /* calculate safe window for ctrl register updates */
--      if (modifier == DRM_FORMAT_MOD_LINEAR)
--              pre->safe_window_end = height - 2;
--      else
--              pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
--
--      writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
--      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
--      pre->last_bufaddr = bufaddr;
--
--      val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
--            IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
--            IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
--            IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
--            IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
--
--      val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
--            IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
--
--      val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
--
--      val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
--            IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
--            IPU_PRE_STORE_ENG_CTRL_STORE_EN;
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
--
--      val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
--            IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
--
--      val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
--
--      writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
--
--      val = readl(pre->regs + IPU_PRE_TPR_CTRL);
--      val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
--      if (modifier != DRM_FORMAT_MOD_LINEAR) {
--              /* only support single buffer formats for now */
--              val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
--              if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
--                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
--              if (info->cpp[0] == 2)
--                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
--      }
--      writel(val, pre->regs + IPU_PRE_TPR_CTRL);
--
--      val = readl(pre->regs + IPU_PRE_CTRL);
--      val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
--             IPU_PRE_CTRL_SDW_UPDATE;
--      if (modifier == DRM_FORMAT_MOD_LINEAR)
--              val &= ~IPU_PRE_CTRL_BLOCK_EN;
--      else
--              val |= IPU_PRE_CTRL_BLOCK_EN;
--      writel(val, pre->regs + IPU_PRE_CTRL);
--}
--
--void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
--{
--      unsigned long timeout = jiffies + msecs_to_jiffies(5);
--      unsigned short current_yblock;
--      u32 val;
--
--      if (bufaddr == pre->last_bufaddr)
--              return;
--
--      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
--      pre->last_bufaddr = bufaddr;
--
--      do {
--              if (time_after(jiffies, timeout)) {
--                      dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
--                      return;
--              }
--
--              val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
--              current_yblock =
--                      (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
--                      IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
--      } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
--
--      writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
--}
--
--bool ipu_pre_update_pending(struct ipu_pre *pre)
--{
--      return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
--                IPU_PRE_CTRL_SDW_UPDATE);
--}
--
--u32 ipu_pre_get_baddr(struct ipu_pre *pre)
--{
--      return (u32)pre->buffer_paddr;
--}
--
--static int ipu_pre_probe(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      struct resource *res;
--      struct ipu_pre *pre;
--
--      pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
--      if (!pre)
--              return -ENOMEM;
--
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      pre->regs = devm_ioremap_resource(&pdev->dev, res);
--      if (IS_ERR(pre->regs))
--              return PTR_ERR(pre->regs);
--
--      pre->clk_axi = devm_clk_get(dev, "axi");
--      if (IS_ERR(pre->clk_axi))
--              return PTR_ERR(pre->clk_axi);
--
--      pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
--      if (!pre->iram)
--              return -EPROBE_DEFER;
--
--      /*
--       * Allocate IRAM buffer with maximum size. This could be made dynamic,
--       * but as there is no other user of this IRAM region and we can fit all
--       * max sized buffers into it, there is no need yet.
--       */
--      pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
--                                            IPU_PRE_NUM_SCANLINES * 4,
--                                            &pre->buffer_paddr);
--      if (!pre->buffer_virt)
--              return -ENOMEM;
--
--      clk_prepare_enable(pre->clk_axi);
--
--      pre->dev = dev;
--      platform_set_drvdata(pdev, pre);
--      mutex_lock(&ipu_pre_list_mutex);
--      list_add(&pre->list, &ipu_pre_list);
--      available_pres++;
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      return 0;
--}
--
--static int ipu_pre_remove(struct platform_device *pdev)
--{
--      struct ipu_pre *pre = platform_get_drvdata(pdev);
--
--      mutex_lock(&ipu_pre_list_mutex);
--      list_del(&pre->list);
--      available_pres--;
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      clk_disable_unprepare(pre->clk_axi);
--
--      if (pre->buffer_virt)
--              gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
--                            IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
--      return 0;
--}
--
--static const struct of_device_id ipu_pre_dt_ids[] = {
--      { .compatible = "fsl,imx6qp-pre", },
--      { /* sentinel */ },
--};
--
--struct platform_driver ipu_pre_drv = {
--      .probe          = ipu_pre_probe,
--      .remove         = ipu_pre_remove,
--      .driver         = {
--              .name   = "imx-ipu-pre",
--              .of_match_table = ipu_pre_dt_ids,
--      },
--};
---- a/drivers/gpu/ipu-v3/ipu-prg.c
-+++ /dev/null
-@@ -1,483 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-only
--/*
-- * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
-- */
--
--#include <drm/drm_fourcc.h>
--#include <linux/clk.h>
--#include <linux/err.h>
--#include <linux/iopoll.h>
--#include <linux/mfd/syscon.h>
--#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
--#include <linux/module.h>
--#include <linux/of.h>
--#include <linux/platform_device.h>
--#include <linux/pm_runtime.h>
--#include <linux/regmap.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--#define IPU_PRG_CTL                           0x00
--#define  IPU_PRG_CTL_BYPASS(i)                        (1 << (0 + i))
--#define  IPU_PRG_CTL_SOFT_ARID_MASK           0x3
--#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)               (8 + i * 2)
--#define  IPU_PRG_CTL_SOFT_ARID(i, v)          ((v & 0x3) << (8 + 2 * i))
--#define  IPU_PRG_CTL_SO(i)                    (1 << (16 + i))
--#define  IPU_PRG_CTL_VFLIP(i)                 (1 << (19 + i))
--#define  IPU_PRG_CTL_BLOCK_MODE(i)            (1 << (22 + i))
--#define  IPU_PRG_CTL_CNT_LOAD_EN(i)           (1 << (25 + i))
--#define  IPU_PRG_CTL_SOFTRST                  (1 << 30)
--#define  IPU_PRG_CTL_SHADOW_EN                        (1 << 31)
--
--#define IPU_PRG_STATUS                                0x04
--#define  IPU_PRG_STATUS_BUFFER0_READY(i)      (1 << (0 + i * 2))
--#define  IPU_PRG_STATUS_BUFFER1_READY(i)      (1 << (1 + i * 2))
--
--#define IPU_PRG_QOS                           0x08
--#define  IPU_PRG_QOS_ARID_MASK                        0xf
--#define  IPU_PRG_QOS_ARID_SHIFT(i)            (0 + i * 4)
--
--#define IPU_PRG_REG_UPDATE                    0x0c
--#define  IPU_PRG_REG_UPDATE_REG_UPDATE                (1 << 0)
--
--#define IPU_PRG_STRIDE(i)                     (0x10 + i * 0x4)
--#define  IPU_PRG_STRIDE_STRIDE_MASK           0x3fff
--
--#define IPU_PRG_CROP_LINE                     0x1c
--
--#define IPU_PRG_THD                           0x20
--
--#define IPU_PRG_BADDR(i)                      (0x24 + i * 0x4)
--
--#define IPU_PRG_OFFSET(i)                     (0x30 + i * 0x4)
--
--#define IPU_PRG_ILO(i)                                (0x3c + i * 0x4)
--
--#define IPU_PRG_HEIGHT(i)                     (0x48 + i * 0x4)
--#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK               0xfff
--#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT      0
--#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK               0xfff
--#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT      16
--
--struct ipu_prg_channel {
--      bool                    enabled;
--      int                     used_pre;
--};
--
--struct ipu_prg {
--      struct list_head        list;
--      struct device           *dev;
--      int                     id;
--
--      void __iomem            *regs;
--      struct clk              *clk_ipg, *clk_axi;
--      struct regmap           *iomuxc_gpr;
--      struct ipu_pre          *pres[3];
--
--      struct ipu_prg_channel  chan[3];
--};
--
--static DEFINE_MUTEX(ipu_prg_list_mutex);
--static LIST_HEAD(ipu_prg_list);
--
--struct ipu_prg *
--ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
--{
--      struct device_node *prg_node = of_parse_phandle(dev->of_node,
--                                                      name, 0);
--      struct ipu_prg *prg;
--
--      mutex_lock(&ipu_prg_list_mutex);
--      list_for_each_entry(prg, &ipu_prg_list, list) {
--              if (prg_node == prg->dev->of_node) {
--                      mutex_unlock(&ipu_prg_list_mutex);
--                      device_link_add(dev, prg->dev,
--                                      DL_FLAG_AUTOREMOVE_CONSUMER);
--                      prg->id = ipu_id;
--                      of_node_put(prg_node);
--                      return prg;
--              }
--      }
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      of_node_put(prg_node);
--
--      return NULL;
--}
--
--int ipu_prg_max_active_channels(void)
--{
--      return ipu_pre_get_available_count();
--}
--EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
--
--bool ipu_prg_present(struct ipu_soc *ipu)
--{
--      if (ipu->prg_priv)
--              return true;
--
--      return false;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_present);
--
--bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
--                            uint64_t modifier)
--{
--      const struct drm_format_info *info = drm_format_info(format);
--
--      if (info->num_planes != 1)
--              return false;
--
--      switch (modifier) {
--      case DRM_FORMAT_MOD_LINEAR:
--      case DRM_FORMAT_MOD_VIVANTE_TILED:
--      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
--              return true;
--      default:
--              return false;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
--
--int ipu_prg_enable(struct ipu_soc *ipu)
--{
--      struct ipu_prg *prg = ipu->prg_priv;
--
--      if (!prg)
--              return 0;
--
--      return pm_runtime_get_sync(prg->dev);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_enable);
--
--void ipu_prg_disable(struct ipu_soc *ipu)
--{
--      struct ipu_prg *prg = ipu->prg_priv;
--
--      if (!prg)
--              return;
--
--      pm_runtime_put(prg->dev);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_disable);
--
--/*
-- * The channel configuartion functions below are not thread safe, as they
-- * must be only called from the atomic commit path in the DRM driver, which
-- * is properly serialized.
-- */
--static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
--{
--      /*
--       * This isn't clearly documented in the RM, but IPU to PRG channel
--       * assignment is fixed, as only with this mapping the control signals
--       * match up.
--       */
--      switch (ipu_chan) {
--      case IPUV3_CHANNEL_MEM_BG_SYNC:
--              return 0;
--      case IPUV3_CHANNEL_MEM_FG_SYNC:
--              return 1;
--      case IPUV3_CHANNEL_MEM_DC_SYNC:
--              return 2;
--      default:
--              return -EINVAL;
--      }
--}
--
--static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
--{
--      int i, ret;
--
--      /* channel 0 is special as it is hardwired to one of the PREs */
--      if (prg_chan == 0) {
--              ret = ipu_pre_get(prg->pres[0]);
--              if (ret)
--                      goto fail;
--              prg->chan[prg_chan].used_pre = 0;
--              return 0;
--      }
--
--      for (i = 1; i < 3; i++) {
--              ret = ipu_pre_get(prg->pres[i]);
--              if (!ret) {
--                      u32 val, mux;
--                      int shift;
--
--                      prg->chan[prg_chan].used_pre = i;
--
--                      /* configure the PRE to PRG channel mux */
--                      shift = (i == 1) ? 12 : 14;
--                      mux = (prg->id << 1) | (prg_chan - 1);
--                      regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
--                                         0x3 << shift, mux << shift);
--
--                      /* check other mux, must not point to same channel */
--                      shift = (i == 1) ? 14 : 12;
--                      regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
--                      if (((val >> shift) & 0x3) == mux) {
--                              regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
--                                                 0x3 << shift,
--                                                 (mux ^ 0x1) << shift);
--                      }
--
--                      return 0;
--              }
--      }
--
--fail:
--      dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
--      return ret;
--}
--
--static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
--{
--      struct ipu_prg_channel *chan = &prg->chan[prg_chan];
--
--      ipu_pre_put(prg->pres[chan->used_pre]);
--      chan->used_pre = -1;
--}
--
--void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--      u32 val;
--
--      if (prg_chan < 0)
--              return;
--
--      chan = &prg->chan[prg_chan];
--      if (!chan->enabled)
--              return;
--
--      pm_runtime_get_sync(prg->dev);
--
--      val = readl(prg->regs + IPU_PRG_CTL);
--      val |= IPU_PRG_CTL_BYPASS(prg_chan);
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
--      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
--
--      pm_runtime_put(prg->dev);
--
--      ipu_prg_put_pre(prg, prg_chan);
--
--      chan->enabled = false;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
--
--int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
--                            unsigned int axi_id, unsigned int width,
--                            unsigned int height, unsigned int stride,
--                            u32 format, uint64_t modifier, unsigned long *eba)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--      u32 val;
--      int ret;
--
--      if (prg_chan < 0)
--              return prg_chan;
--
--      chan = &prg->chan[prg_chan];
--
--      if (chan->enabled) {
--              ipu_pre_update(prg->pres[chan->used_pre], *eba);
--              return 0;
--      }
--
--      ret = ipu_prg_get_pre(prg, prg_chan);
--      if (ret)
--              return ret;
--
--      ipu_pre_configure(prg->pres[chan->used_pre],
--                        width, height, stride, format, modifier, *eba);
--
--
--      pm_runtime_get_sync(prg->dev);
--
--      val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
--      writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
--
--      val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
--             IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
--            ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
--             IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
--      writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
--
--      val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
--      *eba = val;
--      writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
--
--      val = readl(prg->regs + IPU_PRG_CTL);
--      /* config AXI ID */
--      val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
--               IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
--      val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
--      /* enable channel */
--      val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
--      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
--
--      /* wait for both double buffers to be filled */
--      readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
--                         (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
--                         (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
--                         5, 1000);
--
--      pm_runtime_put(prg->dev);
--
--      chan->enabled = true;
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
--
--bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--
--      if (prg_chan < 0)
--              return false;
--
--      chan = &prg->chan[prg_chan];
--      WARN_ON(!chan->enabled);
--
--      return ipu_pre_update_pending(prg->pres[chan->used_pre]);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
--
--static int ipu_prg_probe(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      struct resource *res;
--      struct ipu_prg *prg;
--      u32 val;
--      int i, ret;
--
--      prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
--      if (!prg)
--              return -ENOMEM;
--
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      prg->regs = devm_ioremap_resource(&pdev->dev, res);
--      if (IS_ERR(prg->regs))
--              return PTR_ERR(prg->regs);
--
--
--      prg->clk_ipg = devm_clk_get(dev, "ipg");
--      if (IS_ERR(prg->clk_ipg))
--              return PTR_ERR(prg->clk_ipg);
--
--      prg->clk_axi = devm_clk_get(dev, "axi");
--      if (IS_ERR(prg->clk_axi))
--              return PTR_ERR(prg->clk_axi);
--
--      prg->iomuxc_gpr =
--              syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
--      if (IS_ERR(prg->iomuxc_gpr))
--              return PTR_ERR(prg->iomuxc_gpr);
--
--      for (i = 0; i < 3; i++) {
--              prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
--              if (!prg->pres[i])
--                      return -EPROBE_DEFER;
--      }
--
--      ret = clk_prepare_enable(prg->clk_ipg);
--      if (ret)
--              return ret;
--
--      ret = clk_prepare_enable(prg->clk_axi);
--      if (ret) {
--              clk_disable_unprepare(prg->clk_ipg);
--              return ret;
--      }
--
--      /* init to free running mode */
--      val = readl(prg->regs + IPU_PRG_CTL);
--      val |= IPU_PRG_CTL_SHADOW_EN;
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      /* disable address threshold */
--      writel(0xffffffff, prg->regs + IPU_PRG_THD);
--
--      pm_runtime_set_active(dev);
--      pm_runtime_enable(dev);
--
--      prg->dev = dev;
--      platform_set_drvdata(pdev, prg);
--      mutex_lock(&ipu_prg_list_mutex);
--      list_add(&prg->list, &ipu_prg_list);
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      return 0;
--}
--
--static int ipu_prg_remove(struct platform_device *pdev)
--{
--      struct ipu_prg *prg = platform_get_drvdata(pdev);
--
--      mutex_lock(&ipu_prg_list_mutex);
--      list_del(&prg->list);
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      return 0;
--}
--
--#ifdef CONFIG_PM
--static int prg_suspend(struct device *dev)
--{
--      struct ipu_prg *prg = dev_get_drvdata(dev);
--
--      clk_disable_unprepare(prg->clk_axi);
--      clk_disable_unprepare(prg->clk_ipg);
--
--      return 0;
--}
--
--static int prg_resume(struct device *dev)
--{
--      struct ipu_prg *prg = dev_get_drvdata(dev);
--      int ret;
--
--      ret = clk_prepare_enable(prg->clk_ipg);
--      if (ret)
--              return ret;
--
--      ret = clk_prepare_enable(prg->clk_axi);
--      if (ret) {
--              clk_disable_unprepare(prg->clk_ipg);
--              return ret;
--      }
--
--      return 0;
--}
--#endif
--
--static const struct dev_pm_ops prg_pm_ops = {
--      SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
--};
--
--static const struct of_device_id ipu_prg_dt_ids[] = {
--      { .compatible = "fsl,imx6qp-prg", },
--      { /* sentinel */ },
--};
--
--struct platform_driver ipu_prg_drv = {
--      .probe          = ipu_prg_probe,
--      .remove         = ipu_prg_remove,
--      .driver         = {
--              .name   = "imx-ipu-prg",
--              .pm     = &prg_pm_ops,
--              .of_match_table = ipu_prg_dt_ids,
--      },
--};
---- a/drivers/gpu/ipu-v3/ipu-prv.h
-+++ /dev/null
-@@ -1,274 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0-or-later */
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#ifndef __IPU_PRV_H__
--#define __IPU_PRV_H__
--
--struct ipu_soc;
--
--#include <linux/types.h>
--#include <linux/device.h>
--#include <linux/clk.h>
--#include <linux/platform_device.h>
--
--#include <video/imx-ipu-v3.h>
--
--#define IPU_MCU_T_DEFAULT     8
--#define IPU_CM_IDMAC_REG_OFS  0x00008000
--#define IPU_CM_IC_REG_OFS     0x00020000
--#define IPU_CM_IRT_REG_OFS    0x00028000
--#define IPU_CM_CSI0_REG_OFS   0x00030000
--#define IPU_CM_CSI1_REG_OFS   0x00038000
--#define IPU_CM_SMFC_REG_OFS   0x00050000
--#define IPU_CM_DC_REG_OFS     0x00058000
--#define IPU_CM_DMFC_REG_OFS   0x00060000
--
--/* Register addresses */
--/* IPU Common registers */
--#define IPU_CM_REG(offset)    (offset)
--
--#define IPU_CONF                      IPU_CM_REG(0)
--
--#define IPU_SRM_PRI1                  IPU_CM_REG(0x00a0)
--#define IPU_SRM_PRI2                  IPU_CM_REG(0x00a4)
--#define IPU_FS_PROC_FLOW1             IPU_CM_REG(0x00a8)
--#define IPU_FS_PROC_FLOW2             IPU_CM_REG(0x00ac)
--#define IPU_FS_PROC_FLOW3             IPU_CM_REG(0x00b0)
--#define IPU_FS_DISP_FLOW1             IPU_CM_REG(0x00b4)
--#define IPU_FS_DISP_FLOW2             IPU_CM_REG(0x00b8)
--#define IPU_SKIP                      IPU_CM_REG(0x00bc)
--#define IPU_DISP_ALT_CONF             IPU_CM_REG(0x00c0)
--#define IPU_DISP_GEN                  IPU_CM_REG(0x00c4)
--#define IPU_DISP_ALT1                 IPU_CM_REG(0x00c8)
--#define IPU_DISP_ALT2                 IPU_CM_REG(0x00cc)
--#define IPU_DISP_ALT3                 IPU_CM_REG(0x00d0)
--#define IPU_DISP_ALT4                 IPU_CM_REG(0x00d4)
--#define IPU_SNOOP                     IPU_CM_REG(0x00d8)
--#define IPU_MEM_RST                   IPU_CM_REG(0x00dc)
--#define IPU_PM                                IPU_CM_REG(0x00e0)
--#define IPU_GPR                               IPU_CM_REG(0x00e4)
--#define IPU_CHA_DB_MODE_SEL(ch)               IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_DB_MODE_SEL(ch)   IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
--#define IPU_CHA_CUR_BUF(ch)           IPU_CM_REG(0x023C + 4 * ((ch) / 32))
--#define IPU_ALT_CUR_BUF0              IPU_CM_REG(0x0244)
--#define IPU_ALT_CUR_BUF1              IPU_CM_REG(0x0248)
--#define IPU_SRM_STAT                  IPU_CM_REG(0x024C)
--#define IPU_PROC_TASK_STAT            IPU_CM_REG(0x0250)
--#define IPU_DISP_TASK_STAT            IPU_CM_REG(0x0254)
--#define IPU_CHA_BUF0_RDY(ch)          IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
--#define IPU_CHA_BUF1_RDY(ch)          IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
--#define IPU_CHA_BUF2_RDY(ch)          IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_BUF0_RDY(ch)      IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_BUF1_RDY(ch)      IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
--
--#define IPU_INT_CTRL(n)               IPU_CM_REG(0x003C + 4 * (n))
--#define IPU_INT_STAT(n)               IPU_CM_REG(0x0200 + 4 * (n))
--
--/* SRM_PRI2 */
--#define DP_S_SRM_MODE_MASK            (0x3 << 3)
--#define DP_S_SRM_MODE_NOW             (0x3 << 3)
--#define DP_S_SRM_MODE_NEXT_FRAME      (0x1 << 3)
--
--/* FS_PROC_FLOW1 */
--#define FS_PRPENC_ROT_SRC_SEL_MASK    (0xf << 0)
--#define FS_PRPENC_ROT_SRC_SEL_ENC             (0x7 << 0)
--#define FS_PRPVF_ROT_SRC_SEL_MASK     (0xf << 8)
--#define FS_PRPVF_ROT_SRC_SEL_VF                       (0x8 << 8)
--#define FS_PP_SRC_SEL_MASK            (0xf << 12)
--#define FS_PP_ROT_SRC_SEL_MASK                (0xf << 16)
--#define FS_PP_ROT_SRC_SEL_PP                  (0x5 << 16)
--#define FS_VDI1_SRC_SEL_MASK          (0x3 << 20)
--#define FS_VDI3_SRC_SEL_MASK          (0x3 << 20)
--#define FS_PRP_SRC_SEL_MASK           (0xf << 24)
--#define FS_VDI_SRC_SEL_MASK           (0x3 << 28)
--#define FS_VDI_SRC_SEL_CSI_DIRECT             (0x1 << 28)
--#define FS_VDI_SRC_SEL_VDOA                   (0x2 << 28)
--
--/* FS_PROC_FLOW2 */
--#define FS_PRP_ENC_DEST_SEL_MASK      (0xf << 0)
--#define FS_PRP_ENC_DEST_SEL_IRT_ENC           (0x1 << 0)
--#define FS_PRPVF_DEST_SEL_MASK                (0xf << 4)
--#define FS_PRPVF_DEST_SEL_IRT_VF              (0x1 << 4)
--#define FS_PRPVF_ROT_DEST_SEL_MASK    (0xf << 8)
--#define FS_PP_DEST_SEL_MASK           (0xf << 12)
--#define FS_PP_DEST_SEL_IRT_PP                 (0x3 << 12)
--#define FS_PP_ROT_DEST_SEL_MASK               (0xf << 16)
--#define FS_PRPENC_ROT_DEST_SEL_MASK   (0xf << 20)
--#define FS_PRP_DEST_SEL_MASK          (0xf << 24)
--
--#define IPU_DI0_COUNTER_RELEASE                       (1 << 24)
--#define IPU_DI1_COUNTER_RELEASE                       (1 << 25)
--
--#define IPU_IDMAC_REG(offset) (offset)
--
--#define IDMAC_CONF                    IPU_IDMAC_REG(0x0000)
--#define IDMAC_CHA_EN(ch)              IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
--#define IDMAC_SEP_ALPHA                       IPU_IDMAC_REG(0x000c)
--#define IDMAC_ALT_SEP_ALPHA           IPU_IDMAC_REG(0x0010)
--#define IDMAC_CHA_PRI(ch)             IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
--#define IDMAC_WM_EN(ch)                       IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
--#define IDMAC_CH_LOCK_EN_1            IPU_IDMAC_REG(0x0024)
--#define IDMAC_CH_LOCK_EN_2            IPU_IDMAC_REG(0x0028)
--#define IDMAC_SUB_ADDR_0              IPU_IDMAC_REG(0x002c)
--#define IDMAC_SUB_ADDR_1              IPU_IDMAC_REG(0x0030)
--#define IDMAC_SUB_ADDR_2              IPU_IDMAC_REG(0x0034)
--#define IDMAC_BAND_EN(ch)             IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
--#define IDMAC_CHA_BUSY(ch)            IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
--
--#define IPU_NUM_IRQS  (32 * 15)
--
--enum ipu_modules {
--      IPU_CONF_CSI0_EN                = (1 << 0),
--      IPU_CONF_CSI1_EN                = (1 << 1),
--      IPU_CONF_IC_EN                  = (1 << 2),
--      IPU_CONF_ROT_EN                 = (1 << 3),
--      IPU_CONF_ISP_EN                 = (1 << 4),
--      IPU_CONF_DP_EN                  = (1 << 5),
--      IPU_CONF_DI0_EN                 = (1 << 6),
--      IPU_CONF_DI1_EN                 = (1 << 7),
--      IPU_CONF_SMFC_EN                = (1 << 8),
--      IPU_CONF_DC_EN                  = (1 << 9),
--      IPU_CONF_DMFC_EN                = (1 << 10),
--
--      IPU_CONF_VDI_EN                 = (1 << 12),
--
--      IPU_CONF_IDMAC_DIS              = (1 << 22),
--
--      IPU_CONF_IC_DMFC_SEL            = (1 << 25),
--      IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
--      IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
--
--      IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
--      IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
--      IPU_CONF_IC_INPUT               = (1 << 30),
--      IPU_CONF_CSI_SEL                = (1 << 31),
--};
--
--struct ipuv3_channel {
--      unsigned int num;
--      struct ipu_soc *ipu;
--      struct list_head list;
--};
--
--struct ipu_cpmem;
--struct ipu_csi;
--struct ipu_dc_priv;
--struct ipu_dmfc_priv;
--struct ipu_di;
--struct ipu_ic_priv;
--struct ipu_vdi;
--struct ipu_image_convert_priv;
--struct ipu_smfc_priv;
--struct ipu_pre;
--struct ipu_prg;
--
--struct ipu_devtype;
--
--struct ipu_soc {
--      struct device           *dev;
--      const struct ipu_devtype        *devtype;
--      enum ipuv3_type         ipu_type;
--      spinlock_t              lock;
--      struct mutex            channel_lock;
--      struct list_head        channels;
--
--      void __iomem            *cm_reg;
--      void __iomem            *idmac_reg;
--
--      int                     id;
--      int                     usecount;
--
--      struct clk              *clk;
--
--      int                     irq_sync;
--      int                     irq_err;
--      struct irq_domain       *domain;
--
--      struct ipu_cpmem        *cpmem_priv;
--      struct ipu_dc_priv      *dc_priv;
--      struct ipu_dp_priv      *dp_priv;
--      struct ipu_dmfc_priv    *dmfc_priv;
--      struct ipu_di           *di_priv[2];
--      struct ipu_csi          *csi_priv[2];
--      struct ipu_ic_priv      *ic_priv;
--      struct ipu_vdi          *vdi_priv;
--      struct ipu_image_convert_priv *image_convert_priv;
--      struct ipu_smfc_priv    *smfc_priv;
--      struct ipu_prg          *prg_priv;
--};
--
--static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
--{
--      return readl(ipu->idmac_reg + offset);
--}
--
--static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
--                                 unsigned offset)
--{
--      writel(value, ipu->idmac_reg + offset);
--}
--
--void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
--
--int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
--int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
--
--bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
--
--int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
--               unsigned long base, u32 module, struct clk *clk_ipu);
--void ipu_csi_exit(struct ipu_soc *ipu, int id);
--
--int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long tpmem_base);
--void ipu_ic_exit(struct ipu_soc *ipu);
--
--int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
--               unsigned long base, u32 module);
--void ipu_vdi_exit(struct ipu_soc *ipu);
--
--int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
--void ipu_image_convert_exit(struct ipu_soc *ipu);
--
--int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
--              unsigned long base, u32 module, struct clk *ipu_clk);
--void ipu_di_exit(struct ipu_soc *ipu, int id);
--
--int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              struct clk *ipu_clk);
--void ipu_dmfc_exit(struct ipu_soc *ipu);
--
--int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_dp_exit(struct ipu_soc *ipu);
--
--int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              unsigned long template_base);
--void ipu_dc_exit(struct ipu_soc *ipu);
--
--int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_cpmem_exit(struct ipu_soc *ipu);
--
--int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_smfc_exit(struct ipu_soc *ipu);
--
--struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
--                                        int index);
--int ipu_pre_get_available_count(void);
--int ipu_pre_get(struct ipu_pre *pre);
--void ipu_pre_put(struct ipu_pre *pre);
--u32 ipu_pre_get_baddr(struct ipu_pre *pre);
--void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
--                     unsigned int height, unsigned int stride, u32 format,
--                     uint64_t modifier, unsigned int bufaddr);
--void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
--bool ipu_pre_update_pending(struct ipu_pre *pre);
--
--struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
--                                        int ipu_id);
--
--extern struct platform_driver ipu_pre_drv;
--extern struct platform_driver ipu_prg_drv;
--
--#endif                                /* __IPU_PRV_H__ */
---- a/drivers/gpu/ipu-v3/ipu-smfc.c
-+++ /dev/null
-@@ -1,202 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/init.h>
--#include <linux/io.h>
--#include <linux/errno.h>
--#include <linux/spinlock.h>
--#include <linux/delay.h>
--#include <linux/clk.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--struct ipu_smfc {
--      struct ipu_smfc_priv *priv;
--      int chno;
--      bool inuse;
--};
--
--struct ipu_smfc_priv {
--      void __iomem *base;
--      spinlock_t lock;
--      struct ipu_soc *ipu;
--      struct ipu_smfc channel[4];
--      int use_count;
--};
--
--/*SMFC Registers */
--#define SMFC_MAP      0x0000
--#define SMFC_WMC      0x0004
--#define SMFC_BS               0x0008
--
--int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 4;
--      val = readl(priv->base + SMFC_BS);
--      val &= ~(0xf << shift);
--      val |= burstsize << shift;
--      writel(val, priv->base + SMFC_BS);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
--
--int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 3;
--      val = readl(priv->base + SMFC_MAP);
--      val &= ~(0x7 << shift);
--      val |= ((csi_id << 2) | mipi_id) << shift;
--      writel(val, priv->base + SMFC_MAP);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
--
--int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
--      val = readl(priv->base + SMFC_WMC);
--      val &= ~(0x3f << shift);
--      val |= ((clr_level << 3) | set_level) << shift;
--      writel(val, priv->base + SMFC_WMC);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
--
--int ipu_smfc_enable(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
--
--      priv->use_count++;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_enable);
--
--int ipu_smfc_disable(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_disable);
--
--struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
--{
--      struct ipu_smfc_priv *priv = ipu->smfc_priv;
--      struct ipu_smfc *smfc, *ret;
--      unsigned long flags;
--
--      if (chno >= 4)
--              return ERR_PTR(-EINVAL);
--
--      smfc = &priv->channel[chno];
--      ret = smfc;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (smfc->inuse) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      smfc->inuse = true;
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_get);
--
--void ipu_smfc_put(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--      smfc->inuse = false;
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_put);
--
--int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
--                unsigned long base)
--{
--      struct ipu_smfc_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->smfc_priv = priv;
--      spin_lock_init(&priv->lock);
--      priv->ipu = ipu;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      for (i = 0; i < 4; i++) {
--              priv->channel[i].priv = priv;
--              priv->channel[i].chno = i;
--      }
--
--      pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
--
--      return 0;
--}
--
--void ipu_smfc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/ipu-v3/ipu-vdi.c
-+++ /dev/null
-@@ -1,234 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2016 Mentor Graphics Inc.
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/io.h>
--#include "ipu-prv.h"
--
--struct ipu_vdi {
--      void __iomem *base;
--      u32 module;
--      spinlock_t lock;
--      int use_count;
--      struct ipu_soc *ipu;
--};
--
--
--/* VDI Register Offsets */
--#define VDI_FSIZE 0x0000
--#define VDI_C     0x0004
--
--/* VDI Register Fields */
--#define VDI_C_CH_420             (0 << 1)
--#define VDI_C_CH_422             (1 << 1)
--#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
--#define VDI_C_MOT_SEL_FULL       (2 << 2)
--#define VDI_C_MOT_SEL_LOW        (1 << 2)
--#define VDI_C_MOT_SEL_MED        (0 << 2)
--#define VDI_C_BURST_SIZE1_4      (3 << 4)
--#define VDI_C_BURST_SIZE2_4      (3 << 8)
--#define VDI_C_BURST_SIZE3_4      (3 << 12)
--#define VDI_C_BURST_SIZE_MASK    0xF
--#define VDI_C_BURST_SIZE1_OFFSET 4
--#define VDI_C_BURST_SIZE2_OFFSET 8
--#define VDI_C_BURST_SIZE3_OFFSET 12
--#define VDI_C_VWM1_SET_1         (0 << 16)
--#define VDI_C_VWM1_SET_2         (1 << 16)
--#define VDI_C_VWM1_CLR_2         (1 << 19)
--#define VDI_C_VWM3_SET_1         (0 << 22)
--#define VDI_C_VWM3_SET_2         (1 << 22)
--#define VDI_C_VWM3_CLR_2         (1 << 25)
--#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
--#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
--
--static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
--{
--      return readl(vdi->base + offset);
--}
--
--static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
--                               unsigned int offset)
--{
--      writel(value, vdi->base + offset);
--}
--
--void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
--{
--      bool top_field_0 = false;
--      unsigned long flags;
--      u32 reg;
--
--      switch (field) {
--      case V4L2_FIELD_INTERLACED_TB:
--      case V4L2_FIELD_SEQ_TB:
--      case V4L2_FIELD_TOP:
--              top_field_0 = true;
--              break;
--      case V4L2_FIELD_INTERLACED_BT:
--      case V4L2_FIELD_SEQ_BT:
--      case V4L2_FIELD_BOTTOM:
--              top_field_0 = false;
--              break;
--      default:
--              top_field_0 = (std & V4L2_STD_525_60) ? true : false;
--              break;
--      }
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--      if (top_field_0)
--              reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
--      else
--              reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
--
--void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--
--      reg &= ~VDI_C_MOT_SEL_MASK;
--
--      switch (motion_sel) {
--      case MED_MOTION:
--              reg |= VDI_C_MOT_SEL_MED;
--              break;
--      case HIGH_MOTION:
--              reg |= VDI_C_MOT_SEL_FULL;
--              break;
--      default:
--              reg |= VDI_C_MOT_SEL_LOW;
--              break;
--      }
--
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
--
--void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
--{
--      unsigned long flags;
--      u32 pixel_fmt, reg;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ((yres - 1) << 16) | (xres - 1);
--      ipu_vdi_write(vdi, reg, VDI_FSIZE);
--
--      /*
--       * Full motion, only vertical filter is used.
--       * Burst size is 4 accesses
--       */
--      if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
--          code == MEDIA_BUS_FMT_UYVY8_1X16 ||
--          code == MEDIA_BUS_FMT_YUYV8_2X8 ||
--          code == MEDIA_BUS_FMT_YUYV8_1X16)
--              pixel_fmt = VDI_C_CH_422;
--      else
--              pixel_fmt = VDI_C_CH_420;
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--      reg |= pixel_fmt;
--      reg |= VDI_C_BURST_SIZE2_4;
--      reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
--      reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_setup);
--
--void ipu_vdi_unsetup(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--      ipu_vdi_write(vdi, 0, VDI_FSIZE);
--      ipu_vdi_write(vdi, 0, VDI_C);
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
--
--int ipu_vdi_enable(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      if (!vdi->use_count)
--              ipu_module_enable(vdi->ipu, vdi->module);
--
--      vdi->use_count++;
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_enable);
--
--int ipu_vdi_disable(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      if (vdi->use_count) {
--              if (!--vdi->use_count)
--                      ipu_module_disable(vdi->ipu, vdi->module);
--      }
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_disable);
--
--struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
--{
--      return ipu->vdi_priv;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_get);
--
--void ipu_vdi_put(struct ipu_vdi *vdi)
--{
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_put);
--
--int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
--               unsigned long base, u32 module)
--{
--      struct ipu_vdi *vdi;
--
--      vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
--      if (!vdi)
--              return -ENOMEM;
--
--      ipu->vdi_priv = vdi;
--
--      spin_lock_init(&vdi->lock);
--      vdi->module = module;
--      vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!vdi->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
--      vdi->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_vdi_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/video/Kconfig
-+++ b/drivers/video/Kconfig
-@@ -15,7 +15,7 @@ source "drivers/char/agp/Kconfig"
- source "drivers/gpu/vga/Kconfig"
- source "drivers/gpu/host1x/Kconfig"
--source "drivers/gpu/ipu-v3/Kconfig"
-+source "drivers/gpu/imx/Kconfig"
- source "drivers/gpu/drm/Kconfig"
diff --git a/target/linux/layerscape/patches-5.4/805-display-0044-drm-imx-Extract-IPUv3-specific-KMS-functions-to-ipuv.patch b/target/linux/layerscape/patches-5.4/805-display-0044-drm-imx-Extract-IPUv3-specific-KMS-functions-to-ipuv.patch
deleted file mode 100644 (file)
index cd155a5..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-From 6b1bc8ad2bdcfa0cbda91a0963aed746c424465d Mon Sep 17 00:00:00 2001
-From: Liu Ying <victor.liu@nxp.com>
-Date: Thu, 24 Jan 2019 17:06:30 +0800
-Subject: [PATCH] drm/imx: Extract IPUv3 specific KMS functions to ipuv3-kms.c
- (part 1)
-
-Since we want to add i.MX DPU support into imx-drm, the imx-drm core
-driver should be no more IPUv3 specific.  Let's make imx-drm more generic
-and extract IPUv3 specific KMS functions to ipuv3-kms.c.
-
-Signed-off-by: Liu Ying <victor.liu@nxp.com>
-[ Aisheng: update to new kernel version accordingly ]
-[ Aisheng: split IPU changes out of imx-drm-core change ]
-Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
----
- drivers/gpu/drm/imx/imx-drm-core.c | 81 --------------------------------------
- drivers/gpu/drm/imx/imx-drm.h      |  5 +--
- 2 files changed, 2 insertions(+), 84 deletions(-)
-
---- a/drivers/gpu/drm/imx/imx-drm-core.c
-+++ b/drivers/gpu/drm/imx/imx-drm-core.c
-@@ -26,9 +26,6 @@
- #include <drm/drm_vblank.h>
- #include "imx-drm.h"
--#include "ipuv3-plane.h"
--
--#define MAX_CRTC      4
- static int legacyfb_depth = 16;
- module_param(legacyfb_depth, int, 0444);
-@@ -48,81 +45,6 @@ void imx_drm_encoder_destroy(struct drm_
- }
- EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
--static int imx_drm_atomic_check(struct drm_device *dev,
--                              struct drm_atomic_state *state)
--{
--      int ret;
--
--      ret = drm_atomic_helper_check(dev, state);
--      if (ret)
--              return ret;
--
--      /*
--       * Check modeset again in case crtc_state->mode_changed is
--       * updated in plane's ->atomic_check callback.
--       */
--      ret = drm_atomic_helper_check_modeset(dev, state);
--      if (ret)
--              return ret;
--
--      /* Assign PRG/PRE channels and check if all constrains are satisfied. */
--      ret = ipu_planes_assign_pre(dev, state);
--      if (ret)
--              return ret;
--
--      return ret;
--}
--
--static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
--      .fb_create = drm_gem_fb_create,
--      .atomic_check = imx_drm_atomic_check,
--      .atomic_commit = drm_atomic_helper_commit,
--};
--
--static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
--{
--      struct drm_device *dev = state->dev;
--      struct drm_plane *plane;
--      struct drm_plane_state *old_plane_state, *new_plane_state;
--      bool plane_disabling = false;
--      int i;
--
--      drm_atomic_helper_commit_modeset_disables(dev, state);
--
--      drm_atomic_helper_commit_planes(dev, state,
--                              DRM_PLANE_COMMIT_ACTIVE_ONLY |
--                              DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET);
--
--      drm_atomic_helper_commit_modeset_enables(dev, state);
--
--      for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
--              if (drm_atomic_plane_disabling(old_plane_state, new_plane_state))
--                      plane_disabling = true;
--      }
--
--      /*
--       * The flip done wait is only strictly required by imx-drm if a deferred
--       * plane disable is in-flight. As the core requires blocking commits
--       * to wait for the flip it is done here unconditionally. This keeps the
--       * workitem around a bit longer than required for the majority of
--       * non-blocking commits, but we accept that for the sake of simplicity.
--       */
--      drm_atomic_helper_wait_for_flip_done(dev, state);
--
--      if (plane_disabling) {
--              for_each_old_plane_in_state(state, plane, old_plane_state, i)
--                      ipu_plane_disable_deferred(plane);
--
--      }
--
--      drm_atomic_helper_commit_hw_done(state);
--}
--
--static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
--      .atomic_commit_tail = imx_drm_atomic_commit_tail,
--};
--
--
- int imx_drm_encoder_parse_of(struct drm_device *drm,
-       struct drm_encoder *encoder, struct device_node *np)
- {
-@@ -223,9 +145,6 @@ static int imx_drm_bind(struct device *d
-       drm->mode_config.min_height = 1;
-       drm->mode_config.max_width = 4096;
-       drm->mode_config.max_height = 4096;
--      drm->mode_config.funcs = &imx_drm_mode_config_funcs;
--      drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
--      drm->mode_config.allow_fb_modifiers = true;
-       drm->mode_config.normalize_zpos = true;
-       drm_mode_config_init(drm);
---- a/drivers/gpu/drm/imx/imx-drm.h
-+++ b/drivers/gpu/drm/imx/imx-drm.h
-@@ -2,6 +2,8 @@
- #ifndef _IMX_DRM_H_
- #define _IMX_DRM_H_
-+#define MAX_CRTC      4
-+
- struct device_node;
- struct drm_crtc;
- struct drm_connector;
-@@ -38,7 +40,4 @@ int imx_drm_encoder_parse_of(struct drm_
- void imx_drm_connector_destroy(struct drm_connector *connector);
- void imx_drm_encoder_destroy(struct drm_encoder *encoder);
--int ipu_planes_assign_pre(struct drm_device *dev,
--                        struct drm_atomic_state *state);
--
- #endif /* _IMX_DRM_H_ */
index e00e80564d7a88792db19d1be897d3ae0735ea5c..ae32cf596f46c9424334716f6cf543b4bd68d280 100644 (file)
@@ -20,8 +20,8 @@ Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
 +#include <video/dpu.h>
  
  #include "imx-drm.h"
-@@ -105,6 +106,10 @@ static int compare_of(struct device *dev
+ #include "ipuv3-plane.h"
+@@ -183,6 +184,10 @@ static int compare_of(struct device *dev
                struct ipu_client_platformdata *pdata = dev->platform_data;
  
                return pdata->of_node == np;
index b65727def6bab1b703442f2669cbc12e1a8d90b7..b28f7b172cea5f6febb97b30afbb7baceaa1a65a 100644 (file)
@@ -17,7 +17,7 @@ Signed-off-by: Liu Ying <victor.liu@nxp.com>
 
 --- a/drivers/gpu/drm/imx/imx-drm-core.c
 +++ b/drivers/gpu/drm/imx/imx-drm-core.c
-@@ -158,8 +158,6 @@ static int imx_drm_bind(struct device *d
+@@ -239,8 +239,6 @@ static int imx_drm_bind(struct device *d
        if (ret)
                goto err_kms;
  
@@ -26,7 +26,7 @@ Signed-off-by: Liu Ying <victor.liu@nxp.com>
        /* Now try and bind all our sub-components */
        ret = component_bind_all(dev, drm);
        if (ret)
-@@ -185,6 +183,8 @@ static int imx_drm_bind(struct device *d
+@@ -266,6 +264,8 @@ static int imx_drm_bind(struct device *d
  
        drm_fbdev_generic_setup(drm, legacyfb_depth);
  
index 6bf4e59dcf541d80863a00fe64ceba3f0eabda07..96adbace757740e49aa9032bc35ebca3b77fb259 100644 (file)
@@ -22,7 +22,7 @@ Signed-off-by: Fancy Fang <chen.fang@nxp.com>
  
  #include <drm/drm_atomic.h>
  #include <drm/drm_atomic_helper.h>
-@@ -110,6 +111,18 @@ static int compare_of(struct device *dev
+@@ -188,6 +189,18 @@ static int compare_of(struct device *dev
                struct dpu_client_platformdata *pdata = dev->platform_data;
  
                return pdata->of_node == np;
diff --git a/target/linux/layerscape/patches-5.4/805-display-0048-Revert-drm-imx-Extract-IPUv3-specific-KMS-functions-.patch b/target/linux/layerscape/patches-5.4/805-display-0048-Revert-drm-imx-Extract-IPUv3-specific-KMS-functions-.patch
deleted file mode 100644 (file)
index 23411bc..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From d2943462cef18cb78680215dec058d5254e63dc3 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 2 Mar 2020 13:45:41 +0800
-Subject: [PATCH] Revert "drm/imx: Extract IPUv3 specific KMS functions to
- ipuv3-kms.c (part 1)"
-
-This reverts commit aad8cd9d3f10c57bbf405e25ed1be491d99b6294.
----
- drivers/gpu/drm/imx/imx-drm-core.c | 81 ++++++++++++++++++++++++++++++++++++++
- drivers/gpu/drm/imx/imx-drm.h      |  5 ++-
- 2 files changed, 84 insertions(+), 2 deletions(-)
-
---- a/drivers/gpu/drm/imx/imx-drm-core.c
-+++ b/drivers/gpu/drm/imx/imx-drm-core.c
-@@ -28,6 +28,9 @@
- #include <video/dpu.h>
- #include "imx-drm.h"
-+#include "ipuv3-plane.h"
-+
-+#define MAX_CRTC      4
- static int legacyfb_depth = 16;
- module_param(legacyfb_depth, int, 0444);
-@@ -47,6 +50,81 @@ void imx_drm_encoder_destroy(struct drm_
- }
- EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
-+static int imx_drm_atomic_check(struct drm_device *dev,
-+                              struct drm_atomic_state *state)
-+{
-+      int ret;
-+
-+      ret = drm_atomic_helper_check(dev, state);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * Check modeset again in case crtc_state->mode_changed is
-+       * updated in plane's ->atomic_check callback.
-+       */
-+      ret = drm_atomic_helper_check_modeset(dev, state);
-+      if (ret)
-+              return ret;
-+
-+      /* Assign PRG/PRE channels and check if all constrains are satisfied. */
-+      ret = ipu_planes_assign_pre(dev, state);
-+      if (ret)
-+              return ret;
-+
-+      return ret;
-+}
-+
-+static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
-+      .fb_create = drm_gem_fb_create,
-+      .atomic_check = imx_drm_atomic_check,
-+      .atomic_commit = drm_atomic_helper_commit,
-+};
-+
-+static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
-+{
-+      struct drm_device *dev = state->dev;
-+      struct drm_plane *plane;
-+      struct drm_plane_state *old_plane_state, *new_plane_state;
-+      bool plane_disabling = false;
-+      int i;
-+
-+      drm_atomic_helper_commit_modeset_disables(dev, state);
-+
-+      drm_atomic_helper_commit_planes(dev, state,
-+                              DRM_PLANE_COMMIT_ACTIVE_ONLY |
-+                              DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET);
-+
-+      drm_atomic_helper_commit_modeset_enables(dev, state);
-+
-+      for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
-+              if (drm_atomic_plane_disabling(old_plane_state, new_plane_state))
-+                      plane_disabling = true;
-+      }
-+
-+      /*
-+       * The flip done wait is only strictly required by imx-drm if a deferred
-+       * plane disable is in-flight. As the core requires blocking commits
-+       * to wait for the flip it is done here unconditionally. This keeps the
-+       * workitem around a bit longer than required for the majority of
-+       * non-blocking commits, but we accept that for the sake of simplicity.
-+       */
-+      drm_atomic_helper_wait_for_flip_done(dev, state);
-+
-+      if (plane_disabling) {
-+              for_each_old_plane_in_state(state, plane, old_plane_state, i)
-+                      ipu_plane_disable_deferred(plane);
-+
-+      }
-+
-+      drm_atomic_helper_commit_hw_done(state);
-+}
-+
-+static const struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
-+      .atomic_commit_tail = imx_drm_atomic_commit_tail,
-+};
-+
-+
- int imx_drm_encoder_parse_of(struct drm_device *drm,
-       struct drm_encoder *encoder, struct device_node *np)
- {
-@@ -163,6 +241,9 @@ static int imx_drm_bind(struct device *d
-       drm->mode_config.min_height = 1;
-       drm->mode_config.max_width = 4096;
-       drm->mode_config.max_height = 4096;
-+      drm->mode_config.funcs = &imx_drm_mode_config_funcs;
-+      drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
-+      drm->mode_config.allow_fb_modifiers = true;
-       drm->mode_config.normalize_zpos = true;
-       drm_mode_config_init(drm);
---- a/drivers/gpu/drm/imx/imx-drm.h
-+++ b/drivers/gpu/drm/imx/imx-drm.h
-@@ -2,8 +2,6 @@
- #ifndef _IMX_DRM_H_
- #define _IMX_DRM_H_
--#define MAX_CRTC      4
--
- struct device_node;
- struct drm_crtc;
- struct drm_connector;
-@@ -40,4 +38,7 @@ int imx_drm_encoder_parse_of(struct drm_
- void imx_drm_connector_destroy(struct drm_connector *connector);
- void imx_drm_encoder_destroy(struct drm_encoder *encoder);
-+int ipu_planes_assign_pre(struct drm_device *dev,
-+                        struct drm_atomic_state *state);
-+
- #endif /* _IMX_DRM_H_ */
diff --git a/target/linux/layerscape/patches-5.4/805-display-0049-Revert-gpu-Move-ipu-v3-to-imx-folder.patch b/target/linux/layerscape/patches-5.4/805-display-0049-Revert-gpu-Move-ipu-v3-to-imx-folder.patch
deleted file mode 100644 (file)
index 1c1886b..0000000
+++ /dev/null
@@ -1,19991 +0,0 @@
-From 9a941f832d8b88fb29b40e4b3f9c2b42a8a9b000 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 2 Mar 2020 13:46:13 +0800
-Subject: [PATCH] Revert "gpu: Move ipu-v3 to imx folder"
-
-This reverts commit 9da4beb1c9ce90f97c8d3b5c6254da576746d2cd.
----
- drivers/gpu/Makefile                       |    2 +-
- drivers/gpu/imx/Kconfig                    |    1 -
- drivers/gpu/imx/Makefile                   |    1 -
- drivers/gpu/imx/ipu-v3/Kconfig             |   11 -
- drivers/gpu/imx/ipu-v3/Makefile            |   10 -
- drivers/gpu/imx/ipu-v3/ipu-common.c        | 1565 ------------------
- drivers/gpu/imx/ipu-v3/ipu-cpmem.c         |  976 -----------
- drivers/gpu/imx/ipu-v3/ipu-csi.c           |  821 ---------
- drivers/gpu/imx/ipu-v3/ipu-dc.c            |  420 -----
- drivers/gpu/imx/ipu-v3/ipu-di.c            |  745 ---------
- drivers/gpu/imx/ipu-v3/ipu-dmfc.c          |  214 ---
- drivers/gpu/imx/ipu-v3/ipu-dp.c            |  357 ----
- drivers/gpu/imx/ipu-v3/ipu-ic.c            |  761 ---------
- drivers/gpu/imx/ipu-v3/ipu-image-convert.c | 2475 ----------------------------
- drivers/gpu/imx/ipu-v3/ipu-pre.c           |  346 ----
- drivers/gpu/imx/ipu-v3/ipu-prg.c           |  483 ------
- drivers/gpu/imx/ipu-v3/ipu-prv.h           |  274 ---
- drivers/gpu/imx/ipu-v3/ipu-smfc.c          |  202 ---
- drivers/gpu/imx/ipu-v3/ipu-vdi.c           |  234 ---
- drivers/gpu/ipu-v3/Kconfig                 |   11 +
- drivers/gpu/ipu-v3/Makefile                |   10 +
- drivers/gpu/ipu-v3/ipu-common.c            | 1565 ++++++++++++++++++
- drivers/gpu/ipu-v3/ipu-cpmem.c             |  976 +++++++++++
- drivers/gpu/ipu-v3/ipu-csi.c               |  821 +++++++++
- drivers/gpu/ipu-v3/ipu-dc.c                |  420 +++++
- drivers/gpu/ipu-v3/ipu-di.c                |  745 +++++++++
- drivers/gpu/ipu-v3/ipu-dmfc.c              |  214 +++
- drivers/gpu/ipu-v3/ipu-dp.c                |  357 ++++
- drivers/gpu/ipu-v3/ipu-ic.c                |  761 +++++++++
- drivers/gpu/ipu-v3/ipu-image-convert.c     | 2475 ++++++++++++++++++++++++++++
- drivers/gpu/ipu-v3/ipu-pre.c               |  346 ++++
- drivers/gpu/ipu-v3/ipu-prg.c               |  483 ++++++
- drivers/gpu/ipu-v3/ipu-prv.h               |  274 +++
- drivers/gpu/ipu-v3/ipu-smfc.c              |  202 +++
- drivers/gpu/ipu-v3/ipu-vdi.c               |  234 +++
- drivers/video/Kconfig                      |    2 +-
- 36 files changed, 9896 insertions(+), 9898 deletions(-)
- delete mode 100644 drivers/gpu/imx/Kconfig
- delete mode 100644 drivers/gpu/imx/Makefile
- delete mode 100644 drivers/gpu/imx/ipu-v3/Kconfig
- delete mode 100644 drivers/gpu/imx/ipu-v3/Makefile
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-common.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-cpmem.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-csi.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dc.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-di.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dmfc.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-dp.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-ic.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-image-convert.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-pre.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-prg.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-prv.h
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-smfc.c
- delete mode 100644 drivers/gpu/imx/ipu-v3/ipu-vdi.c
- create mode 100644 drivers/gpu/ipu-v3/Kconfig
- create mode 100644 drivers/gpu/ipu-v3/Makefile
- create mode 100644 drivers/gpu/ipu-v3/ipu-common.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-cpmem.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-csi.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-dc.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-di.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-dmfc.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-dp.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-ic.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-image-convert.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-pre.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-prg.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-prv.h
- create mode 100644 drivers/gpu/ipu-v3/ipu-smfc.c
- create mode 100644 drivers/gpu/ipu-v3/ipu-vdi.c
-
---- a/drivers/gpu/Makefile
-+++ b/drivers/gpu/Makefile
-@@ -3,5 +3,5 @@
- # taken to initialize them in the correct order. Link order is the only way
- # to ensure this currently.
- obj-$(CONFIG_TEGRA_HOST1X)    += host1x/
--obj-y                 += imx/
- obj-y                 += drm/ vga/
-+obj-$(CONFIG_IMX_IPUV3_CORE)  += ipu-v3/
---- a/drivers/gpu/imx/Kconfig
-+++ /dev/null
-@@ -1 +0,0 @@
--source "drivers/gpu/imx/ipu-v3/Kconfig"
---- a/drivers/gpu/imx/Makefile
-+++ /dev/null
-@@ -1 +0,0 @@
--obj-$(CONFIG_IMX_IPUV3_CORE)  += ipu-v3/
---- a/drivers/gpu/imx/ipu-v3/Kconfig
-+++ /dev/null
-@@ -1,11 +0,0 @@
--# SPDX-License-Identifier: GPL-2.0-only
--config IMX_IPUV3_CORE
--      tristate "IPUv3 core support"
--      depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
--      depends on DRM || !DRM # if DRM=m, this can't be 'y'
--      select BITREVERSE
--      select GENERIC_ALLOCATOR if DRM
--      select GENERIC_IRQ_CHIP
--      help
--        Choose this if you have a i.MX5/6 system and want to use the Image
--        Processing Unit. This option only enables IPU base support.
---- a/drivers/gpu/imx/ipu-v3/Makefile
-+++ /dev/null
-@@ -1,10 +0,0 @@
--# SPDX-License-Identifier: GPL-2.0
--obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
--
--imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
--              ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
--              ipu-image-convert.o ipu-smfc.o ipu-vdi.o
--
--ifdef CONFIG_DRM
--      imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
--endif
---- a/drivers/gpu/imx/ipu-v3/ipu-common.c
-+++ /dev/null
-@@ -1,1565 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/module.h>
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/reset.h>
--#include <linux/platform_device.h>
--#include <linux/err.h>
--#include <linux/spinlock.h>
--#include <linux/delay.h>
--#include <linux/interrupt.h>
--#include <linux/io.h>
--#include <linux/clk.h>
--#include <linux/list.h>
--#include <linux/irq.h>
--#include <linux/irqchip/chained_irq.h>
--#include <linux/irqdomain.h>
--#include <linux/of_device.h>
--#include <linux/of_graph.h>
--
--#include <drm/drm_fourcc.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
--{
--      return readl(ipu->cm_reg + offset);
--}
--
--static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
--{
--      writel(value, ipu->cm_reg + offset);
--}
--
--int ipu_get_num(struct ipu_soc *ipu)
--{
--      return ipu->id;
--}
--EXPORT_SYMBOL_GPL(ipu_get_num);
--
--void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
--{
--      u32 val;
--
--      val = ipu_cm_read(ipu, IPU_SRM_PRI2);
--      val &= ~DP_S_SRM_MODE_MASK;
--      val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
--                    DP_S_SRM_MODE_NOW;
--      ipu_cm_write(ipu, val, IPU_SRM_PRI2);
--}
--EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
--
--enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
--{
--      switch (drm_fourcc) {
--      case DRM_FORMAT_ARGB1555:
--      case DRM_FORMAT_ABGR1555:
--      case DRM_FORMAT_RGBA5551:
--      case DRM_FORMAT_BGRA5551:
--      case DRM_FORMAT_RGB565:
--      case DRM_FORMAT_BGR565:
--      case DRM_FORMAT_RGB888:
--      case DRM_FORMAT_BGR888:
--      case DRM_FORMAT_ARGB4444:
--      case DRM_FORMAT_XRGB8888:
--      case DRM_FORMAT_XBGR8888:
--      case DRM_FORMAT_RGBX8888:
--      case DRM_FORMAT_BGRX8888:
--      case DRM_FORMAT_ARGB8888:
--      case DRM_FORMAT_ABGR8888:
--      case DRM_FORMAT_RGBA8888:
--      case DRM_FORMAT_BGRA8888:
--      case DRM_FORMAT_RGB565_A8:
--      case DRM_FORMAT_BGR565_A8:
--      case DRM_FORMAT_RGB888_A8:
--      case DRM_FORMAT_BGR888_A8:
--      case DRM_FORMAT_RGBX8888_A8:
--      case DRM_FORMAT_BGRX8888_A8:
--              return IPUV3_COLORSPACE_RGB;
--      case DRM_FORMAT_YUYV:
--      case DRM_FORMAT_UYVY:
--      case DRM_FORMAT_YUV420:
--      case DRM_FORMAT_YVU420:
--      case DRM_FORMAT_YUV422:
--      case DRM_FORMAT_YVU422:
--      case DRM_FORMAT_YUV444:
--      case DRM_FORMAT_YVU444:
--      case DRM_FORMAT_NV12:
--      case DRM_FORMAT_NV21:
--      case DRM_FORMAT_NV16:
--      case DRM_FORMAT_NV61:
--              return IPUV3_COLORSPACE_YUV;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
--
--enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_UYVY:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              return IPUV3_COLORSPACE_YUV;
--      case V4L2_PIX_FMT_RGB565:
--      case V4L2_PIX_FMT_BGR24:
--      case V4L2_PIX_FMT_RGB24:
--      case V4L2_PIX_FMT_ABGR32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_BGRA32:
--      case V4L2_PIX_FMT_BGRX32:
--      case V4L2_PIX_FMT_RGBA32:
--      case V4L2_PIX_FMT_RGBX32:
--      case V4L2_PIX_FMT_ARGB32:
--      case V4L2_PIX_FMT_XRGB32:
--              return IPUV3_COLORSPACE_RGB;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
--
--bool ipu_pixelformat_is_planar(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              return true;
--      }
--
--      return false;
--}
--EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
--
--enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
--{
--      switch (mbus_code & 0xf000) {
--      case 0x1000:
--              return IPUV3_COLORSPACE_RGB;
--      case 0x2000:
--              return IPUV3_COLORSPACE_YUV;
--      default:
--              return IPUV3_COLORSPACE_UNKNOWN;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
--
--int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--      case V4L2_PIX_FMT_YUV422P:
--      case V4L2_PIX_FMT_NV12:
--      case V4L2_PIX_FMT_NV21:
--      case V4L2_PIX_FMT_NV16:
--      case V4L2_PIX_FMT_NV61:
--              /*
--               * for the planar YUV formats, the stride passed to
--               * cpmem must be the stride in bytes of the Y plane.
--               * And all the planar YUV formats have an 8-bit
--               * Y component.
--               */
--              return (8 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_RGB565:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_UYVY:
--              return (16 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_BGR24:
--      case V4L2_PIX_FMT_RGB24:
--              return (24 * pixel_stride) >> 3;
--      case V4L2_PIX_FMT_BGR32:
--      case V4L2_PIX_FMT_RGB32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_XRGB32:
--              return (32 * pixel_stride) >> 3;
--      default:
--              break;
--      }
--
--      return -EINVAL;
--}
--EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
--
--int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
--                          bool hflip, bool vflip)
--{
--      u32 r90, vf, hf;
--
--      switch (degrees) {
--      case 0:
--              vf = hf = r90 = 0;
--              break;
--      case 90:
--              vf = hf = 0;
--              r90 = 1;
--              break;
--      case 180:
--              vf = hf = 1;
--              r90 = 0;
--              break;
--      case 270:
--              vf = hf = r90 = 1;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      hf ^= (u32)hflip;
--      vf ^= (u32)vflip;
--
--      *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
--
--int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
--                          bool hflip, bool vflip)
--{
--      u32 r90, vf, hf;
--
--      r90 = ((u32)mode >> 2) & 0x1;
--      hf = ((u32)mode >> 1) & 0x1;
--      vf = ((u32)mode >> 0) & 0x1;
--      hf ^= (u32)hflip;
--      vf ^= (u32)vflip;
--
--      switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
--      case IPU_ROTATE_NONE:
--              *degrees = 0;
--              break;
--      case IPU_ROTATE_90_RIGHT:
--              *degrees = 90;
--              break;
--      case IPU_ROTATE_180:
--              *degrees = 180;
--              break;
--      case IPU_ROTATE_90_LEFT:
--              *degrees = 270;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
--
--struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
--{
--      struct ipuv3_channel *channel;
--
--      dev_dbg(ipu->dev, "%s %d\n", __func__, num);
--
--      if (num > 63)
--              return ERR_PTR(-ENODEV);
--
--      mutex_lock(&ipu->channel_lock);
--
--      list_for_each_entry(channel, &ipu->channels, list) {
--              if (channel->num == num) {
--                      channel = ERR_PTR(-EBUSY);
--                      goto out;
--              }
--      }
--
--      channel = kzalloc(sizeof(*channel), GFP_KERNEL);
--      if (!channel) {
--              channel = ERR_PTR(-ENOMEM);
--              goto out;
--      }
--
--      channel->num = num;
--      channel->ipu = ipu;
--      list_add(&channel->list, &ipu->channels);
--
--out:
--      mutex_unlock(&ipu->channel_lock);
--
--      return channel;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_get);
--
--void ipu_idmac_put(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--
--      dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
--
--      mutex_lock(&ipu->channel_lock);
--
--      list_del(&channel->list);
--      kfree(channel);
--
--      mutex_unlock(&ipu->channel_lock);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_put);
--
--#define idma_mask(ch)                 (1 << ((ch) & 0x1f))
--
--/*
-- * This is an undocumented feature, a write one to a channel bit in
-- * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
-- * internal current buffer pointer so that transfers start from buffer
-- * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
-- * only says these are read-only registers). This operation is required
-- * for channel linking to work correctly, for instance video capture
-- * pipelines that carry out image rotations will fail after the first
-- * streaming unless this function is called for each channel before
-- * re-enabling the channels.
-- */
--static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--
--      ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
--}
--
--void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
--              bool doublebuffer)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
--      if (doublebuffer)
--              reg |= idma_mask(channel->num);
--      else
--              reg &= ~idma_mask(channel->num);
--      ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
--
--      __ipu_idmac_reset_current_buffer(channel);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
--
--static const struct {
--      int chnum;
--      u32 reg;
--      int shift;
--} idmac_lock_en_info[] = {
--      { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
--      { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
--      { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
--      { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
--      { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
--      { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
--      { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
--      { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
--      { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
--      { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
--      { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
--      { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
--      { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
--      { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
--      { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
--      { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
--      { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
--};
--
--int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 bursts, regval;
--      int i;
--
--      switch (num_bursts) {
--      case 0:
--      case 1:
--              bursts = 0x00; /* locking disabled */
--              break;
--      case 2:
--              bursts = 0x01;
--              break;
--      case 4:
--              bursts = 0x02;
--              break;
--      case 8:
--              bursts = 0x03;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      /*
--       * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
--       * i.MX53 channel arbitration locking doesn't seem to work properly.
--       * Allow enabling the lock feature on IPUv3H / i.MX6 only.
--       */
--      if (bursts && ipu->ipu_type != IPUV3H)
--              return -EINVAL;
--
--      for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
--              if (channel->num == idmac_lock_en_info[i].chnum)
--                      break;
--      }
--      if (i >= ARRAY_SIZE(idmac_lock_en_info))
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
--      regval &= ~(0x03 << idmac_lock_en_info[i].shift);
--      regval |= (bursts << idmac_lock_en_info[i].shift);
--      ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
--
--int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
--{
--      unsigned long lock_flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, lock_flags);
--
--      val = ipu_cm_read(ipu, IPU_DISP_GEN);
--
--      if (mask & IPU_CONF_DI0_EN)
--              val |= IPU_DI0_COUNTER_RELEASE;
--      if (mask & IPU_CONF_DI1_EN)
--              val |= IPU_DI1_COUNTER_RELEASE;
--
--      ipu_cm_write(ipu, val, IPU_DISP_GEN);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      val |= mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, lock_flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_module_enable);
--
--int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
--{
--      unsigned long lock_flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, lock_flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      val &= ~mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      val = ipu_cm_read(ipu, IPU_DISP_GEN);
--
--      if (mask & IPU_CONF_DI0_EN)
--              val &= ~IPU_DI0_COUNTER_RELEASE;
--      if (mask & IPU_CONF_DI1_EN)
--              val &= ~IPU_DI1_COUNTER_RELEASE;
--
--      ipu_cm_write(ipu, val, IPU_DISP_GEN);
--
--      spin_unlock_irqrestore(&ipu->lock, lock_flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_module_disable);
--
--int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--
--      return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
--
--bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 reg = 0;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--      switch (buf_num) {
--      case 0:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
--              break;
--      case 1:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
--              break;
--      case 2:
--              reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
--              break;
--      }
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return ((reg & idma_mask(channel->num)) != 0);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
--
--void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      /* Mark buffer as ready. */
--      if (buf_num == 0)
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
--      else
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
--
--void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned int chno = channel->num;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
--      switch (buf_num) {
--      case 0:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
--              break;
--      case 1:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
--              break;
--      case 2:
--              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
--              break;
--      default:
--              break;
--      }
--      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
--
--int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      u32 val;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
--      val |= idma_mask(channel->num);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
--
--bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
--{
--      return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
--
--int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long timeout;
--
--      timeout = jiffies + msecs_to_jiffies(ms);
--      while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
--                      idma_mask(channel->num)) {
--              if (time_after(jiffies, timeout))
--                      return -ETIMEDOUT;
--              cpu_relax();
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
--
--int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      u32 val;
--      unsigned long flags;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      /* Disable DMA channel(s) */
--      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
--      val &= ~idma_mask(channel->num);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
--
--      __ipu_idmac_reset_current_buffer(channel);
--
--      /* Set channel buffers NOT to be ready */
--      ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
--
--      if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
--                      idma_mask(channel->num)) {
--              ipu_cm_write(ipu, idma_mask(channel->num),
--                           IPU_CHA_BUF0_RDY(channel->num));
--      }
--
--      if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
--                      idma_mask(channel->num)) {
--              ipu_cm_write(ipu, idma_mask(channel->num),
--                           IPU_CHA_BUF1_RDY(channel->num));
--      }
--
--      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
--
--      /* Reset the double buffer */
--      val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
--      val &= ~idma_mask(channel->num);
--      ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
--
--/*
-- * The imx6 rev. D TRM says that enabling the WM feature will increase
-- * a channel's priority. Refer to Table 36-8 Calculated priority value.
-- * The sub-module that is the sink or source for the channel must enable
-- * watermark signal for this to take effect (SMFC_WM for instance).
-- */
--void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
--{
--      struct ipu_soc *ipu = channel->ipu;
--      unsigned long flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
--      if (enable)
--              val |= 1 << (channel->num % 32);
--      else
--              val &= ~(1 << (channel->num % 32));
--      ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
--
--static int ipu_memory_reset(struct ipu_soc *ipu)
--{
--      unsigned long timeout;
--
--      ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
--
--      timeout = jiffies + msecs_to_jiffies(1000);
--      while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
--              if (time_after(jiffies, timeout))
--                      return -ETIME;
--              cpu_relax();
--      }
--
--      return 0;
--}
--
--/*
-- * Set the source mux for the given CSI. Selects either parallel or
-- * MIPI CSI2 sources.
-- */
--void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
--{
--      unsigned long flags;
--      u32 val, mask;
--
--      mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
--              IPU_CONF_CSI0_DATA_SOURCE;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      if (mipi_csi2)
--              val |= mask;
--      else
--              val &= ~mask;
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
--
--/*
-- * Set the source mux for the IC. Selects either CSI[01] or the VDI.
-- */
--void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
--{
--      unsigned long flags;
--      u32 val;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      val = ipu_cm_read(ipu, IPU_CONF);
--      if (vdi)
--              val |= IPU_CONF_IC_INPUT;
--      else
--              val &= ~IPU_CONF_IC_INPUT;
--
--      if (csi_id == 1)
--              val |= IPU_CONF_CSI_SEL;
--      else
--              val &= ~IPU_CONF_CSI_SEL;
--
--      ipu_cm_write(ipu, val, IPU_CONF);
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
--
--
--/* Frame Synchronization Unit Channel Linking */
--
--struct fsu_link_reg_info {
--      int chno;
--      u32 reg;
--      u32 mask;
--      u32 val;
--};
--
--struct fsu_link_info {
--      struct fsu_link_reg_info src;
--      struct fsu_link_reg_info sink;
--};
--
--static const struct fsu_link_info fsu_link_info[] = {
--      {
--              .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
--                        FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
--      }, {
--              .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
--                        FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
--      }, {
--              .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
--                        FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
--              .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
--                        FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
--      }, {
--              .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
--              .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
--                        FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
--      },
--};
--
--static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
--{
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
--              if (src == fsu_link_info[i].src.chno &&
--                  sink == fsu_link_info[i].sink.chno)
--                      return &fsu_link_info[i];
--      }
--
--      return NULL;
--}
--
--/*
-- * Links a source channel to a sink channel in the FSU.
-- */
--int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
--{
--      const struct fsu_link_info *link;
--      u32 src_reg, sink_reg;
--      unsigned long flags;
--
--      link = find_fsu_link_info(src_ch, sink_ch);
--      if (!link)
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      if (link->src.mask) {
--              src_reg = ipu_cm_read(ipu, link->src.reg);
--              src_reg &= ~link->src.mask;
--              src_reg |= link->src.val;
--              ipu_cm_write(ipu, src_reg, link->src.reg);
--      }
--
--      if (link->sink.mask) {
--              sink_reg = ipu_cm_read(ipu, link->sink.reg);
--              sink_reg &= ~link->sink.mask;
--              sink_reg |= link->sink.val;
--              ipu_cm_write(ipu, sink_reg, link->sink.reg);
--      }
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_fsu_link);
--
--/*
-- * Unlinks source and sink channels in the FSU.
-- */
--int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
--{
--      const struct fsu_link_info *link;
--      u32 src_reg, sink_reg;
--      unsigned long flags;
--
--      link = find_fsu_link_info(src_ch, sink_ch);
--      if (!link)
--              return -EINVAL;
--
--      spin_lock_irqsave(&ipu->lock, flags);
--
--      if (link->src.mask) {
--              src_reg = ipu_cm_read(ipu, link->src.reg);
--              src_reg &= ~link->src.mask;
--              ipu_cm_write(ipu, src_reg, link->src.reg);
--      }
--
--      if (link->sink.mask) {
--              sink_reg = ipu_cm_read(ipu, link->sink.reg);
--              sink_reg &= ~link->sink.mask;
--              ipu_cm_write(ipu, sink_reg, link->sink.reg);
--      }
--
--      spin_unlock_irqrestore(&ipu->lock, flags);
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
--
--/* Link IDMAC channels in the FSU */
--int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
--{
--      return ipu_fsu_link(src->ipu, src->num, sink->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_link);
--
--/* Unlink IDMAC channels in the FSU */
--int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
--{
--      return ipu_fsu_unlink(src->ipu, src->num, sink->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
--
--struct ipu_devtype {
--      const char *name;
--      unsigned long cm_ofs;
--      unsigned long cpmem_ofs;
--      unsigned long srm_ofs;
--      unsigned long tpm_ofs;
--      unsigned long csi0_ofs;
--      unsigned long csi1_ofs;
--      unsigned long ic_ofs;
--      unsigned long disp0_ofs;
--      unsigned long disp1_ofs;
--      unsigned long dc_tmpl_ofs;
--      unsigned long vdi_ofs;
--      enum ipuv3_type type;
--};
--
--static struct ipu_devtype ipu_type_imx51 = {
--      .name = "IPUv3EX",
--      .cm_ofs = 0x1e000000,
--      .cpmem_ofs = 0x1f000000,
--      .srm_ofs = 0x1f040000,
--      .tpm_ofs = 0x1f060000,
--      .csi0_ofs = 0x1e030000,
--      .csi1_ofs = 0x1e038000,
--      .ic_ofs = 0x1e020000,
--      .disp0_ofs = 0x1e040000,
--      .disp1_ofs = 0x1e048000,
--      .dc_tmpl_ofs = 0x1f080000,
--      .vdi_ofs = 0x1e068000,
--      .type = IPUV3EX,
--};
--
--static struct ipu_devtype ipu_type_imx53 = {
--      .name = "IPUv3M",
--      .cm_ofs = 0x06000000,
--      .cpmem_ofs = 0x07000000,
--      .srm_ofs = 0x07040000,
--      .tpm_ofs = 0x07060000,
--      .csi0_ofs = 0x06030000,
--      .csi1_ofs = 0x06038000,
--      .ic_ofs = 0x06020000,
--      .disp0_ofs = 0x06040000,
--      .disp1_ofs = 0x06048000,
--      .dc_tmpl_ofs = 0x07080000,
--      .vdi_ofs = 0x06068000,
--      .type = IPUV3M,
--};
--
--static struct ipu_devtype ipu_type_imx6q = {
--      .name = "IPUv3H",
--      .cm_ofs = 0x00200000,
--      .cpmem_ofs = 0x00300000,
--      .srm_ofs = 0x00340000,
--      .tpm_ofs = 0x00360000,
--      .csi0_ofs = 0x00230000,
--      .csi1_ofs = 0x00238000,
--      .ic_ofs = 0x00220000,
--      .disp0_ofs = 0x00240000,
--      .disp1_ofs = 0x00248000,
--      .dc_tmpl_ofs = 0x00380000,
--      .vdi_ofs = 0x00268000,
--      .type = IPUV3H,
--};
--
--static const struct of_device_id imx_ipu_dt_ids[] = {
--      { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
--      { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
--      { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
--      { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
--      { /* sentinel */ }
--};
--MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
--
--static int ipu_submodules_init(struct ipu_soc *ipu,
--              struct platform_device *pdev, unsigned long ipu_base,
--              struct clk *ipu_clk)
--{
--      char *unit;
--      int ret;
--      struct device *dev = &pdev->dev;
--      const struct ipu_devtype *devtype = ipu->devtype;
--
--      ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
--      if (ret) {
--              unit = "cpmem";
--              goto err_cpmem;
--      }
--
--      ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
--                         IPU_CONF_CSI0_EN, ipu_clk);
--      if (ret) {
--              unit = "csi0";
--              goto err_csi_0;
--      }
--
--      ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
--                         IPU_CONF_CSI1_EN, ipu_clk);
--      if (ret) {
--              unit = "csi1";
--              goto err_csi_1;
--      }
--
--      ret = ipu_ic_init(ipu, dev,
--                        ipu_base + devtype->ic_ofs,
--                        ipu_base + devtype->tpm_ofs);
--      if (ret) {
--              unit = "ic";
--              goto err_ic;
--      }
--
--      ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
--                         IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
--                         IPU_CONF_IC_INPUT);
--      if (ret) {
--              unit = "vdi";
--              goto err_vdi;
--      }
--
--      ret = ipu_image_convert_init(ipu, dev);
--      if (ret) {
--              unit = "image_convert";
--              goto err_image_convert;
--      }
--
--      ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
--                        IPU_CONF_DI0_EN, ipu_clk);
--      if (ret) {
--              unit = "di0";
--              goto err_di_0;
--      }
--
--      ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
--                      IPU_CONF_DI1_EN, ipu_clk);
--      if (ret) {
--              unit = "di1";
--              goto err_di_1;
--      }
--
--      ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
--                      IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
--      if (ret) {
--              unit = "dc_template";
--              goto err_dc;
--      }
--
--      ret = ipu_dmfc_init(ipu, dev, ipu_base +
--                      devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
--      if (ret) {
--              unit = "dmfc";
--              goto err_dmfc;
--      }
--
--      ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
--      if (ret) {
--              unit = "dp";
--              goto err_dp;
--      }
--
--      ret = ipu_smfc_init(ipu, dev, ipu_base +
--                      devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
--      if (ret) {
--              unit = "smfc";
--              goto err_smfc;
--      }
--
--      return 0;
--
--err_smfc:
--      ipu_dp_exit(ipu);
--err_dp:
--      ipu_dmfc_exit(ipu);
--err_dmfc:
--      ipu_dc_exit(ipu);
--err_dc:
--      ipu_di_exit(ipu, 1);
--err_di_1:
--      ipu_di_exit(ipu, 0);
--err_di_0:
--      ipu_image_convert_exit(ipu);
--err_image_convert:
--      ipu_vdi_exit(ipu);
--err_vdi:
--      ipu_ic_exit(ipu);
--err_ic:
--      ipu_csi_exit(ipu, 1);
--err_csi_1:
--      ipu_csi_exit(ipu, 0);
--err_csi_0:
--      ipu_cpmem_exit(ipu);
--err_cpmem:
--      dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
--      return ret;
--}
--
--static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
--{
--      unsigned long status;
--      int i, bit, irq;
--
--      for (i = 0; i < num_regs; i++) {
--
--              status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
--              status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
--
--              for_each_set_bit(bit, &status, 32) {
--                      irq = irq_linear_revmap(ipu->domain,
--                                              regs[i] * 32 + bit);
--                      if (irq)
--                              generic_handle_irq(irq);
--              }
--      }
--}
--
--static void ipu_irq_handler(struct irq_desc *desc)
--{
--      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
--
--      chained_irq_enter(chip, desc);
--
--      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
--
--      chained_irq_exit(chip, desc);
--}
--
--static void ipu_err_irq_handler(struct irq_desc *desc)
--{
--      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      static const int int_reg[] = { 4, 5, 8, 9};
--
--      chained_irq_enter(chip, desc);
--
--      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
--
--      chained_irq_exit(chip, desc);
--}
--
--int ipu_map_irq(struct ipu_soc *ipu, int irq)
--{
--      int virq;
--
--      virq = irq_linear_revmap(ipu->domain, irq);
--      if (!virq)
--              virq = irq_create_mapping(ipu->domain, irq);
--
--      return virq;
--}
--EXPORT_SYMBOL_GPL(ipu_map_irq);
--
--int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
--              enum ipu_channel_irq irq_type)
--{
--      return ipu_map_irq(ipu, irq_type + channel->num);
--}
--EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
--
--static void ipu_submodules_exit(struct ipu_soc *ipu)
--{
--      ipu_smfc_exit(ipu);
--      ipu_dp_exit(ipu);
--      ipu_dmfc_exit(ipu);
--      ipu_dc_exit(ipu);
--      ipu_di_exit(ipu, 1);
--      ipu_di_exit(ipu, 0);
--      ipu_image_convert_exit(ipu);
--      ipu_vdi_exit(ipu);
--      ipu_ic_exit(ipu);
--      ipu_csi_exit(ipu, 1);
--      ipu_csi_exit(ipu, 0);
--      ipu_cpmem_exit(ipu);
--}
--
--static int platform_remove_devices_fn(struct device *dev, void *unused)
--{
--      struct platform_device *pdev = to_platform_device(dev);
--
--      platform_device_unregister(pdev);
--
--      return 0;
--}
--
--static void platform_device_unregister_children(struct platform_device *pdev)
--{
--      device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
--}
--
--struct ipu_platform_reg {
--      struct ipu_client_platformdata pdata;
--      const char *name;
--};
--
--/* These must be in the order of the corresponding device tree port nodes */
--static struct ipu_platform_reg client_reg[] = {
--      {
--              .pdata = {
--                      .csi = 0,
--                      .dma[0] = IPUV3_CHANNEL_CSI0,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-csi",
--      }, {
--              .pdata = {
--                      .csi = 1,
--                      .dma[0] = IPUV3_CHANNEL_CSI1,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-csi",
--      }, {
--              .pdata = {
--                      .di = 0,
--                      .dc = 5,
--                      .dp = IPU_DP_FLOW_SYNC_BG,
--                      .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
--                      .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
--              },
--              .name = "imx-ipuv3-crtc",
--      }, {
--              .pdata = {
--                      .di = 1,
--                      .dc = 1,
--                      .dp = -EINVAL,
--                      .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
--                      .dma[1] = -EINVAL,
--              },
--              .name = "imx-ipuv3-crtc",
--      },
--};
--
--static DEFINE_MUTEX(ipu_client_id_mutex);
--static int ipu_client_id;
--
--static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
--{
--      struct device *dev = ipu->dev;
--      unsigned i;
--      int id, ret;
--
--      mutex_lock(&ipu_client_id_mutex);
--      id = ipu_client_id;
--      ipu_client_id += ARRAY_SIZE(client_reg);
--      mutex_unlock(&ipu_client_id_mutex);
--
--      for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
--              struct ipu_platform_reg *reg = &client_reg[i];
--              struct platform_device *pdev;
--              struct device_node *of_node;
--
--              /* Associate subdevice with the corresponding port node */
--              of_node = of_graph_get_port_by_id(dev->of_node, i);
--              if (!of_node) {
--                      dev_info(dev,
--                               "no port@%d node in %pOF, not using %s%d\n",
--                               i, dev->of_node,
--                               (i / 2) ? "DI" : "CSI", i % 2);
--                      continue;
--              }
--
--              pdev = platform_device_alloc(reg->name, id++);
--              if (!pdev) {
--                      ret = -ENOMEM;
--                      goto err_register;
--              }
--
--              pdev->dev.parent = dev;
--
--              reg->pdata.of_node = of_node;
--              ret = platform_device_add_data(pdev, &reg->pdata,
--                                             sizeof(reg->pdata));
--              if (!ret)
--                      ret = platform_device_add(pdev);
--              if (ret) {
--                      platform_device_put(pdev);
--                      goto err_register;
--              }
--      }
--
--      return 0;
--
--err_register:
--      platform_device_unregister_children(to_platform_device(dev));
--
--      return ret;
--}
--
--
--static int ipu_irq_init(struct ipu_soc *ipu)
--{
--      struct irq_chip_generic *gc;
--      struct irq_chip_type *ct;
--      unsigned long unused[IPU_NUM_IRQS / 32] = {
--              0x400100d0, 0xffe000fd,
--              0x400100d0, 0xffe000fd,
--              0x400100d0, 0xffe000fd,
--              0x4077ffff, 0xffe7e1fd,
--              0x23fffffe, 0x8880fff0,
--              0xf98fe7d0, 0xfff81fff,
--              0x400100d0, 0xffe000fd,
--              0x00000000,
--      };
--      int ret, i;
--
--      ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
--                                          &irq_generic_chip_ops, ipu);
--      if (!ipu->domain) {
--              dev_err(ipu->dev, "failed to add irq domain\n");
--              return -ENODEV;
--      }
--
--      ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
--                                           handle_level_irq, 0, 0, 0);
--      if (ret < 0) {
--              dev_err(ipu->dev, "failed to alloc generic irq chips\n");
--              irq_domain_remove(ipu->domain);
--              return ret;
--      }
--
--      /* Mask and clear all interrupts */
--      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
--              ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
--              ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
--      }
--
--      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
--              gc = irq_get_domain_generic_chip(ipu->domain, i);
--              gc->reg_base = ipu->cm_reg;
--              gc->unused = unused[i / 32];
--              ct = gc->chip_types;
--              ct->chip.irq_ack = irq_gc_ack_set_bit;
--              ct->chip.irq_mask = irq_gc_mask_clr_bit;
--              ct->chip.irq_unmask = irq_gc_mask_set_bit;
--              ct->regs.ack = IPU_INT_STAT(i / 32);
--              ct->regs.mask = IPU_INT_CTRL(i / 32);
--      }
--
--      irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
--      irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
--                                       ipu);
--
--      return 0;
--}
--
--static void ipu_irq_exit(struct ipu_soc *ipu)
--{
--      int i, irq;
--
--      irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
--      irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
--
--      /* TODO: remove irq_domain_generic_chips */
--
--      for (i = 0; i < IPU_NUM_IRQS; i++) {
--              irq = irq_linear_revmap(ipu->domain, i);
--              if (irq)
--                      irq_dispose_mapping(irq);
--      }
--
--      irq_domain_remove(ipu->domain);
--}
--
--void ipu_dump(struct ipu_soc *ipu)
--{
--      int i;
--
--      dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CONF));
--      dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CONF));
--      dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
--      dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
--      dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
--      dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
--              ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
--      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
--      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
--      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
--      dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
--              ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
--      for (i = 0; i < 15; i++)
--              dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
--                      ipu_cm_read(ipu, IPU_INT_CTRL(i)));
--}
--EXPORT_SYMBOL_GPL(ipu_dump);
--
--static int ipu_probe(struct platform_device *pdev)
--{
--      struct device_node *np = pdev->dev.of_node;
--      struct ipu_soc *ipu;
--      struct resource *res;
--      unsigned long ipu_base;
--      int ret, irq_sync, irq_err;
--      const struct ipu_devtype *devtype;
--
--      devtype = of_device_get_match_data(&pdev->dev);
--      if (!devtype)
--              return -EINVAL;
--
--      irq_sync = platform_get_irq(pdev, 0);
--      irq_err = platform_get_irq(pdev, 1);
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--
--      dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
--                      irq_sync, irq_err);
--
--      if (!res || irq_sync < 0 || irq_err < 0)
--              return -ENODEV;
--
--      ipu_base = res->start;
--
--      ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
--      if (!ipu)
--              return -ENODEV;
--
--      ipu->id = of_alias_get_id(np, "ipu");
--      if (ipu->id < 0)
--              ipu->id = 0;
--
--      if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
--          IS_ENABLED(CONFIG_DRM)) {
--              ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
--                                                        "fsl,prg", ipu->id);
--              if (!ipu->prg_priv)
--                      return -EPROBE_DEFER;
--      }
--
--      ipu->devtype = devtype;
--      ipu->ipu_type = devtype->type;
--
--      spin_lock_init(&ipu->lock);
--      mutex_init(&ipu->channel_lock);
--      INIT_LIST_HEAD(&ipu->channels);
--
--      dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
--                      ipu_base + devtype->cm_ofs);
--      dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
--      dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
--                      ipu_base + devtype->cpmem_ofs);
--      dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
--                      ipu_base + devtype->csi0_ofs);
--      dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
--                      ipu_base + devtype->csi1_ofs);
--      dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
--                      ipu_base + devtype->ic_ofs);
--      dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
--                      ipu_base + devtype->disp0_ofs);
--      dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
--                      ipu_base + devtype->disp1_ofs);
--      dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
--                      ipu_base + devtype->srm_ofs);
--      dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
--                      ipu_base + devtype->tpm_ofs);
--      dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
--      dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
--      dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
--                      ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
--      dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
--                      ipu_base + devtype->vdi_ofs);
--
--      ipu->cm_reg = devm_ioremap(&pdev->dev,
--                      ipu_base + devtype->cm_ofs, PAGE_SIZE);
--      ipu->idmac_reg = devm_ioremap(&pdev->dev,
--                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
--                      PAGE_SIZE);
--
--      if (!ipu->cm_reg || !ipu->idmac_reg)
--              return -ENOMEM;
--
--      ipu->clk = devm_clk_get(&pdev->dev, "bus");
--      if (IS_ERR(ipu->clk)) {
--              ret = PTR_ERR(ipu->clk);
--              dev_err(&pdev->dev, "clk_get failed with %d", ret);
--              return ret;
--      }
--
--      platform_set_drvdata(pdev, ipu);
--
--      ret = clk_prepare_enable(ipu->clk);
--      if (ret) {
--              dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
--              return ret;
--      }
--
--      ipu->dev = &pdev->dev;
--      ipu->irq_sync = irq_sync;
--      ipu->irq_err = irq_err;
--
--      ret = device_reset(&pdev->dev);
--      if (ret) {
--              dev_err(&pdev->dev, "failed to reset: %d\n", ret);
--              goto out_failed_reset;
--      }
--      ret = ipu_memory_reset(ipu);
--      if (ret)
--              goto out_failed_reset;
--
--      ret = ipu_irq_init(ipu);
--      if (ret)
--              goto out_failed_irq;
--
--      /* Set MCU_T to divide MCU access window into 2 */
--      ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
--                      IPU_DISP_GEN);
--
--      ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
--      if (ret)
--              goto failed_submodules_init;
--
--      ret = ipu_add_client_devices(ipu, ipu_base);
--      if (ret) {
--              dev_err(&pdev->dev, "adding client devices failed with %d\n",
--                              ret);
--              goto failed_add_clients;
--      }
--
--      dev_info(&pdev->dev, "%s probed\n", devtype->name);
--
--      return 0;
--
--failed_add_clients:
--      ipu_submodules_exit(ipu);
--failed_submodules_init:
--      ipu_irq_exit(ipu);
--out_failed_irq:
--out_failed_reset:
--      clk_disable_unprepare(ipu->clk);
--      return ret;
--}
--
--static int ipu_remove(struct platform_device *pdev)
--{
--      struct ipu_soc *ipu = platform_get_drvdata(pdev);
--
--      platform_device_unregister_children(pdev);
--      ipu_submodules_exit(ipu);
--      ipu_irq_exit(ipu);
--
--      clk_disable_unprepare(ipu->clk);
--
--      return 0;
--}
--
--static struct platform_driver imx_ipu_driver = {
--      .driver = {
--              .name = "imx-ipuv3",
--              .of_match_table = imx_ipu_dt_ids,
--      },
--      .probe = ipu_probe,
--      .remove = ipu_remove,
--};
--
--static struct platform_driver * const drivers[] = {
--#if IS_ENABLED(CONFIG_DRM)
--      &ipu_pre_drv,
--      &ipu_prg_drv,
--#endif
--      &imx_ipu_driver,
--};
--
--static int __init imx_ipu_init(void)
--{
--      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_init(imx_ipu_init);
--
--static void __exit imx_ipu_exit(void)
--{
--      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
--}
--module_exit(imx_ipu_exit);
--
--MODULE_ALIAS("platform:imx-ipuv3");
--MODULE_DESCRIPTION("i.MX IPU v3 driver");
--MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
--MODULE_LICENSE("GPL");
---- a/drivers/gpu/imx/ipu-v3/ipu-cpmem.c
-+++ /dev/null
-@@ -1,976 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012 Mentor Graphics Inc.
-- * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--#include <linux/types.h>
--#include <linux/bitrev.h>
--#include <linux/io.h>
--#include <linux/sizes.h>
--#include <drm/drm_fourcc.h>
--#include "ipu-prv.h"
--
--struct ipu_cpmem_word {
--      u32 data[5];
--      u32 res[3];
--};
--
--struct ipu_ch_param {
--      struct ipu_cpmem_word word[2];
--};
--
--struct ipu_cpmem {
--      struct ipu_ch_param __iomem *base;
--      u32 module;
--      spinlock_t lock;
--      int use_count;
--      struct ipu_soc *ipu;
--};
--
--#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
--
--#define IPU_FIELD_UBO         IPU_CPMEM_WORD(0, 46, 22)
--#define IPU_FIELD_VBO         IPU_CPMEM_WORD(0, 68, 22)
--#define IPU_FIELD_IOX         IPU_CPMEM_WORD(0, 90, 4)
--#define IPU_FIELD_RDRW                IPU_CPMEM_WORD(0, 94, 1)
--#define IPU_FIELD_SO          IPU_CPMEM_WORD(0, 113, 1)
--#define IPU_FIELD_SLY         IPU_CPMEM_WORD(1, 102, 14)
--#define IPU_FIELD_SLUV                IPU_CPMEM_WORD(1, 128, 14)
--
--#define IPU_FIELD_XV          IPU_CPMEM_WORD(0, 0, 10)
--#define IPU_FIELD_YV          IPU_CPMEM_WORD(0, 10, 9)
--#define IPU_FIELD_XB          IPU_CPMEM_WORD(0, 19, 13)
--#define IPU_FIELD_YB          IPU_CPMEM_WORD(0, 32, 12)
--#define IPU_FIELD_NSB_B               IPU_CPMEM_WORD(0, 44, 1)
--#define IPU_FIELD_CF          IPU_CPMEM_WORD(0, 45, 1)
--#define IPU_FIELD_SX          IPU_CPMEM_WORD(0, 46, 12)
--#define IPU_FIELD_SY          IPU_CPMEM_WORD(0, 58, 11)
--#define IPU_FIELD_NS          IPU_CPMEM_WORD(0, 69, 10)
--#define IPU_FIELD_SDX         IPU_CPMEM_WORD(0, 79, 7)
--#define IPU_FIELD_SM          IPU_CPMEM_WORD(0, 86, 10)
--#define IPU_FIELD_SCC         IPU_CPMEM_WORD(0, 96, 1)
--#define IPU_FIELD_SCE         IPU_CPMEM_WORD(0, 97, 1)
--#define IPU_FIELD_SDY         IPU_CPMEM_WORD(0, 98, 7)
--#define IPU_FIELD_SDRX                IPU_CPMEM_WORD(0, 105, 1)
--#define IPU_FIELD_SDRY                IPU_CPMEM_WORD(0, 106, 1)
--#define IPU_FIELD_BPP         IPU_CPMEM_WORD(0, 107, 3)
--#define IPU_FIELD_DEC_SEL     IPU_CPMEM_WORD(0, 110, 2)
--#define IPU_FIELD_DIM         IPU_CPMEM_WORD(0, 112, 1)
--#define IPU_FIELD_BNDM                IPU_CPMEM_WORD(0, 114, 3)
--#define IPU_FIELD_BM          IPU_CPMEM_WORD(0, 117, 2)
--#define IPU_FIELD_ROT         IPU_CPMEM_WORD(0, 119, 1)
--#define IPU_FIELD_ROT_HF_VF   IPU_CPMEM_WORD(0, 119, 3)
--#define IPU_FIELD_HF          IPU_CPMEM_WORD(0, 120, 1)
--#define IPU_FIELD_VF          IPU_CPMEM_WORD(0, 121, 1)
--#define IPU_FIELD_THE         IPU_CPMEM_WORD(0, 122, 1)
--#define IPU_FIELD_CAP         IPU_CPMEM_WORD(0, 123, 1)
--#define IPU_FIELD_CAE         IPU_CPMEM_WORD(0, 124, 1)
--#define IPU_FIELD_FW          IPU_CPMEM_WORD(0, 125, 13)
--#define IPU_FIELD_FH          IPU_CPMEM_WORD(0, 138, 12)
--#define IPU_FIELD_EBA0                IPU_CPMEM_WORD(1, 0, 29)
--#define IPU_FIELD_EBA1                IPU_CPMEM_WORD(1, 29, 29)
--#define IPU_FIELD_ILO         IPU_CPMEM_WORD(1, 58, 20)
--#define IPU_FIELD_NPB         IPU_CPMEM_WORD(1, 78, 7)
--#define IPU_FIELD_PFS         IPU_CPMEM_WORD(1, 85, 4)
--#define IPU_FIELD_ALU         IPU_CPMEM_WORD(1, 89, 1)
--#define IPU_FIELD_ALBM                IPU_CPMEM_WORD(1, 90, 3)
--#define IPU_FIELD_ID          IPU_CPMEM_WORD(1, 93, 2)
--#define IPU_FIELD_TH          IPU_CPMEM_WORD(1, 95, 7)
--#define IPU_FIELD_SL          IPU_CPMEM_WORD(1, 102, 14)
--#define IPU_FIELD_WID0                IPU_CPMEM_WORD(1, 116, 3)
--#define IPU_FIELD_WID1                IPU_CPMEM_WORD(1, 119, 3)
--#define IPU_FIELD_WID2                IPU_CPMEM_WORD(1, 122, 3)
--#define IPU_FIELD_WID3                IPU_CPMEM_WORD(1, 125, 3)
--#define IPU_FIELD_OFS0                IPU_CPMEM_WORD(1, 128, 5)
--#define IPU_FIELD_OFS1                IPU_CPMEM_WORD(1, 133, 5)
--#define IPU_FIELD_OFS2                IPU_CPMEM_WORD(1, 138, 5)
--#define IPU_FIELD_OFS3                IPU_CPMEM_WORD(1, 143, 5)
--#define IPU_FIELD_SXYS                IPU_CPMEM_WORD(1, 148, 1)
--#define IPU_FIELD_CRE         IPU_CPMEM_WORD(1, 149, 1)
--#define IPU_FIELD_DEC_SEL2    IPU_CPMEM_WORD(1, 150, 1)
--
--static inline struct ipu_ch_param __iomem *
--ipu_get_cpmem(struct ipuv3_channel *ch)
--{
--      struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
--
--      return cpmem->base + ch->num;
--}
--
--static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
--{
--      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
--      u32 bit = (wbs >> 8) % 160;
--      u32 size = wbs & 0xff;
--      u32 word = (wbs >> 8) / 160;
--      u32 i = bit / 32;
--      u32 ofs = bit % 32;
--      u32 mask = (1 << size) - 1;
--      u32 val;
--
--      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
--
--      val = readl(&base->word[word].data[i]);
--      val &= ~(mask << ofs);
--      val |= v << ofs;
--      writel(val, &base->word[word].data[i]);
--
--      if ((bit + size - 1) / 32 > i) {
--              val = readl(&base->word[word].data[i + 1]);
--              val &= ~(mask >> (ofs ? (32 - ofs) : 0));
--              val |= v >> (ofs ? (32 - ofs) : 0);
--              writel(val, &base->word[word].data[i + 1]);
--      }
--}
--
--static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
--{
--      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
--      u32 bit = (wbs >> 8) % 160;
--      u32 size = wbs & 0xff;
--      u32 word = (wbs >> 8) / 160;
--      u32 i = bit / 32;
--      u32 ofs = bit % 32;
--      u32 mask = (1 << size) - 1;
--      u32 val = 0;
--
--      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
--
--      val = (readl(&base->word[word].data[i]) >> ofs) & mask;
--
--      if ((bit + size - 1) / 32 > i) {
--              u32 tmp;
--
--              tmp = readl(&base->word[word].data[i + 1]);
--              tmp &= mask >> (ofs ? (32 - ofs) : 0);
--              val |= tmp << (ofs ? (32 - ofs) : 0);
--      }
--
--      return val;
--}
--
--/*
-- * The V4L2 spec defines packed RGB formats in memory byte order, which from
-- * point of view of the IPU corresponds to little-endian words with the first
-- * component in the least significant bits.
-- * The DRM pixel formats and IPU internal representation are ordered the other
-- * way around, with the first named component ordered at the most significant
-- * bits. Further, V4L2 formats are not well defined:
-- *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
-- * We choose the interpretation which matches GStreamer behavior.
-- */
--static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
--{
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_RGB565:
--              /*
--               * Here we choose the 'corrected' interpretation of RGBP, a
--               * little-endian 16-bit word with the red component at the most
--               * significant bits:
--               * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
--               */
--              return DRM_FORMAT_RGB565;
--      case V4L2_PIX_FMT_BGR24:
--              /* B G R <=> [24:0] R:G:B */
--              return DRM_FORMAT_RGB888;
--      case V4L2_PIX_FMT_RGB24:
--              /* R G B <=> [24:0] B:G:R */
--              return DRM_FORMAT_BGR888;
--      case V4L2_PIX_FMT_BGR32:
--              /* B G R A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_XRGB8888;
--      case V4L2_PIX_FMT_RGB32:
--              /* R G B A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_XBGR8888;
--      case V4L2_PIX_FMT_ABGR32:
--              /* B G R A <=> [32:0] A:R:G:B */
--              return DRM_FORMAT_ARGB8888;
--      case V4L2_PIX_FMT_XBGR32:
--              /* B G R X <=> [32:0] X:R:G:B */
--              return DRM_FORMAT_XRGB8888;
--      case V4L2_PIX_FMT_BGRA32:
--              /* A B G R <=> [32:0] R:G:B:A */
--              return DRM_FORMAT_RGBA8888;
--      case V4L2_PIX_FMT_BGRX32:
--              /* X B G R <=> [32:0] R:G:B:X */
--              return DRM_FORMAT_RGBX8888;
--      case V4L2_PIX_FMT_RGBA32:
--              /* R G B A <=> [32:0] A:B:G:R */
--              return DRM_FORMAT_ABGR8888;
--      case V4L2_PIX_FMT_RGBX32:
--              /* R G B X <=> [32:0] X:B:G:R */
--              return DRM_FORMAT_XBGR8888;
--      case V4L2_PIX_FMT_ARGB32:
--              /* A R G B <=> [32:0] B:G:R:A */
--              return DRM_FORMAT_BGRA8888;
--      case V4L2_PIX_FMT_XRGB32:
--              /* X R G B <=> [32:0] B:G:R:X */
--              return DRM_FORMAT_BGRX8888;
--      case V4L2_PIX_FMT_UYVY:
--              return DRM_FORMAT_UYVY;
--      case V4L2_PIX_FMT_YUYV:
--              return DRM_FORMAT_YUYV;
--      case V4L2_PIX_FMT_YUV420:
--              return DRM_FORMAT_YUV420;
--      case V4L2_PIX_FMT_YUV422P:
--              return DRM_FORMAT_YUV422;
--      case V4L2_PIX_FMT_YVU420:
--              return DRM_FORMAT_YVU420;
--      case V4L2_PIX_FMT_NV12:
--              return DRM_FORMAT_NV12;
--      case V4L2_PIX_FMT_NV16:
--              return DRM_FORMAT_NV16;
--      }
--
--      return -EINVAL;
--}
--
--void ipu_cpmem_zero(struct ipuv3_channel *ch)
--{
--      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
--      void __iomem *base = p;
--      int i;
--
--      for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
--              writel(0, base + i * sizeof(u32));
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
--
--void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
--
--void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
--
--void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
--
--void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
--{
--      struct ipu_soc *ipu = ch->ipu;
--      u32 val;
--
--      if (ipu->ipu_type == IPUV3EX)
--              ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
--
--      val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
--      val |= 1 << (ch->num % 32);
--      ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
--
--void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
--{
--      WARN_ON_ONCE(buf & 0x7);
--
--      if (bufnum)
--              ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
--      else
--              ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
--
--void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
--{
--      WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
--      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
--
--void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
--                             u32 pixelformat)
--{
--      u32 ilo, sly, sluv;
--
--      if (stride < 0) {
--              stride = -stride;
--              ilo = 0x100000 - (stride / 8);
--      } else {
--              ilo = stride / 8;
--      }
--
--      sly = (stride * 2) - 1;
--
--      switch (pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--      case V4L2_PIX_FMT_YVU420:
--              sluv = stride / 2 - 1;
--              break;
--      case V4L2_PIX_FMT_NV12:
--              sluv = stride - 1;
--              break;
--      case V4L2_PIX_FMT_YUV422P:
--              sluv = stride - 1;
--              break;
--      case V4L2_PIX_FMT_NV16:
--              sluv = stride * 2 - 1;
--              break;
--      default:
--              sluv = 0;
--              break;
--      }
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
--      if (sluv)
--              ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
--
--void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
--{
--      id &= 0x3;
--      ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
--
--int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
--{
--      return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
--
--void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
--};
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
--
--void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
--{
--      ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
--
--void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
--                          enum ipu_rotate_mode rot)
--{
--      u32 temp_rot = bitrev8(rot) >> 5;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
--
--int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
--                           const struct ipu_rgb *rgb)
--{
--      int bpp = 0, npb = 0, ro, go, bo, to;
--
--      ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
--      go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
--      bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
--      to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
--      ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
--
--      if (rgb->transp.length) {
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
--                              rgb->transp.length - 1);
--              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
--      } else {
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
--              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
--                              rgb->bits_per_pixel);
--      }
--
--      switch (rgb->bits_per_pixel) {
--      case 32:
--              bpp = 0;
--              npb = 15;
--              break;
--      case 24:
--              bpp = 1;
--              npb = 19;
--              break;
--      case 16:
--              bpp = 3;
--              npb = 31;
--              break;
--      case 8:
--              bpp = 5;
--              npb = 63;
--              break;
--      default:
--              return -EINVAL;
--      }
--      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
--      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
--
--int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
--{
--      int bpp = 0, npb = 0;
--
--      switch (width) {
--      case 32:
--              bpp = 0;
--              npb = 15;
--              break;
--      case 24:
--              bpp = 1;
--              npb = 19;
--              break;
--      case 16:
--              bpp = 3;
--              npb = 31;
--              break;
--      case 8:
--              bpp = 5;
--              npb = 63;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
--      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
--      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
--
--void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
--{
--      switch (pixel_format) {
--      case V4L2_PIX_FMT_UYVY:
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
--              break;
--      case V4L2_PIX_FMT_YUYV:
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
--              break;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
--
--void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
--                                 unsigned int uv_stride,
--                                 unsigned int u_offset, unsigned int v_offset)
--{
--      WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
--      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
--
--static const struct ipu_rgb def_xrgb_32 = {
--      .red    = { .offset = 16, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset =  0, .length = 8, },
--      .transp = { .offset = 24, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_xbgr_32 = {
--      .red    = { .offset =  0, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset = 16, .length = 8, },
--      .transp = { .offset = 24, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_rgbx_32 = {
--      .red    = { .offset = 24, .length = 8, },
--      .green  = { .offset = 16, .length = 8, },
--      .blue   = { .offset =  8, .length = 8, },
--      .transp = { .offset =  0, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_bgrx_32 = {
--      .red    = { .offset =  8, .length = 8, },
--      .green  = { .offset = 16, .length = 8, },
--      .blue   = { .offset = 24, .length = 8, },
--      .transp = { .offset =  0, .length = 8, },
--      .bits_per_pixel = 32,
--};
--
--static const struct ipu_rgb def_rgb_24 = {
--      .red    = { .offset = 16, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset =  0, .length = 8, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 24,
--};
--
--static const struct ipu_rgb def_bgr_24 = {
--      .red    = { .offset =  0, .length = 8, },
--      .green  = { .offset =  8, .length = 8, },
--      .blue   = { .offset = 16, .length = 8, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 24,
--};
--
--static const struct ipu_rgb def_rgb_16 = {
--      .red    = { .offset = 11, .length = 5, },
--      .green  = { .offset =  5, .length = 6, },
--      .blue   = { .offset =  0, .length = 5, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_bgr_16 = {
--      .red    = { .offset =  0, .length = 5, },
--      .green  = { .offset =  5, .length = 6, },
--      .blue   = { .offset = 11, .length = 5, },
--      .transp = { .offset =  0, .length = 0, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_argb_16 = {
--      .red    = { .offset = 10, .length = 5, },
--      .green  = { .offset =  5, .length = 5, },
--      .blue   = { .offset =  0, .length = 5, },
--      .transp = { .offset = 15, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_argb_16_4444 = {
--      .red    = { .offset =  8, .length = 4, },
--      .green  = { .offset =  4, .length = 4, },
--      .blue   = { .offset =  0, .length = 4, },
--      .transp = { .offset = 12, .length = 4, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_abgr_16 = {
--      .red    = { .offset =  0, .length = 5, },
--      .green  = { .offset =  5, .length = 5, },
--      .blue   = { .offset = 10, .length = 5, },
--      .transp = { .offset = 15, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_rgba_16 = {
--      .red    = { .offset = 11, .length = 5, },
--      .green  = { .offset =  6, .length = 5, },
--      .blue   = { .offset =  1, .length = 5, },
--      .transp = { .offset =  0, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--static const struct ipu_rgb def_bgra_16 = {
--      .red    = { .offset =  1, .length = 5, },
--      .green  = { .offset =  6, .length = 5, },
--      .blue   = { .offset = 11, .length = 5, },
--      .transp = { .offset =  0, .length = 1, },
--      .bits_per_pixel = 16,
--};
--
--#define Y_OFFSET(pix, x, y)   ((x) + pix->width * (y))
--#define U_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
--                               (pix->width * ((y) / 2) / 2) + (x) / 2)
--#define V_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
--                               (pix->width * pix->height / 4) +       \
--                               (pix->width * ((y) / 2) / 2) + (x) / 2)
--#define U2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
--                               (pix->width * (y) / 2) + (x) / 2)
--#define V2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
--                               (pix->width * pix->height / 2) +       \
--                               (pix->width * (y) / 2) + (x) / 2)
--#define UV_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
--                               (pix->width * ((y) / 2)) + (x))
--#define UV2_OFFSET(pix, x, y) ((pix->width * pix->height) +   \
--                               (pix->width * y) + (x))
--
--#define NUM_ALPHA_CHANNELS    7
--
--/* See Table 37-12. Alpha channels mapping. */
--static int ipu_channel_albm(int ch_num)
--{
--      switch (ch_num) {
--      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
--      case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
--      case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
--      case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
--      case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
--      case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
--      case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
--      default:
--              return -EINVAL;
--      }
--}
--
--static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
--{
--      struct ipu_soc *ipu = ch->ipu;
--      int albm;
--      u32 val;
--
--      albm = ipu_channel_albm(ch->num);
--      if (albm < 0)
--              return;
--
--      ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
--      ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
--      ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
--
--      val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
--      val |= BIT(ch->num);
--      ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
--}
--
--int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
--{
--      switch (drm_fourcc) {
--      case DRM_FORMAT_YUV420:
--      case DRM_FORMAT_YVU420:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUV422:
--      case DRM_FORMAT_YVU422:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUV444:
--      case DRM_FORMAT_YVU444:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_NV12:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_NV16:
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_UYVY:
--              /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_YUYV:
--              /* bits/pixel */
--              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
--              /* pix format */
--              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
--              /* burst size */
--              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
--              break;
--      case DRM_FORMAT_ABGR8888:
--      case DRM_FORMAT_XBGR8888:
--              ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
--              break;
--      case DRM_FORMAT_ARGB8888:
--      case DRM_FORMAT_XRGB8888:
--              ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
--              break;
--      case DRM_FORMAT_RGBA8888:
--      case DRM_FORMAT_RGBX8888:
--      case DRM_FORMAT_RGBX8888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
--              break;
--      case DRM_FORMAT_BGRA8888:
--      case DRM_FORMAT_BGRX8888:
--      case DRM_FORMAT_BGRX8888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
--              break;
--      case DRM_FORMAT_BGR888:
--      case DRM_FORMAT_BGR888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
--              break;
--      case DRM_FORMAT_RGB888:
--      case DRM_FORMAT_RGB888_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
--              break;
--      case DRM_FORMAT_RGB565:
--      case DRM_FORMAT_RGB565_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
--              break;
--      case DRM_FORMAT_BGR565:
--      case DRM_FORMAT_BGR565_A8:
--              ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
--              break;
--      case DRM_FORMAT_ARGB1555:
--              ipu_cpmem_set_format_rgb(ch, &def_argb_16);
--              break;
--      case DRM_FORMAT_ABGR1555:
--              ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
--              break;
--      case DRM_FORMAT_RGBA5551:
--              ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
--              break;
--      case DRM_FORMAT_BGRA5551:
--              ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
--              break;
--      case DRM_FORMAT_ARGB4444:
--              ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      switch (drm_fourcc) {
--      case DRM_FORMAT_RGB565_A8:
--      case DRM_FORMAT_BGR565_A8:
--      case DRM_FORMAT_RGB888_A8:
--      case DRM_FORMAT_BGR888_A8:
--      case DRM_FORMAT_RGBX8888_A8:
--      case DRM_FORMAT_BGRX8888_A8:
--              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
--              ipu_cpmem_set_separate_alpha(ch);
--              break;
--      default:
--              break;
--      }
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
--
--int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
--{
--      struct v4l2_pix_format *pix = &image->pix;
--      int offset, u_offset, v_offset;
--      int ret = 0;
--
--      pr_debug("%s: resolution: %dx%d stride: %d\n",
--               __func__, pix->width, pix->height,
--               pix->bytesperline);
--
--      ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
--      ipu_cpmem_set_stride(ch, pix->bytesperline);
--
--      ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
--
--      switch (pix->pixelformat) {
--      case V4L2_PIX_FMT_YUV420:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : U_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : V_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_YVU420:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : V_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : U_OFFSET(pix, image->rect.left,
--                                                 image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_YUV422P:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : U2_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--              v_offset = image->v_offset ?
--                      image->v_offset : V2_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_NV12:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : UV_OFFSET(pix, image->rect.left,
--                                                  image->rect.top) - offset;
--              v_offset = image->v_offset ? image->v_offset : 0;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_NV16:
--              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
--              u_offset = image->u_offset ?
--                      image->u_offset : UV2_OFFSET(pix, image->rect.left,
--                                                   image->rect.top) - offset;
--              v_offset = image->v_offset ? image->v_offset : 0;
--
--              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
--                                            u_offset, v_offset);
--              break;
--      case V4L2_PIX_FMT_UYVY:
--      case V4L2_PIX_FMT_YUYV:
--      case V4L2_PIX_FMT_RGB565:
--              offset = image->rect.left * 2 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_RGB32:
--      case V4L2_PIX_FMT_BGR32:
--      case V4L2_PIX_FMT_ABGR32:
--      case V4L2_PIX_FMT_XBGR32:
--      case V4L2_PIX_FMT_BGRA32:
--      case V4L2_PIX_FMT_BGRX32:
--      case V4L2_PIX_FMT_RGBA32:
--      case V4L2_PIX_FMT_RGBX32:
--      case V4L2_PIX_FMT_ARGB32:
--      case V4L2_PIX_FMT_XRGB32:
--              offset = image->rect.left * 4 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_RGB24:
--      case V4L2_PIX_FMT_BGR24:
--              offset = image->rect.left * 3 +
--                      image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_SBGGR8:
--      case V4L2_PIX_FMT_SGBRG8:
--      case V4L2_PIX_FMT_SGRBG8:
--      case V4L2_PIX_FMT_SRGGB8:
--      case V4L2_PIX_FMT_GREY:
--              offset = image->rect.left + image->rect.top * pix->bytesperline;
--              break;
--      case V4L2_PIX_FMT_SBGGR16:
--      case V4L2_PIX_FMT_SGBRG16:
--      case V4L2_PIX_FMT_SGRBG16:
--      case V4L2_PIX_FMT_SRGGB16:
--      case V4L2_PIX_FMT_Y16:
--              offset = image->rect.left * 2 +
--                       image->rect.top * pix->bytesperline;
--              break;
--      default:
--              /* This should not happen */
--              WARN_ON(1);
--              offset = 0;
--              ret = -EINVAL;
--      }
--
--      ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
--      ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
--
--void ipu_cpmem_dump(struct ipuv3_channel *ch)
--{
--      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
--      struct ipu_soc *ipu = ch->ipu;
--      int chno = ch->num;
--
--      dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
--              readl(&p->word[0].data[0]),
--              readl(&p->word[0].data[1]),
--              readl(&p->word[0].data[2]),
--              readl(&p->word[0].data[3]),
--              readl(&p->word[0].data[4]));
--      dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
--              readl(&p->word[1].data[0]),
--              readl(&p->word[1].data[1]),
--              readl(&p->word[1].data[2]),
--              readl(&p->word[1].data[3]),
--              readl(&p->word[1].data[4]));
--      dev_dbg(ipu->dev, "PFS 0x%x, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
--      dev_dbg(ipu->dev, "BPP 0x%x, ",
--              ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
--      dev_dbg(ipu->dev, "NPB 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
--
--      dev_dbg(ipu->dev, "FW %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_FW));
--      dev_dbg(ipu->dev, "FH %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_FH));
--      dev_dbg(ipu->dev, "EBA0 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
--      dev_dbg(ipu->dev, "EBA1 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
--      dev_dbg(ipu->dev, "Stride %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SL));
--      dev_dbg(ipu->dev, "scan_order %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SO));
--      dev_dbg(ipu->dev, "uv_stride %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
--      dev_dbg(ipu->dev, "u_offset 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
--      dev_dbg(ipu->dev, "v_offset 0x%x\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
--
--      dev_dbg(ipu->dev, "Width0 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
--      dev_dbg(ipu->dev, "Width1 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
--      dev_dbg(ipu->dev, "Width2 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
--      dev_dbg(ipu->dev, "Width3 %d+1, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
--      dev_dbg(ipu->dev, "Offset0 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
--      dev_dbg(ipu->dev, "Offset1 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
--      dev_dbg(ipu->dev, "Offset2 %d, ",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
--      dev_dbg(ipu->dev, "Offset3 %d\n",
--               ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
--}
--EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
--
--int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
--{
--      struct ipu_cpmem *cpmem;
--
--      cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
--      if (!cpmem)
--              return -ENOMEM;
--
--      ipu->cpmem_priv = cpmem;
--
--      spin_lock_init(&cpmem->lock);
--      cpmem->base = devm_ioremap(dev, base, SZ_128K);
--      if (!cpmem->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
--              base, cpmem->base);
--      cpmem->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_cpmem_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-csi.c
-+++ /dev/null
-@@ -1,821 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2014 Mentor Graphics Inc.
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/delay.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/platform_device.h>
--#include <linux/videodev2.h>
--#include <uapi/linux/v4l2-mediabus.h>
--#include <linux/clk.h>
--#include <linux/clk-provider.h>
--#include <linux/clkdev.h>
--
--#include "ipu-prv.h"
--
--struct ipu_csi {
--      void __iomem *base;
--      int id;
--      u32 module;
--      struct clk *clk_ipu;    /* IPU bus clock */
--      spinlock_t lock;
--      bool inuse;
--      struct ipu_soc *ipu;
--};
--
--/* CSI Register Offsets */
--#define CSI_SENS_CONF         0x0000
--#define CSI_SENS_FRM_SIZE     0x0004
--#define CSI_ACT_FRM_SIZE      0x0008
--#define CSI_OUT_FRM_CTRL      0x000c
--#define CSI_TST_CTRL          0x0010
--#define CSI_CCIR_CODE_1               0x0014
--#define CSI_CCIR_CODE_2               0x0018
--#define CSI_CCIR_CODE_3               0x001c
--#define CSI_MIPI_DI           0x0020
--#define CSI_SKIP              0x0024
--#define CSI_CPD_CTRL          0x0028
--#define CSI_CPD_RC(n)         (0x002c + ((n)*4))
--#define CSI_CPD_RS(n)         (0x004c + ((n)*4))
--#define CSI_CPD_GRC(n)                (0x005c + ((n)*4))
--#define CSI_CPD_GRS(n)                (0x007c + ((n)*4))
--#define CSI_CPD_GBC(n)                (0x008c + ((n)*4))
--#define CSI_CPD_GBS(n)                (0x00Ac + ((n)*4))
--#define CSI_CPD_BC(n)         (0x00Bc + ((n)*4))
--#define CSI_CPD_BS(n)         (0x00Dc + ((n)*4))
--#define CSI_CPD_OFFSET1               0x00ec
--#define CSI_CPD_OFFSET2               0x00f0
--
--/* CSI Register Fields */
--#define CSI_SENS_CONF_DATA_FMT_SHIFT          8
--#define CSI_SENS_CONF_DATA_FMT_MASK           0x00000700
--#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444     0L
--#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV    1L
--#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY    2L
--#define CSI_SENS_CONF_DATA_FMT_BAYER          3L
--#define CSI_SENS_CONF_DATA_FMT_RGB565         4L
--#define CSI_SENS_CONF_DATA_FMT_RGB555         5L
--#define CSI_SENS_CONF_DATA_FMT_RGB444         6L
--#define CSI_SENS_CONF_DATA_FMT_JPEG           7L
--
--#define CSI_SENS_CONF_VSYNC_POL_SHIFT         0
--#define CSI_SENS_CONF_HSYNC_POL_SHIFT         1
--#define CSI_SENS_CONF_DATA_POL_SHIFT          2
--#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT               3
--#define CSI_SENS_CONF_SENS_PRTCL_MASK         0x00000070
--#define CSI_SENS_CONF_SENS_PRTCL_SHIFT                4
--#define CSI_SENS_CONF_PACK_TIGHT_SHIFT                7
--#define CSI_SENS_CONF_DATA_WIDTH_SHIFT                11
--#define CSI_SENS_CONF_EXT_VSYNC_SHIFT         15
--#define CSI_SENS_CONF_DIVRATIO_SHIFT          16
--
--#define CSI_SENS_CONF_DIVRATIO_MASK           0x00ff0000
--#define CSI_SENS_CONF_DATA_DEST_SHIFT         24
--#define CSI_SENS_CONF_DATA_DEST_MASK          0x07000000
--#define CSI_SENS_CONF_JPEG8_EN_SHIFT          27
--#define CSI_SENS_CONF_JPEG_EN_SHIFT           28
--#define CSI_SENS_CONF_FORCE_EOF_SHIFT         29
--#define CSI_SENS_CONF_DATA_EN_POL_SHIFT               31
--
--#define CSI_DATA_DEST_IC                      2
--#define CSI_DATA_DEST_IDMAC                   4
--
--#define CSI_CCIR_ERR_DET_EN                   0x01000000
--#define CSI_HORI_DOWNSIZE_EN                  0x80000000
--#define CSI_VERT_DOWNSIZE_EN                  0x40000000
--#define CSI_TEST_GEN_MODE_EN                  0x01000000
--
--#define CSI_HSC_MASK                          0x1fff0000
--#define CSI_HSC_SHIFT                         16
--#define CSI_VSC_MASK                          0x00000fff
--#define CSI_VSC_SHIFT                         0
--
--#define CSI_TEST_GEN_R_MASK                   0x000000ff
--#define CSI_TEST_GEN_R_SHIFT                  0
--#define CSI_TEST_GEN_G_MASK                   0x0000ff00
--#define CSI_TEST_GEN_G_SHIFT                  8
--#define CSI_TEST_GEN_B_MASK                   0x00ff0000
--#define CSI_TEST_GEN_B_SHIFT                  16
--
--#define CSI_MAX_RATIO_SKIP_SMFC_MASK          0x00000007
--#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT         0
--#define CSI_SKIP_SMFC_MASK                    0x000000f8
--#define CSI_SKIP_SMFC_SHIFT                   3
--#define CSI_ID_2_SKIP_MASK                    0x00000300
--#define CSI_ID_2_SKIP_SHIFT                   8
--
--#define CSI_COLOR_FIRST_ROW_MASK              0x00000002
--#define CSI_COLOR_FIRST_COMP_MASK             0x00000001
--
--/* MIPI CSI-2 data types */
--#define MIPI_DT_YUV420                0x18 /* YYY.../UYVY.... */
--#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY...   */
--#define MIPI_DT_YUV422                0x1e /* UYVY...         */
--#define MIPI_DT_RGB444                0x20
--#define MIPI_DT_RGB555                0x21
--#define MIPI_DT_RGB565                0x22
--#define MIPI_DT_RGB666                0x23
--#define MIPI_DT_RGB888                0x24
--#define MIPI_DT_RAW6          0x28
--#define MIPI_DT_RAW7          0x29
--#define MIPI_DT_RAW8          0x2a
--#define MIPI_DT_RAW10         0x2b
--#define MIPI_DT_RAW12         0x2c
--#define MIPI_DT_RAW14         0x2d
--
--/*
-- * Bitfield of CSI bus signal polarities and modes.
-- */
--struct ipu_csi_bus_config {
--      unsigned data_width:4;
--      unsigned clk_mode:3;
--      unsigned ext_vsync:1;
--      unsigned vsync_pol:1;
--      unsigned hsync_pol:1;
--      unsigned pixclk_pol:1;
--      unsigned data_pol:1;
--      unsigned sens_clksrc:1;
--      unsigned pack_tight:1;
--      unsigned force_eof:1;
--      unsigned data_en_pol:1;
--
--      unsigned data_fmt;
--      unsigned mipi_dt;
--};
--
--/*
-- * Enumeration of CSI data bus widths.
-- */
--enum ipu_csi_data_width {
--      IPU_CSI_DATA_WIDTH_4   = 0,
--      IPU_CSI_DATA_WIDTH_8   = 1,
--      IPU_CSI_DATA_WIDTH_10  = 3,
--      IPU_CSI_DATA_WIDTH_12  = 5,
--      IPU_CSI_DATA_WIDTH_16  = 9,
--};
--
--/*
-- * Enumeration of CSI clock modes.
-- */
--enum ipu_csi_clk_mode {
--      IPU_CSI_CLK_MODE_GATED_CLK,
--      IPU_CSI_CLK_MODE_NONGATED_CLK,
--      IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
--      IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
--      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
--      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
--      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
--      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
--};
--
--static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
--{
--      return readl(csi->base + offset);
--}
--
--static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
--                               unsigned offset)
--{
--      writel(value, csi->base + offset);
--}
--
--/*
-- * Set mclk division ratio for generating test mode mclk. Only used
-- * for test generator.
-- */
--static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
--                                      u32 ipu_clk)
--{
--      u32 temp;
--      int div_ratio;
--
--      div_ratio = (ipu_clk / pixel_clk) - 1;
--
--      if (div_ratio > 0xFF || div_ratio < 0) {
--              dev_err(csi->ipu->dev,
--                      "value of pixel_clk extends normal range\n");
--              return -EINVAL;
--      }
--
--      temp = ipu_csi_read(csi, CSI_SENS_CONF);
--      temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
--      ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
--                        CSI_SENS_CONF);
--
--      return 0;
--}
--
--/*
-- * Find the CSI data format and data width for the given V4L2 media
-- * bus pixel format code.
-- */
--static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
--                              enum v4l2_mbus_type mbus_type)
--{
--      switch (mbus_code) {
--      case MEDIA_BUS_FMT_BGR565_2X8_BE:
--      case MEDIA_BUS_FMT_BGR565_2X8_LE:
--      case MEDIA_BUS_FMT_RGB565_2X8_BE:
--      case MEDIA_BUS_FMT_RGB565_2X8_LE:
--              if (mbus_type == V4L2_MBUS_CSI2_DPHY)
--                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
--              else
--                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RGB565;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
--              cfg->mipi_dt = MIPI_DT_RGB444;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
--              cfg->mipi_dt = MIPI_DT_RGB555;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_RGB888_1X24:
--      case MEDIA_BUS_FMT_BGR888_1X24:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
--              cfg->mipi_dt = MIPI_DT_RGB888;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_UYVY8_2X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_YUYV8_2X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_UYVY8_1X16:
--      case MEDIA_BUS_FMT_YUYV8_1X16:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_YUV422;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_16;
--              break;
--      case MEDIA_BUS_FMT_SBGGR8_1X8:
--      case MEDIA_BUS_FMT_SGBRG8_1X8:
--      case MEDIA_BUS_FMT_SGRBG8_1X8:
--      case MEDIA_BUS_FMT_SRGGB8_1X8:
--      case MEDIA_BUS_FMT_Y8_1X8:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW8;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
--      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW10;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      case MEDIA_BUS_FMT_SBGGR10_1X10:
--      case MEDIA_BUS_FMT_SGBRG10_1X10:
--      case MEDIA_BUS_FMT_SGRBG10_1X10:
--      case MEDIA_BUS_FMT_SRGGB10_1X10:
--      case MEDIA_BUS_FMT_Y10_1X10:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW10;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_10;
--              break;
--      case MEDIA_BUS_FMT_SBGGR12_1X12:
--      case MEDIA_BUS_FMT_SGBRG12_1X12:
--      case MEDIA_BUS_FMT_SGRBG12_1X12:
--      case MEDIA_BUS_FMT_SRGGB12_1X12:
--      case MEDIA_BUS_FMT_Y12_1X12:
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
--              cfg->mipi_dt = MIPI_DT_RAW12;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_12;
--              break;
--      case MEDIA_BUS_FMT_JPEG_1X8:
--              /* TODO */
--              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
--              cfg->mipi_dt = MIPI_DT_RAW8;
--              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
--              break;
--      default:
--              return -EINVAL;
--      }
--
--      return 0;
--}
--
--/* translate alternate field mode based on given standard */
--static inline enum v4l2_field
--ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
--{
--      return (field != V4L2_FIELD_ALTERNATE) ? field :
--              ((std & V4L2_STD_525_60) ?
--               V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
--}
--
--/*
-- * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
-- */
--static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
--                          const struct v4l2_mbus_config *mbus_cfg,
--                          const struct v4l2_mbus_framefmt *mbus_fmt)
--{
--      int ret;
--
--      memset(csicfg, 0, sizeof(*csicfg));
--
--      ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
--      if (ret < 0)
--              return ret;
--
--      switch (mbus_cfg->type) {
--      case V4L2_MBUS_PARALLEL:
--              csicfg->ext_vsync = 1;
--              csicfg->vsync_pol = (mbus_cfg->flags &
--                                   V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
--              csicfg->hsync_pol = (mbus_cfg->flags &
--                                   V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
--              csicfg->pixclk_pol = (mbus_cfg->flags &
--                                    V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
--              csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
--              break;
--      case V4L2_MBUS_BT656:
--              csicfg->ext_vsync = 0;
--              if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
--                  mbus_fmt->field == V4L2_FIELD_ALTERNATE)
--                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
--              else
--                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
--              break;
--      case V4L2_MBUS_CSI2_DPHY:
--              /*
--               * MIPI CSI-2 requires non gated clock mode, all other
--               * parameters are not applicable for MIPI CSI-2 bus.
--               */
--              csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
--              break;
--      default:
--              /* will never get here, keep compiler quiet */
--              break;
--      }
--
--      return 0;
--}
--
--static int
--ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
--                              const struct v4l2_mbus_framefmt *infmt,
--                              const struct v4l2_mbus_framefmt *outfmt,
--                              v4l2_std_id std)
--{
--      enum v4l2_field infield, outfield;
--      bool swap_fields;
--
--      /* get translated field type of input and output */
--      infield = ipu_csi_translate_field(infmt->field, std);
--      outfield = ipu_csi_translate_field(outfmt->field, std);
--
--      /*
--       * Write the H-V-F codes the CSI will match against the
--       * incoming data for start/end of active and blanking
--       * field intervals. If input and output field types are
--       * sequential but not the same (one is SEQ_BT and the other
--       * is SEQ_TB), swap the F-bit so that the CSI will capture
--       * field 1 lines before field 0 lines.
--       */
--      swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
--                     V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
--                     infield != outfield);
--
--      if (!swap_fields) {
--              /*
--               * Field0BlankEnd  = 110, Field0BlankStart  = 010
--               * Field0ActiveEnd = 100, Field0ActiveStart = 000
--               * Field1BlankEnd  = 111, Field1BlankStart  = 011
--               * Field1ActiveEnd = 101, Field1ActiveStart = 001
--               */
--              ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
--                            CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
--      } else {
--              dev_dbg(csi->ipu->dev, "capture field swap\n");
--
--              /* same as above but with F-bit inverted */
--              ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
--                            CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
--      }
--
--      ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--
--      return 0;
--}
--
--
--int ipu_csi_init_interface(struct ipu_csi *csi,
--                         const struct v4l2_mbus_config *mbus_cfg,
--                         const struct v4l2_mbus_framefmt *infmt,
--                         const struct v4l2_mbus_framefmt *outfmt)
--{
--      struct ipu_csi_bus_config cfg;
--      unsigned long flags;
--      u32 width, height, data = 0;
--      v4l2_std_id std;
--      int ret;
--
--      ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
--      if (ret < 0)
--              return ret;
--
--      /* set default sensor frame width and height */
--      width = infmt->width;
--      height = infmt->height;
--      if (infmt->field == V4L2_FIELD_ALTERNATE)
--              height *= 2;
--
--      /* Set the CSI_SENS_CONF register remaining fields */
--      data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
--              cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
--              cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
--              cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
--              cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
--              cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
--              cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
--              cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
--              cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
--              cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
--              cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      ipu_csi_write(csi, data, CSI_SENS_CONF);
--
--      /* Set CCIR registers */
--
--      switch (cfg.clk_mode) {
--      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
--              ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--              break;
--      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
--              if (width == 720 && height == 480) {
--                      std = V4L2_STD_NTSC;
--                      height = 525;
--              } else if (width == 720 && height == 576) {
--                      std = V4L2_STD_PAL;
--                      height = 625;
--              } else {
--                      dev_err(csi->ipu->dev,
--                              "Unsupported interlaced video mode\n");
--                      ret = -EINVAL;
--                      goto out_unlock;
--              }
--
--              ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
--              if (ret)
--                      goto out_unlock;
--              break;
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
--              ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
--                                 CSI_CCIR_CODE_1);
--              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
--              break;
--      case IPU_CSI_CLK_MODE_GATED_CLK:
--      case IPU_CSI_CLK_MODE_NONGATED_CLK:
--              ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
--              break;
--      }
--
--      /* Setup sensor frame size */
--      ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
--                    CSI_SENS_FRM_SIZE);
--
--      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
--              ipu_csi_read(csi, CSI_SENS_CONF));
--      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
--              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
--
--out_unlock:
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
--
--bool ipu_csi_is_interlaced(struct ipu_csi *csi)
--{
--      unsigned long flags;
--      u32 sensor_protocol;
--
--      spin_lock_irqsave(&csi->lock, flags);
--      sensor_protocol =
--              (ipu_csi_read(csi, CSI_SENS_CONF) &
--               CSI_SENS_CONF_SENS_PRTCL_MASK) >>
--              CSI_SENS_CONF_SENS_PRTCL_SHIFT;
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      switch (sensor_protocol) {
--      case IPU_CSI_CLK_MODE_GATED_CLK:
--      case IPU_CSI_CLK_MODE_NONGATED_CLK:
--      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
--              return false;
--      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
--      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
--              return true;
--      default:
--              dev_err(csi->ipu->dev,
--                      "CSI %d sensor protocol unsupported\n", csi->id);
--              return false;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
--
--void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
--      w->width = (reg & 0xFFFF) + 1;
--      w->height = (reg >> 16 & 0xFFFF) + 1;
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
--      w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_get_window);
--
--void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
--                        CSI_ACT_FRM_SIZE);
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
--      reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
--      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_window);
--
--void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
--      reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
--      reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
--             (vert ? CSI_VERT_DOWNSIZE_EN : 0);
--      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
--
--void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
--                              u32 r_value, u32 g_value, u32 b_value,
--                              u32 pix_clk)
--{
--      unsigned long flags;
--      u32 ipu_clk = clk_get_rate(csi->clk_ipu);
--      u32 temp;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_TST_CTRL);
--
--      if (!active) {
--              temp &= ~CSI_TEST_GEN_MODE_EN;
--              ipu_csi_write(csi, temp, CSI_TST_CTRL);
--      } else {
--              /* Set sensb_mclk div_ratio */
--              ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
--
--              temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
--                        CSI_TEST_GEN_B_MASK);
--              temp |= CSI_TEST_GEN_MODE_EN;
--              temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
--                      (g_value << CSI_TEST_GEN_G_SHIFT) |
--                      (b_value << CSI_TEST_GEN_B_SHIFT);
--              ipu_csi_write(csi, temp, CSI_TST_CTRL);
--      }
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
--
--int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
--                            struct v4l2_mbus_framefmt *mbus_fmt)
--{
--      struct ipu_csi_bus_config cfg;
--      unsigned long flags;
--      u32 temp;
--      int ret;
--
--      if (vc > 3)
--              return -EINVAL;
--
--      ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
--      if (ret < 0)
--              return ret;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_MIPI_DI);
--      temp &= ~(0xff << (vc * 8));
--      temp |= (cfg.mipi_dt << (vc * 8));
--      ipu_csi_write(csi, temp, CSI_MIPI_DI);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
--
--int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
--                        u32 max_ratio, u32 id)
--{
--      unsigned long flags;
--      u32 temp;
--
--      if (max_ratio > 5 || id > 3)
--              return -EINVAL;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      temp = ipu_csi_read(csi, CSI_SKIP);
--      temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
--                CSI_SKIP_SMFC_MASK);
--      temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
--              (id << CSI_ID_2_SKIP_SHIFT) |
--              (skip << CSI_SKIP_SMFC_SHIFT);
--      ipu_csi_write(csi, temp, CSI_SKIP);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
--
--int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
--{
--      unsigned long flags;
--      u32 csi_sens_conf, dest;
--
--      if (csi_dest == IPU_CSI_DEST_IDMAC)
--              dest = CSI_DATA_DEST_IDMAC;
--      else
--              dest = CSI_DATA_DEST_IC; /* IC or VDIC */
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
--      csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
--      csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
--      ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
--
--      spin_unlock_irqrestore(&csi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
--
--int ipu_csi_enable(struct ipu_csi *csi)
--{
--      ipu_module_enable(csi->ipu, csi->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_enable);
--
--int ipu_csi_disable(struct ipu_csi *csi)
--{
--      ipu_module_disable(csi->ipu, csi->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_disable);
--
--struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
--{
--      unsigned long flags;
--      struct ipu_csi *csi, *ret;
--
--      if (id > 1)
--              return ERR_PTR(-EINVAL);
--
--      csi = ipu->csi_priv[id];
--      ret = csi;
--
--      spin_lock_irqsave(&csi->lock, flags);
--
--      if (csi->inuse) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      csi->inuse = true;
--unlock:
--      spin_unlock_irqrestore(&csi->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_csi_get);
--
--void ipu_csi_put(struct ipu_csi *csi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&csi->lock, flags);
--      csi->inuse = false;
--      spin_unlock_irqrestore(&csi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_csi_put);
--
--int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
--               unsigned long base, u32 module, struct clk *clk_ipu)
--{
--      struct ipu_csi *csi;
--
--      if (id > 1)
--              return -ENODEV;
--
--      csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
--      if (!csi)
--              return -ENOMEM;
--
--      ipu->csi_priv[id] = csi;
--
--      spin_lock_init(&csi->lock);
--      csi->module = module;
--      csi->id = id;
--      csi->clk_ipu = clk_ipu;
--      csi->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!csi->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
--              id, base, csi->base);
--      csi->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_csi_exit(struct ipu_soc *ipu, int id)
--{
--}
--
--void ipu_csi_dump(struct ipu_csi *csi)
--{
--      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
--              ipu_csi_read(csi, CSI_SENS_CONF));
--      dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
--              ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
--      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
--              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
--      dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
--              ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
--      dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
--              ipu_csi_read(csi, CSI_TST_CTRL));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_1));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_2));
--      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
--              ipu_csi_read(csi, CSI_CCIR_CODE_3));
--      dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
--              ipu_csi_read(csi, CSI_MIPI_DI));
--      dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
--              ipu_csi_read(csi, CSI_SKIP));
--}
--EXPORT_SYMBOL_GPL(ipu_csi_dump);
---- a/drivers/gpu/imx/ipu-v3/ipu-dc.c
-+++ /dev/null
-@@ -1,420 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/delay.h>
--#include <linux/interrupt.h>
--#include <linux/io.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DC_MAP_CONF_PTR(n)    (0x108 + ((n) & ~0x1) * 2)
--#define DC_MAP_CONF_VAL(n)    (0x144 + ((n) & ~0x1) * 2)
--
--#define DC_EVT_NF             0
--#define DC_EVT_NL             1
--#define DC_EVT_EOF            2
--#define DC_EVT_NFIELD         3
--#define DC_EVT_EOL            4
--#define DC_EVT_EOFIELD                5
--#define DC_EVT_NEW_ADDR               6
--#define DC_EVT_NEW_CHAN               7
--#define DC_EVT_NEW_DATA               8
--
--#define DC_EVT_NEW_ADDR_W_0   0
--#define DC_EVT_NEW_ADDR_W_1   1
--#define DC_EVT_NEW_CHAN_W_0   2
--#define DC_EVT_NEW_CHAN_W_1   3
--#define DC_EVT_NEW_DATA_W_0   4
--#define DC_EVT_NEW_DATA_W_1   5
--#define DC_EVT_NEW_ADDR_R_0   6
--#define DC_EVT_NEW_ADDR_R_1   7
--#define DC_EVT_NEW_CHAN_R_0   8
--#define DC_EVT_NEW_CHAN_R_1   9
--#define DC_EVT_NEW_DATA_R_0   10
--#define DC_EVT_NEW_DATA_R_1   11
--
--#define DC_WR_CH_CONF         0x0
--#define DC_WR_CH_ADDR         0x4
--#define DC_RL_CH(evt)         (8 + ((evt) & ~0x1) * 2)
--
--#define DC_GEN                        0xd4
--#define DC_DISP_CONF1(disp)   (0xd8 + (disp) * 4)
--#define DC_DISP_CONF2(disp)   (0xe8 + (disp) * 4)
--#define DC_STAT                       0x1c8
--
--#define WROD(lf)              (0x18 | ((lf) << 1))
--#define WRG                   0x01
--#define WCLK                  0xc9
--
--#define SYNC_WAVE 0
--#define NULL_WAVE (-1)
--
--#define DC_GEN_SYNC_1_6_SYNC  (2 << 1)
--#define DC_GEN_SYNC_PRIORITY_1        (1 << 7)
--
--#define DC_WR_CH_CONF_WORD_SIZE_8             (0 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_16            (1 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_24            (2 << 0)
--#define DC_WR_CH_CONF_WORD_SIZE_32            (3 << 0)
--#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)     (((i) & 0x1) << 3)
--#define DC_WR_CH_CONF_DISP_ID_SERIAL          (2 << 3)
--#define DC_WR_CH_CONF_DISP_ID_ASYNC           (3 << 4)
--#define DC_WR_CH_CONF_FIELD_MODE              (1 << 9)
--#define DC_WR_CH_CONF_PROG_TYPE_NORMAL                (4 << 5)
--#define DC_WR_CH_CONF_PROG_TYPE_MASK          (7 << 5)
--#define DC_WR_CH_CONF_PROG_DI_ID              (1 << 2)
--#define DC_WR_CH_CONF_PROG_DISP_ID(i)         (((i) & 0x1) << 3)
--
--#define IPU_DC_NUM_CHANNELS   10
--
--struct ipu_dc_priv;
--
--enum ipu_dc_map {
--      IPU_DC_MAP_RGB24,
--      IPU_DC_MAP_RGB565,
--      IPU_DC_MAP_GBR24, /* TVEv2 */
--      IPU_DC_MAP_BGR666,
--      IPU_DC_MAP_LVDS666,
--      IPU_DC_MAP_BGR24,
--};
--
--struct ipu_dc {
--      /* The display interface number assigned to this dc channel */
--      unsigned int            di;
--      void __iomem            *base;
--      struct ipu_dc_priv      *priv;
--      int                     chno;
--      bool                    in_use;
--};
--
--struct ipu_dc_priv {
--      void __iomem            *dc_reg;
--      void __iomem            *dc_tmpl_reg;
--      struct ipu_soc          *ipu;
--      struct device           *dev;
--      struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
--      struct mutex            mutex;
--      struct completion       comp;
--      int                     use_count;
--};
--
--static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
--{
--      u32 reg;
--
--      reg = readl(dc->base + DC_RL_CH(event));
--      reg &= ~(0xffff << (16 * (event & 0x1)));
--      reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
--      writel(reg, dc->base + DC_RL_CH(event));
--}
--
--static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
--              int map, int wave, int glue, int sync, int stop)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--      u32 reg1, reg2;
--
--      if (opcode == WCLK) {
--              reg1 = (operand << 20) & 0xfff00000;
--              reg2 = operand >> 12 | opcode << 1 | stop << 9;
--      } else if (opcode == WRG) {
--              reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
--              reg2 = operand >> 17 | opcode << 7 | stop << 9;
--      } else {
--              reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
--              reg2 = operand >> 12 | opcode << 4 | stop << 9;
--      }
--      writel(reg1, priv->dc_tmpl_reg + word * 8);
--      writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
--}
--
--static int ipu_bus_format_to_map(u32 fmt)
--{
--      switch (fmt) {
--      default:
--              WARN_ON(1);
--              /* fall-through */
--      case MEDIA_BUS_FMT_RGB888_1X24:
--              return IPU_DC_MAP_RGB24;
--      case MEDIA_BUS_FMT_RGB565_1X16:
--              return IPU_DC_MAP_RGB565;
--      case MEDIA_BUS_FMT_GBR888_1X24:
--              return IPU_DC_MAP_GBR24;
--      case MEDIA_BUS_FMT_RGB666_1X18:
--              return IPU_DC_MAP_BGR666;
--      case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
--              return IPU_DC_MAP_LVDS666;
--      case MEDIA_BUS_FMT_BGR888_1X24:
--              return IPU_DC_MAP_BGR24;
--      }
--}
--
--int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
--              u32 bus_format, u32 width)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--      int addr, sync;
--      u32 reg = 0;
--      int map;
--
--      dc->di = ipu_di_get_num(di);
--
--      map = ipu_bus_format_to_map(bus_format);
--
--      /*
--       * In interlaced mode we need more counters to create the asymmetric
--       * per-field VSYNC signals. The pixel active signal synchronising DC
--       * to DI moves to signal generator #6 (see ipu-di.c). In progressive
--       * mode counter #5 is used.
--       */
--      sync = interlaced ? 6 : 5;
--
--      /* Reserve 5 microcode template words for each DI */
--      if (dc->di)
--              addr = 5;
--      else
--              addr = 0;
--
--      if (interlaced) {
--              dc_link_event(dc, DC_EVT_NL, addr, 3);
--              dc_link_event(dc, DC_EVT_EOL, addr, 2);
--              dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
--
--              /* Init template microcode */
--              dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
--      } else {
--              dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
--              dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
--              dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
--
--              /* Init template microcode */
--              dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
--              dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
--              dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
--              dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
--      }
--
--      dc_link_event(dc, DC_EVT_NF, 0, 0);
--      dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
--      dc_link_event(dc, DC_EVT_EOF, 0, 0);
--      dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
--      dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
--      dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
--
--      reg = readl(dc->base + DC_WR_CH_CONF);
--      if (interlaced)
--              reg |= DC_WR_CH_CONF_FIELD_MODE;
--      else
--              reg &= ~DC_WR_CH_CONF_FIELD_MODE;
--      writel(reg, dc->base + DC_WR_CH_CONF);
--
--      writel(0x0, dc->base + DC_WR_CH_ADDR);
--      writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
--
--void ipu_dc_enable(struct ipu_soc *ipu)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_enable);
--
--void ipu_dc_enable_channel(struct ipu_dc *dc)
--{
--      u32 reg;
--
--      reg = readl(dc->base + DC_WR_CH_CONF);
--      reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
--      writel(reg, dc->base + DC_WR_CH_CONF);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
--
--void ipu_dc_disable_channel(struct ipu_dc *dc)
--{
--      u32 val;
--
--      val = readl(dc->base + DC_WR_CH_CONF);
--      val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
--      writel(val, dc->base + DC_WR_CH_CONF);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
--
--void ipu_dc_disable(struct ipu_soc *ipu)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_disable);
--
--static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
--              int byte_num, int offset, int mask)
--{
--      int ptr = map * 3 + byte_num;
--      u32 reg;
--
--      reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
--      reg &= ~(0xffff << (16 * (ptr & 0x1)));
--      reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
--      writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
--
--      reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
--      reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
--      reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
--      writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
--}
--
--static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
--{
--      u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
--
--      writel(reg & ~(0xffff << (16 * (map & 0x1))),
--                   priv->dc_reg + DC_MAP_CONF_PTR(map));
--}
--
--struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
--{
--      struct ipu_dc_priv *priv = ipu->dc_priv;
--      struct ipu_dc *dc;
--
--      if (channel >= IPU_DC_NUM_CHANNELS)
--              return ERR_PTR(-ENODEV);
--
--      dc = &priv->channels[channel];
--
--      mutex_lock(&priv->mutex);
--
--      if (dc->in_use) {
--              mutex_unlock(&priv->mutex);
--              return ERR_PTR(-EBUSY);
--      }
--
--      dc->in_use = true;
--
--      mutex_unlock(&priv->mutex);
--
--      return dc;
--}
--EXPORT_SYMBOL_GPL(ipu_dc_get);
--
--void ipu_dc_put(struct ipu_dc *dc)
--{
--      struct ipu_dc_priv *priv = dc->priv;
--
--      mutex_lock(&priv->mutex);
--      dc->in_use = false;
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dc_put);
--
--int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long template_base)
--{
--      struct ipu_dc_priv *priv;
--      static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
--              0x78, 0, 0x94, 0xb4};
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      mutex_init(&priv->mutex);
--
--      priv->dev = dev;
--      priv->ipu = ipu;
--      priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
--      priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
--      if (!priv->dc_reg || !priv->dc_tmpl_reg)
--              return -ENOMEM;
--
--      for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
--              priv->channels[i].chno = i;
--              priv->channels[i].priv = priv;
--              priv->channels[i].base = priv->dc_reg + channel_offsets[i];
--      }
--
--      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
--                      DC_WR_CH_CONF_PROG_DI_ID,
--                      priv->channels[1].base + DC_WR_CH_CONF);
--      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
--                      priv->channels[5].base + DC_WR_CH_CONF);
--
--      writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
--              priv->dc_reg + DC_GEN);
--
--      ipu->dc_priv = priv;
--
--      dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
--                      base, template_base);
--
--      /* rgb24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
--
--      /* rgb565 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
--
--      /* gbr24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
--
--      /* bgr666 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
--
--      /* lvds666 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
--
--      /* bgr24 */
--      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
--      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
--
--      return 0;
--}
--
--void ipu_dc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-di.c
-+++ /dev/null
-@@ -1,745 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/module.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/platform_device.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--struct ipu_di {
--      void __iomem *base;
--      int id;
--      u32 module;
--      struct clk *clk_di;     /* display input clock */
--      struct clk *clk_ipu;    /* IPU bus clock */
--      struct clk *clk_di_pixel; /* resulting pixel clock */
--      bool inuse;
--      struct ipu_soc *ipu;
--};
--
--static DEFINE_MUTEX(di_mutex);
--
--struct di_sync_config {
--      int run_count;
--      int run_src;
--      int offset_count;
--      int offset_src;
--      int repeat_count;
--      int cnt_clr_src;
--      int cnt_polarity_gen_en;
--      int cnt_polarity_clr_src;
--      int cnt_polarity_trigger_src;
--      int cnt_up;
--      int cnt_down;
--};
--
--enum di_pins {
--      DI_PIN11 = 0,
--      DI_PIN12 = 1,
--      DI_PIN13 = 2,
--      DI_PIN14 = 3,
--      DI_PIN15 = 4,
--      DI_PIN16 = 5,
--      DI_PIN17 = 6,
--      DI_PIN_CS = 7,
--
--      DI_PIN_SER_CLK = 0,
--      DI_PIN_SER_RS = 1,
--};
--
--enum di_sync_wave {
--      DI_SYNC_NONE = 0,
--      DI_SYNC_CLK = 1,
--      DI_SYNC_INT_HSYNC = 2,
--      DI_SYNC_HSYNC = 3,
--      DI_SYNC_VSYNC = 4,
--      DI_SYNC_DE = 6,
--
--      DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
--      DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
--      DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
--};
--
--#define SYNC_WAVE 0
--
--#define DI_GENERAL            0x0000
--#define DI_BS_CLKGEN0         0x0004
--#define DI_BS_CLKGEN1         0x0008
--#define DI_SW_GEN0(gen)               (0x000c + 4 * ((gen) - 1))
--#define DI_SW_GEN1(gen)               (0x0030 + 4 * ((gen) - 1))
--#define DI_STP_REP(gen)               (0x0148 + 4 * (((gen) - 1)/2))
--#define DI_SYNC_AS_GEN                0x0054
--#define DI_DW_GEN(gen)                (0x0058 + 4 * (gen))
--#define DI_DW_SET(gen, set)   (0x0088 + 4 * ((gen) + 0xc * (set)))
--#define DI_SER_CONF           0x015c
--#define DI_SSC                        0x0160
--#define DI_POL                        0x0164
--#define DI_AW0                        0x0168
--#define DI_AW1                        0x016c
--#define DI_SCR_CONF           0x0170
--#define DI_STAT                       0x0174
--
--#define DI_SW_GEN0_RUN_COUNT(x)                       ((x) << 19)
--#define DI_SW_GEN0_RUN_SRC(x)                 ((x) << 16)
--#define DI_SW_GEN0_OFFSET_COUNT(x)            ((x) << 3)
--#define DI_SW_GEN0_OFFSET_SRC(x)              ((x) << 0)
--
--#define DI_SW_GEN1_CNT_POL_GEN_EN(x)          ((x) << 29)
--#define DI_SW_GEN1_CNT_CLR_SRC(x)             ((x) << 25)
--#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)     ((x) << 12)
--#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)         ((x) << 9)
--#define DI_SW_GEN1_CNT_DOWN(x)                        ((x) << 16)
--#define DI_SW_GEN1_CNT_UP(x)                  (x)
--#define DI_SW_GEN1_AUTO_RELOAD                        (0x10000000)
--
--#define DI_DW_GEN_ACCESS_SIZE_OFFSET          24
--#define DI_DW_GEN_COMPONENT_SIZE_OFFSET               16
--
--#define DI_GEN_POLARITY_1                     (1 << 0)
--#define DI_GEN_POLARITY_2                     (1 << 1)
--#define DI_GEN_POLARITY_3                     (1 << 2)
--#define DI_GEN_POLARITY_4                     (1 << 3)
--#define DI_GEN_POLARITY_5                     (1 << 4)
--#define DI_GEN_POLARITY_6                     (1 << 5)
--#define DI_GEN_POLARITY_7                     (1 << 6)
--#define DI_GEN_POLARITY_8                     (1 << 7)
--#define DI_GEN_POLARITY_DISP_CLK              (1 << 17)
--#define DI_GEN_DI_CLK_EXT                     (1 << 20)
--#define DI_GEN_DI_VSYNC_EXT                   (1 << 21)
--
--#define DI_POL_DRDY_DATA_POLARITY             (1 << 7)
--#define DI_POL_DRDY_POLARITY_15                       (1 << 4)
--
--#define DI_VSYNC_SEL_OFFSET                   13
--
--static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
--{
--      return readl(di->base + offset);
--}
--
--static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
--{
--      writel(value, di->base + offset);
--}
--
--static void ipu_di_data_wave_config(struct ipu_di *di,
--                                   int wave_gen,
--                                   int access_size, int component_size)
--{
--      u32 reg;
--      reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
--          (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
--      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
--}
--
--static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
--              int set, int up, int down)
--{
--      u32 reg;
--
--      reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
--      reg &= ~(0x3 << (di_pin * 2));
--      reg |= set << (di_pin * 2);
--      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
--
--      ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
--}
--
--static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
--              int start, int count)
--{
--      u32 reg;
--      int i;
--
--      for (i = 0; i < count; i++) {
--              struct di_sync_config *c = &config[i];
--              int wave_gen = start + i + 1;
--
--              if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
--                              (c->repeat_count >= 0x1000) ||
--                              (c->cnt_up >= 0x400) ||
--                              (c->cnt_down >= 0x400)) {
--                      dev_err(di->ipu->dev, "DI%d counters out of range.\n",
--                                      di->id);
--                      return;
--              }
--
--              reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
--                      DI_SW_GEN0_RUN_SRC(c->run_src) |
--                      DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
--                      DI_SW_GEN0_OFFSET_SRC(c->offset_src);
--              ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
--
--              reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
--                      DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
--                      DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
--                                      c->cnt_polarity_trigger_src) |
--                      DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
--                      DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
--                      DI_SW_GEN1_CNT_UP(c->cnt_up);
--
--              /* Enable auto reload */
--              if (c->repeat_count == 0)
--                      reg |= DI_SW_GEN1_AUTO_RELOAD;
--
--              ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
--
--              reg = ipu_di_read(di, DI_STP_REP(wave_gen));
--              reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
--              reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
--              ipu_di_write(di, reg, DI_STP_REP(wave_gen));
--      }
--}
--
--static void ipu_di_sync_config_interlaced(struct ipu_di *di,
--              struct ipu_di_signal_cfg *sig)
--{
--      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
--              sig->mode.hback_porch + sig->mode.hfront_porch;
--      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
--              sig->mode.vback_porch + sig->mode.vfront_porch;
--      struct di_sync_config cfg[] = {
--              {
--                      /* 1: internal VSYNC for each frame */
--                      .run_count = v_total * 2 - 1,
--                      .run_src = 3,                   /* == counter 7 */
--              }, {
--                      /* PIN2: HSYNC waveform */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              }, {
--                      /* PIN3: VSYNC waveform */
--                      .run_count = v_total - 1,
--                      .run_src = 4,                   /* == counter 7 */
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = 4,  /* == counter 7 */
--                      .cnt_down = sig->mode.vsync_len * 2,
--                      .cnt_clr_src = DI_SYNC_CNT1,
--              }, {
--                      /* 4: Field */
--                      .run_count = v_total / 2,
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = h_total / 2,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = 2,
--                      .cnt_clr_src = DI_SYNC_CNT1,
--              }, {
--                      /* 5: Active lines */
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = (sig->mode.vsync_len +
--                                       sig->mode.vback_porch) / 2,
--                      .offset_src = DI_SYNC_HSYNC,
--                      .repeat_count = sig->mode.vactive / 2,
--                      .cnt_clr_src = DI_SYNC_CNT4,
--              }, {
--                      /* 6: Active pixel, referenced by DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = DI_SYNC_CNT5,
--              }, {
--                      /* 7: Half line HSYNC */
--                      .run_count = h_total / 2 - 1,
--                      .run_src = DI_SYNC_CLK,
--              }
--      };
--
--      ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
--
--      ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
--}
--
--static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
--              struct ipu_di_signal_cfg *sig, int div)
--{
--      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
--              sig->mode.hback_porch + sig->mode.hfront_porch;
--      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
--              sig->mode.vback_porch + sig->mode.vfront_porch;
--      struct di_sync_config cfg[] = {
--              {
--                      /* 1: INT_HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--              } , {
--                      /* PIN2: HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync,
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* PIN3: VSYNC */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* 4: Line Active */
--                      .run_src = DI_SYNC_HSYNC,
--                      .offset_count = sig->mode.vsync_len +
--                                      sig->mode.vback_porch,
--                      .offset_src = DI_SYNC_HSYNC,
--                      .repeat_count = sig->mode.vactive,
--                      .cnt_clr_src = DI_SYNC_VSYNC,
--              } , {
--                      /* 5: Pixel Active, referenced by DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = 5, /* Line Active */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              } , {
--                      /* unused */
--              },
--      };
--      /* can't use #7 and #8 for line active and pixel active counters */
--      struct di_sync_config cfg_vga[] = {
--              {
--                      /* 1: INT_HSYNC */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--              } , {
--                      /* 2: VSYNC */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--              } , {
--                      /* 3: Line Active */
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = sig->mode.vsync_len +
--                                      sig->mode.vback_porch,
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .repeat_count = sig->mode.vactive,
--                      .cnt_clr_src = 3 /* VSYNC */,
--              } , {
--                      /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* 5: Pixel Active signal to DC */
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = sig->mode.hsync_len +
--                                      sig->mode.hback_porch,
--                      .offset_src = DI_SYNC_CLK,
--                      .repeat_count = sig->mode.hactive,
--                      .cnt_clr_src = 4, /* Line Active */
--              } , {
--                      /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = 1, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
--                      .run_count = h_total - 1,
--                      .run_src = DI_SYNC_CLK,
--                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_CLK,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
--                      .cnt_down = sig->mode.hsync_len * 2,
--              } , {
--                      /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
--                      .run_count = v_total - 1,
--                      .run_src = DI_SYNC_INT_HSYNC,
--                      .offset_count = 1, /* magic value from Freescale TVE driver */
--                      .offset_src = DI_SYNC_INT_HSYNC,
--                      .cnt_polarity_gen_en = 1,
--                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
--                      .cnt_down = sig->mode.vsync_len * 2,
--              } , {
--                      /* unused */
--              },
--      };
--
--      ipu_di_write(di, v_total - 1, DI_SCR_CONF);
--      if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
--              ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
--      else
--              ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
--}
--
--static void ipu_di_config_clock(struct ipu_di *di,
--      const struct ipu_di_signal_cfg *sig)
--{
--      struct clk *clk;
--      unsigned clkgen0;
--      uint32_t val;
--
--      if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
--              /*
--               * CLKMODE_EXT means we must use the DI clock: this is
--               * needed for things like LVDS which needs to feed the
--               * DI and LDB with the same pixel clock.
--               */
--              clk = di->clk_di;
--
--              if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
--                      /*
--                       * CLKMODE_SYNC means that we want the DI to be
--                       * clocked at the same rate as the parent clock.
--                       * This is needed (eg) for LDB which needs to be
--                       * fed with the same pixel clock.  We assume that
--                       * the LDB clock has already been set correctly.
--                       */
--                      clkgen0 = 1 << 4;
--              } else {
--                      /*
--                       * We can use the divider.  We should really have
--                       * a flag here indicating whether the bridge can
--                       * cope with a fractional divider or not.  For the
--                       * time being, let's go for simplicitly and
--                       * reliability.
--                       */
--                      unsigned long in_rate;
--                      unsigned div;
--
--                      clk_set_rate(clk, sig->mode.pixelclock);
--
--                      in_rate = clk_get_rate(clk);
--                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
--                      div = clamp(div, 1U, 255U);
--
--                      clkgen0 = div << 4;
--              }
--      } else {
--              /*
--               * For other interfaces, we can arbitarily select between
--               * the DI specific clock and the internal IPU clock.  See
--               * DI_GENERAL bit 20.  We select the IPU clock if it can
--               * give us a clock rate within 1% of the requested frequency,
--               * otherwise we use the DI clock.
--               */
--              unsigned long rate, clkrate;
--              unsigned div, error;
--
--              clkrate = clk_get_rate(di->clk_ipu);
--              div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
--              div = clamp(div, 1U, 255U);
--              rate = clkrate / div;
--
--              error = rate / (sig->mode.pixelclock / 1000);
--
--              dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
--                      rate, div, (signed)(error - 1000) / 10, error % 10);
--
--              /* Allow a 1% error */
--              if (error < 1010 && error >= 990) {
--                      clk = di->clk_ipu;
--
--                      clkgen0 = div << 4;
--              } else {
--                      unsigned long in_rate;
--                      unsigned div;
--
--                      clk = di->clk_di;
--
--                      clk_set_rate(clk, sig->mode.pixelclock);
--
--                      in_rate = clk_get_rate(clk);
--                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
--                      div = clamp(div, 1U, 255U);
--
--                      clkgen0 = div << 4;
--              }
--      }
--
--      di->clk_di_pixel = clk;
--
--      /* Set the divider */
--      ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
--
--      /*
--       * Set the high/low periods.  Bits 24:16 give us the falling edge,
--       * and bits 8:0 give the rising edge.  LSB is fraction, and is
--       * based on the divider above.  We want a 50% duty cycle, so set
--       * the falling edge to be half the divider.
--       */
--      ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
--
--      /* Finally select the input clock */
--      val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
--      if (clk == di->clk_di)
--              val |= DI_GEN_DI_CLK_EXT;
--      ipu_di_write(di, val, DI_GENERAL);
--
--      dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
--              sig->mode.pixelclock,
--              clk_get_rate(di->clk_ipu),
--              clk_get_rate(di->clk_di),
--              clk == di->clk_di ? "DI" : "IPU",
--              clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
--}
--
--/*
-- * This function is called to adjust a video mode to IPU restrictions.
-- * It is meant to be called from drm crtc mode_fixup() methods.
-- */
--int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
--{
--      u32 diff;
--
--      if (mode->vfront_porch >= 2)
--              return 0;
--
--      diff = 2 - mode->vfront_porch;
--
--      if (mode->vback_porch >= diff) {
--              mode->vfront_porch = 2;
--              mode->vback_porch -= diff;
--      } else if (mode->vsync_len > diff) {
--              mode->vfront_porch = 2;
--              mode->vsync_len = mode->vsync_len - diff;
--      } else {
--              dev_warn(di->ipu->dev, "failed to adjust videomode\n");
--              return -EINVAL;
--      }
--
--      dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
--
--static u32 ipu_di_gen_polarity(int pin)
--{
--      switch (pin) {
--      case 1:
--              return DI_GEN_POLARITY_1;
--      case 2:
--              return DI_GEN_POLARITY_2;
--      case 3:
--              return DI_GEN_POLARITY_3;
--      case 4:
--              return DI_GEN_POLARITY_4;
--      case 5:
--              return DI_GEN_POLARITY_5;
--      case 6:
--              return DI_GEN_POLARITY_6;
--      case 7:
--              return DI_GEN_POLARITY_7;
--      case 8:
--              return DI_GEN_POLARITY_8;
--      }
--      return 0;
--}
--
--int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
--{
--      u32 reg;
--      u32 di_gen, vsync_cnt;
--      u32 div;
--
--      dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
--              di->id, sig->mode.hactive, sig->mode.vactive);
--
--      dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
--              clk_get_rate(di->clk_ipu),
--              clk_get_rate(di->clk_di),
--              sig->mode.pixelclock);
--
--      mutex_lock(&di_mutex);
--
--      ipu_di_config_clock(di, sig);
--
--      div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
--      div = div / 16;         /* Now divider is integer portion */
--
--      /* Setup pixel clock timing */
--      /* Down time is half of period */
--      ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
--
--      ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
--      ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
--
--      di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
--      di_gen |= DI_GEN_DI_VSYNC_EXT;
--
--      if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
--              ipu_di_sync_config_interlaced(di, sig);
--
--              /* set y_sel = 1 */
--              di_gen |= 0x10000000;
--
--              vsync_cnt = 3;
--      } else {
--              ipu_di_sync_config_noninterlaced(di, sig, div);
--
--              vsync_cnt = 3;
--              if (di->id == 1)
--                      /*
--                       * TODO: change only for TVEv2, parallel display
--                       * uses pin 2 / 3
--                       */
--                      if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
--                              vsync_cnt = 6;
--      }
--
--      if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
--              di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
--      if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
--              di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
--
--      if (sig->clk_pol)
--              di_gen |= DI_GEN_POLARITY_DISP_CLK;
--
--      ipu_di_write(di, di_gen, DI_GENERAL);
--
--      ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
--                   DI_SYNC_AS_GEN);
--
--      reg = ipu_di_read(di, DI_POL);
--      reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
--
--      if (sig->enable_pol)
--              reg |= DI_POL_DRDY_POLARITY_15;
--      if (sig->data_pol)
--              reg |= DI_POL_DRDY_DATA_POLARITY;
--
--      ipu_di_write(di, reg, DI_POL);
--
--      mutex_unlock(&di_mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
--
--int ipu_di_enable(struct ipu_di *di)
--{
--      int ret;
--
--      WARN_ON(IS_ERR(di->clk_di_pixel));
--
--      ret = clk_prepare_enable(di->clk_di_pixel);
--      if (ret)
--              return ret;
--
--      ipu_module_enable(di->ipu, di->module);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_enable);
--
--int ipu_di_disable(struct ipu_di *di)
--{
--      WARN_ON(IS_ERR(di->clk_di_pixel));
--
--      ipu_module_disable(di->ipu, di->module);
--
--      clk_disable_unprepare(di->clk_di_pixel);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_di_disable);
--
--int ipu_di_get_num(struct ipu_di *di)
--{
--      return di->id;
--}
--EXPORT_SYMBOL_GPL(ipu_di_get_num);
--
--static DEFINE_MUTEX(ipu_di_lock);
--
--struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
--{
--      struct ipu_di *di;
--
--      if (disp > 1)
--              return ERR_PTR(-EINVAL);
--
--      di = ipu->di_priv[disp];
--
--      mutex_lock(&ipu_di_lock);
--
--      if (di->inuse) {
--              di = ERR_PTR(-EBUSY);
--              goto out;
--      }
--
--      di->inuse = true;
--out:
--      mutex_unlock(&ipu_di_lock);
--
--      return di;
--}
--EXPORT_SYMBOL_GPL(ipu_di_get);
--
--void ipu_di_put(struct ipu_di *di)
--{
--      mutex_lock(&ipu_di_lock);
--
--      di->inuse = false;
--
--      mutex_unlock(&ipu_di_lock);
--}
--EXPORT_SYMBOL_GPL(ipu_di_put);
--
--int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
--              unsigned long base,
--              u32 module, struct clk *clk_ipu)
--{
--      struct ipu_di *di;
--
--      if (id > 1)
--              return -ENODEV;
--
--      di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
--      if (!di)
--              return -ENOMEM;
--
--      ipu->di_priv[id] = di;
--
--      di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
--      if (IS_ERR(di->clk_di))
--              return PTR_ERR(di->clk_di);
--
--      di->module = module;
--      di->id = id;
--      di->clk_ipu = clk_ipu;
--      di->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!di->base)
--              return -ENOMEM;
--
--      ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
--
--      dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
--                      id, base, di->base);
--      di->inuse = false;
--      di->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_di_exit(struct ipu_soc *ipu, int id)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-dmfc.c
-+++ /dev/null
-@@ -1,214 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DMFC_RD_CHAN          0x0000
--#define DMFC_WR_CHAN          0x0004
--#define DMFC_WR_CHAN_DEF      0x0008
--#define DMFC_DP_CHAN          0x000c
--#define DMFC_DP_CHAN_DEF      0x0010
--#define DMFC_GENERAL1         0x0014
--#define DMFC_GENERAL2         0x0018
--#define DMFC_IC_CTRL          0x001c
--#define DMFC_WR_CHAN_ALT      0x0020
--#define DMFC_WR_CHAN_DEF_ALT  0x0024
--#define DMFC_DP_CHAN_ALT      0x0028
--#define DMFC_DP_CHAN_DEF_ALT  0x002c
--#define DMFC_GENERAL1_ALT     0x0030
--#define DMFC_STAT             0x0034
--
--#define DMFC_WR_CHAN_1_28             0
--#define DMFC_WR_CHAN_2_41             8
--#define DMFC_WR_CHAN_1C_42            16
--#define DMFC_WR_CHAN_2C_43            24
--
--#define DMFC_DP_CHAN_5B_23            0
--#define DMFC_DP_CHAN_5F_27            8
--#define DMFC_DP_CHAN_6B_24            16
--#define DMFC_DP_CHAN_6F_29            24
--
--struct dmfc_channel_data {
--      int             ipu_channel;
--      unsigned long   channel_reg;
--      unsigned long   shift;
--      unsigned        eot_shift;
--      unsigned        max_fifo_lines;
--};
--
--static const struct dmfc_channel_data dmfcdata[] = {
--      {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_5B_23,
--              .eot_shift      = 20,
--              .max_fifo_lines = 3,
--      }, {
--              .ipu_channel    = 24,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_6B_24,
--              .eot_shift      = 22,
--              .max_fifo_lines = 1,
--      }, {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_5F_27,
--              .eot_shift      = 21,
--              .max_fifo_lines = 2,
--      }, {
--              .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
--              .channel_reg    = DMFC_WR_CHAN,
--              .shift          = DMFC_WR_CHAN_1_28,
--              .eot_shift      = 16,
--              .max_fifo_lines = 2,
--      }, {
--              .ipu_channel    = 29,
--              .channel_reg    = DMFC_DP_CHAN,
--              .shift          = DMFC_DP_CHAN_6F_29,
--              .eot_shift      = 23,
--              .max_fifo_lines = 1,
--      },
--};
--
--#define DMFC_NUM_CHANNELS     ARRAY_SIZE(dmfcdata)
--
--struct ipu_dmfc_priv;
--
--struct dmfc_channel {
--      unsigned                        slots;
--      struct ipu_soc                  *ipu;
--      struct ipu_dmfc_priv            *priv;
--      const struct dmfc_channel_data  *data;
--};
--
--struct ipu_dmfc_priv {
--      struct ipu_soc *ipu;
--      struct device *dev;
--      struct dmfc_channel channels[DMFC_NUM_CHANNELS];
--      struct mutex mutex;
--      void __iomem *base;
--      int use_count;
--};
--
--int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
--
--void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
--
--void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
--{
--      struct ipu_dmfc_priv *priv = dmfc->priv;
--      u32 dmfc_gen1;
--
--      mutex_lock(&priv->mutex);
--
--      dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
--
--      if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
--              dmfc_gen1 |= 1 << dmfc->data->eot_shift;
--      else
--              dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
--
--      writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
--
--struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
--{
--      struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
--      int i;
--
--      for (i = 0; i < DMFC_NUM_CHANNELS; i++)
--              if (dmfcdata[i].ipu_channel == ipu_channel)
--                      return &priv->channels[i];
--      return ERR_PTR(-ENODEV);
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_get);
--
--void ipu_dmfc_put(struct dmfc_channel *dmfc)
--{
--}
--EXPORT_SYMBOL_GPL(ipu_dmfc_put);
--
--int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              struct clk *ipu_clk)
--{
--      struct ipu_dmfc_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      priv->dev = dev;
--      priv->ipu = ipu;
--      mutex_init(&priv->mutex);
--
--      ipu->dmfc_priv = priv;
--
--      for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
--              priv->channels[i].priv = priv;
--              priv->channels[i].ipu = ipu;
--              priv->channels[i].data = &dmfcdata[i];
--
--              if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
--                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
--                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
--                      priv->channels[i].slots = 2;
--      }
--
--      writel(0x00000050, priv->base + DMFC_WR_CHAN);
--      writel(0x00005654, priv->base + DMFC_DP_CHAN);
--      writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
--      writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
--      writel(0x00000003, priv->base + DMFC_GENERAL1);
--
--      return 0;
--}
--
--void ipu_dmfc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-dp.c
-+++ /dev/null
-@@ -1,357 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/export.h>
--#include <linux/kernel.h>
--#include <linux/types.h>
--#include <linux/errno.h>
--#include <linux/io.h>
--#include <linux/err.h>
--
--#include <video/imx-ipu-v3.h>
--#include "ipu-prv.h"
--
--#define DP_SYNC 0
--#define DP_ASYNC0 0x60
--#define DP_ASYNC1 0xBC
--
--#define DP_COM_CONF           0x0
--#define DP_GRAPH_WIND_CTRL    0x0004
--#define DP_FG_POS             0x0008
--#define DP_CSC_A_0            0x0044
--#define DP_CSC_A_1            0x0048
--#define DP_CSC_A_2            0x004C
--#define DP_CSC_A_3            0x0050
--#define DP_CSC_0              0x0054
--#define DP_CSC_1              0x0058
--
--#define DP_COM_CONF_FG_EN             (1 << 0)
--#define DP_COM_CONF_GWSEL             (1 << 1)
--#define DP_COM_CONF_GWAM              (1 << 2)
--#define DP_COM_CONF_GWCKE             (1 << 3)
--#define DP_COM_CONF_CSC_DEF_MASK      (3 << 8)
--#define DP_COM_CONF_CSC_DEF_OFFSET    8
--#define DP_COM_CONF_CSC_DEF_FG                (3 << 8)
--#define DP_COM_CONF_CSC_DEF_BG                (2 << 8)
--#define DP_COM_CONF_CSC_DEF_BOTH      (1 << 8)
--
--#define IPUV3_NUM_FLOWS               3
--
--struct ipu_dp_priv;
--
--struct ipu_dp {
--      u32 flow;
--      bool in_use;
--      bool foreground;
--      enum ipu_color_space in_cs;
--};
--
--struct ipu_flow {
--      struct ipu_dp foreground;
--      struct ipu_dp background;
--      enum ipu_color_space out_cs;
--      void __iomem *base;
--      struct ipu_dp_priv *priv;
--};
--
--struct ipu_dp_priv {
--      struct ipu_soc *ipu;
--      struct device *dev;
--      void __iomem *base;
--      struct ipu_flow flow[IPUV3_NUM_FLOWS];
--      struct mutex mutex;
--      int use_count;
--};
--
--static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
--
--static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
--{
--      if (dp->foreground)
--              return container_of(dp, struct ipu_flow, foreground);
--      else
--              return container_of(dp, struct ipu_flow, background);
--}
--
--int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
--              u8 alpha, bool bg_chan)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      if (bg_chan)
--              reg &= ~DP_COM_CONF_GWSEL;
--      else
--              reg |= DP_COM_CONF_GWSEL;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      if (enable) {
--              reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
--              writel(reg | ((u32) alpha << 24),
--                           flow->base + DP_GRAPH_WIND_CTRL);
--
--              reg = readl(flow->base + DP_COM_CONF);
--              writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
--      } else {
--              reg = readl(flow->base + DP_COM_CONF);
--              writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
--      }
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
--
--int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--
--      writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
--
--static void ipu_dp_csc_init(struct ipu_flow *flow,
--              enum ipu_color_space in,
--              enum ipu_color_space out,
--              u32 place)
--{
--      u32 reg;
--
--      reg = readl(flow->base + DP_COM_CONF);
--      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
--
--      if (in == out) {
--              writel(reg, flow->base + DP_COM_CONF);
--              return;
--      }
--
--      if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
--              writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
--              writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
--              writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
--              writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
--              writel(0x3d6 | (0x0000 << 16) | (2 << 30),
--                              flow->base + DP_CSC_0);
--              writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
--                              flow->base + DP_CSC_1);
--      } else {
--              writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
--              writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
--              writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
--              writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
--              writel(0x000 | (0x3e42 << 16) | (1 << 30),
--                              flow->base + DP_CSC_0);
--              writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
--                              flow->base + DP_CSC_1);
--      }
--
--      reg |= place;
--
--      writel(reg, flow->base + DP_COM_CONF);
--}
--
--int ipu_dp_setup_channel(struct ipu_dp *dp,
--              enum ipu_color_space in,
--              enum ipu_color_space out)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--
--      mutex_lock(&priv->mutex);
--
--      dp->in_cs = in;
--
--      if (!dp->foreground)
--              flow->out_cs = out;
--
--      if (flow->foreground.in_cs == flow->background.in_cs) {
--              /*
--               * foreground and background are of same colorspace, put
--               * colorspace converter after combining unit.
--               */
--              ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
--                              DP_COM_CONF_CSC_DEF_BOTH);
--      } else {
--              if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
--                  flow->foreground.in_cs == flow->out_cs)
--                      /*
--                       * foreground identical to output, apply color
--                       * conversion on background
--                       */
--                      ipu_dp_csc_init(flow, flow->background.in_cs,
--                                      flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
--              else
--                      ipu_dp_csc_init(flow, flow->foreground.in_cs,
--                                      flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
--      }
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
--
--int ipu_dp_enable(struct ipu_soc *ipu)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--
--      mutex_lock(&priv->mutex);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
--
--      priv->use_count++;
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_enable);
--
--int ipu_dp_enable_channel(struct ipu_dp *dp)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg;
--
--      if (!dp->foreground)
--              return 0;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      reg |= DP_COM_CONF_FG_EN;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      ipu_srm_dp_update(priv->ipu, true);
--
--      mutex_unlock(&priv->mutex);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
--
--void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
--{
--      struct ipu_flow *flow = to_flow(dp);
--      struct ipu_dp_priv *priv = flow->priv;
--      u32 reg, csc;
--
--      dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
--
--      if (!dp->foreground)
--              return;
--
--      mutex_lock(&priv->mutex);
--
--      reg = readl(flow->base + DP_COM_CONF);
--      csc = reg & DP_COM_CONF_CSC_DEF_MASK;
--      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
--      if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
--              reg |= DP_COM_CONF_CSC_DEF_BG;
--
--      reg &= ~DP_COM_CONF_FG_EN;
--      writel(reg, flow->base + DP_COM_CONF);
--
--      writel(0, flow->base + DP_FG_POS);
--      ipu_srm_dp_update(priv->ipu, sync);
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
--
--void ipu_dp_disable(struct ipu_soc *ipu)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--
--      mutex_lock(&priv->mutex);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      mutex_unlock(&priv->mutex);
--}
--EXPORT_SYMBOL_GPL(ipu_dp_disable);
--
--struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
--{
--      struct ipu_dp_priv *priv = ipu->dp_priv;
--      struct ipu_dp *dp;
--
--      if ((flow >> 1) >= IPUV3_NUM_FLOWS)
--              return ERR_PTR(-EINVAL);
--
--      if (flow & 1)
--              dp = &priv->flow[flow >> 1].foreground;
--      else
--              dp = &priv->flow[flow >> 1].background;
--
--      if (dp->in_use)
--              return ERR_PTR(-EBUSY);
--
--      dp->in_use = true;
--
--      return dp;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_get);
--
--void ipu_dp_put(struct ipu_dp *dp)
--{
--      dp->in_use = false;
--}
--EXPORT_SYMBOL_GPL(ipu_dp_put);
--
--int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
--{
--      struct ipu_dp_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--      priv->dev = dev;
--      priv->ipu = ipu;
--
--      ipu->dp_priv = priv;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      mutex_init(&priv->mutex);
--
--      for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
--              priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
--              priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
--              priv->flow[i].foreground.foreground = true;
--              priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
--              priv->flow[i].priv = priv;
--      }
--
--      return 0;
--}
--
--void ipu_dp_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-ic.c
-+++ /dev/null
-@@ -1,761 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2014 Mentor Graphics Inc.
-- * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--
--#include <linux/types.h>
--#include <linux/init.h>
--#include <linux/errno.h>
--#include <linux/spinlock.h>
--#include <linux/bitrev.h>
--#include <linux/io.h>
--#include <linux/err.h>
--#include <linux/sizes.h>
--#include "ipu-prv.h"
--
--/* IC Register Offsets */
--#define IC_CONF                 0x0000
--#define IC_PRP_ENC_RSC          0x0004
--#define IC_PRP_VF_RSC           0x0008
--#define IC_PP_RSC               0x000C
--#define IC_CMBP_1               0x0010
--#define IC_CMBP_2               0x0014
--#define IC_IDMAC_1              0x0018
--#define IC_IDMAC_2              0x001C
--#define IC_IDMAC_3              0x0020
--#define IC_IDMAC_4              0x0024
--
--/* IC Register Fields */
--#define IC_CONF_PRPENC_EN       (1 << 0)
--#define IC_CONF_PRPENC_CSC1     (1 << 1)
--#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
--#define IC_CONF_PRPVF_EN        (1 << 8)
--#define IC_CONF_PRPVF_CSC1      (1 << 9)
--#define IC_CONF_PRPVF_CSC2      (1 << 10)
--#define IC_CONF_PRPVF_CMB       (1 << 11)
--#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
--#define IC_CONF_PP_EN           (1 << 16)
--#define IC_CONF_PP_CSC1         (1 << 17)
--#define IC_CONF_PP_CSC2         (1 << 18)
--#define IC_CONF_PP_CMB          (1 << 19)
--#define IC_CONF_PP_ROT_EN       (1 << 20)
--#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
--#define IC_CONF_KEY_COLOR_EN    (1 << 29)
--#define IC_CONF_RWS_EN          (1 << 30)
--#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
--
--#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
--#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
--#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
--#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
--#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
--#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
--#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
--#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
--#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
--#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
--#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
--#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
--#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
--#define IC_IDMAC_1_PP_ROT_OFFSET        17
--#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
--#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
--#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
--
--#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
--#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
--#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
--#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
--#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
--#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
--
--#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
--#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
--#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
--#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
--#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
--#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
--
--struct ic_task_regoffs {
--      u32 rsc;
--      u32 tpmem_csc[2];
--};
--
--struct ic_task_bitfields {
--      u32 ic_conf_en;
--      u32 ic_conf_rot_en;
--      u32 ic_conf_cmb_en;
--      u32 ic_conf_csc1_en;
--      u32 ic_conf_csc2_en;
--      u32 ic_cmb_galpha_bit;
--};
--
--static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
--      [IC_TASK_ENCODER] = {
--              .rsc = IC_PRP_ENC_RSC,
--              .tpmem_csc = {0x2008, 0},
--      },
--      [IC_TASK_VIEWFINDER] = {
--              .rsc = IC_PRP_VF_RSC,
--              .tpmem_csc = {0x4028, 0x4040},
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .rsc = IC_PP_RSC,
--              .tpmem_csc = {0x6060, 0x6078},
--      },
--};
--
--static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
--      [IC_TASK_ENCODER] = {
--              .ic_conf_en = IC_CONF_PRPENC_EN,
--              .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
--              .ic_conf_cmb_en = 0,    /* NA */
--              .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
--              .ic_conf_csc2_en = 0,   /* NA */
--              .ic_cmb_galpha_bit = 0, /* NA */
--      },
--      [IC_TASK_VIEWFINDER] = {
--              .ic_conf_en = IC_CONF_PRPVF_EN,
--              .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
--              .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
--              .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
--              .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
--              .ic_cmb_galpha_bit = 0,
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .ic_conf_en = IC_CONF_PP_EN,
--              .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
--              .ic_conf_cmb_en = IC_CONF_PP_CMB,
--              .ic_conf_csc1_en = IC_CONF_PP_CSC1,
--              .ic_conf_csc2_en = IC_CONF_PP_CSC2,
--              .ic_cmb_galpha_bit = 8,
--      },
--};
--
--struct ipu_ic_priv;
--
--struct ipu_ic {
--      enum ipu_ic_task task;
--      const struct ic_task_regoffs *reg;
--      const struct ic_task_bitfields *bit;
--
--      struct ipu_ic_colorspace in_cs;
--      struct ipu_ic_colorspace g_in_cs;
--      struct ipu_ic_colorspace out_cs;
--
--      bool graphics;
--      bool rotation;
--      bool in_use;
--
--      struct ipu_ic_priv *priv;
--};
--
--struct ipu_ic_priv {
--      void __iomem *base;
--      void __iomem *tpmem_base;
--      spinlock_t lock;
--      struct ipu_soc *ipu;
--      int use_count;
--      int irt_use_count;
--      struct ipu_ic task[IC_NUM_TASKS];
--};
--
--static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
--{
--      return readl(ic->priv->base + offset);
--}
--
--static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
--{
--      writel(value, ic->priv->base + offset);
--}
--
--static int init_csc(struct ipu_ic *ic,
--                  const struct ipu_ic_csc *csc,
--                  int csc_index)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      u32 __iomem *base;
--      const u16 (*c)[3];
--      const u16 *a;
--      u32 param;
--
--      base = (u32 __iomem *)
--              (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
--
--      /* Cast to unsigned */
--      c = (const u16 (*)[3])csc->params.coeff;
--      a = (const u16 *)csc->params.offset;
--
--      param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
--              ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
--              (csc->params.sat << 10);
--      writel(param, base++);
--
--      param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
--              ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[1] & 0x1fe0) >> 5);
--      writel(param, base++);
--
--      param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
--              ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
--      writel(param, base++);
--
--      param = ((a[2] & 0x1fe0) >> 5);
--      writel(param, base++);
--
--      return 0;
--}
--
--static int calc_resize_coeffs(struct ipu_ic *ic,
--                            u32 in_size, u32 out_size,
--                            u32 *resize_coeff,
--                            u32 *downsize_coeff)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--      u32 temp_size, temp_downsize;
--
--      /*
--       * Input size cannot be more than 4096, and output size cannot
--       * be more than 1024
--       */
--      if (in_size > 4096) {
--              dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
--              return -EINVAL;
--      }
--      if (out_size > 1024) {
--              dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
--              return -EINVAL;
--      }
--
--      /* Cannot downsize more than 4:1 */
--      if ((out_size << 2) < in_size) {
--              dev_err(ipu->dev, "Unsupported downsize\n");
--              return -EINVAL;
--      }
--
--      /* Compute downsizing coefficient */
--      temp_downsize = 0;
--      temp_size = in_size;
--      while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
--             (temp_downsize < 2)) {
--              temp_size >>= 1;
--              temp_downsize++;
--      }
--      *downsize_coeff = temp_downsize;
--
--      /*
--       * compute resizing coefficient using the following equation:
--       * resize_coeff = M * (SI - 1) / (SO - 1)
--       * where M = 2^13, SI = input size, SO = output size
--       */
--      *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
--      if (*resize_coeff >= 16384L) {
--              dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
--              *resize_coeff = 0x3FFF;
--      }
--
--      return 0;
--}
--
--void ipu_ic_task_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--      u32 ic_conf;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      ic_conf |= ic->bit->ic_conf_en;
--
--      if (ic->rotation)
--              ic_conf |= ic->bit->ic_conf_rot_en;
--
--      if (ic->in_cs.cs != ic->out_cs.cs)
--              ic_conf |= ic->bit->ic_conf_csc1_en;
--
--      if (ic->graphics) {
--              ic_conf |= ic->bit->ic_conf_cmb_en;
--              ic_conf |= ic->bit->ic_conf_csc1_en;
--
--              if (ic->g_in_cs.cs != ic->out_cs.cs)
--                      ic_conf |= ic->bit->ic_conf_csc2_en;
--      }
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
--
--void ipu_ic_task_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--      u32 ic_conf;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      ic_conf &= ~(ic->bit->ic_conf_en |
--                   ic->bit->ic_conf_csc1_en |
--                   ic->bit->ic_conf_rot_en);
--      if (ic->bit->ic_conf_csc2_en)
--              ic_conf &= ~ic->bit->ic_conf_csc2_en;
--      if (ic->bit->ic_conf_cmb_en)
--              ic_conf &= ~ic->bit->ic_conf_cmb_en;
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
--
--int ipu_ic_task_graphics_init(struct ipu_ic *ic,
--                            const struct ipu_ic_colorspace *g_in_cs,
--                            bool galpha_en, u32 galpha,
--                            bool colorkey_en, u32 colorkey)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_ic_csc csc2;
--      unsigned long flags;
--      u32 reg, ic_conf;
--      int ret = 0;
--
--      if (ic->task == IC_TASK_ENCODER)
--              return -EINVAL;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_conf = ipu_ic_read(ic, IC_CONF);
--
--      if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
--              struct ipu_ic_csc csc1;
--
--              ret = ipu_ic_calc_csc(&csc1,
--                                    V4L2_YCBCR_ENC_601,
--                                    V4L2_QUANTIZATION_FULL_RANGE,
--                                    IPUV3_COLORSPACE_RGB,
--                                    V4L2_YCBCR_ENC_601,
--                                    V4L2_QUANTIZATION_FULL_RANGE,
--                                    IPUV3_COLORSPACE_RGB);
--              if (ret)
--                      goto unlock;
--
--              /* need transparent CSC1 conversion */
--              ret = init_csc(ic, &csc1, 0);
--              if (ret)
--                      goto unlock;
--      }
--
--      ic->g_in_cs = *g_in_cs;
--      csc2.in_cs = ic->g_in_cs;
--      csc2.out_cs = ic->out_cs;
--
--      ret = __ipu_ic_calc_csc(&csc2);
--      if (ret)
--              goto unlock;
--
--      ret = init_csc(ic, &csc2, 1);
--      if (ret)
--              goto unlock;
--
--      if (galpha_en) {
--              ic_conf |= IC_CONF_IC_GLB_LOC_A;
--              reg = ipu_ic_read(ic, IC_CMBP_1);
--              reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
--              reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
--              ipu_ic_write(ic, reg, IC_CMBP_1);
--      } else
--              ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
--
--      if (colorkey_en) {
--              ic_conf |= IC_CONF_KEY_COLOR_EN;
--              ipu_ic_write(ic, colorkey, IC_CMBP_2);
--      } else
--              ic_conf &= ~IC_CONF_KEY_COLOR_EN;
--
--      ipu_ic_write(ic, ic_conf, IC_CONF);
--
--      ic->graphics = true;
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
--
--int ipu_ic_task_init_rsc(struct ipu_ic *ic,
--                       const struct ipu_ic_csc *csc,
--                       int in_width, int in_height,
--                       int out_width, int out_height,
--                       u32 rsc)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      u32 downsize_coeff, resize_coeff;
--      unsigned long flags;
--      int ret = 0;
--
--      if (!rsc) {
--              /* Setup vertical resizing */
--
--              ret = calc_resize_coeffs(ic, in_height, out_height,
--                                       &resize_coeff, &downsize_coeff);
--              if (ret)
--                      return ret;
--
--              rsc = (downsize_coeff << 30) | (resize_coeff << 16);
--
--              /* Setup horizontal resizing */
--              ret = calc_resize_coeffs(ic, in_width, out_width,
--                                       &resize_coeff, &downsize_coeff);
--              if (ret)
--                      return ret;
--
--              rsc |= (downsize_coeff << 14) | resize_coeff;
--      }
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ipu_ic_write(ic, rsc, ic->reg->rsc);
--
--      /* Setup color space conversion */
--      ic->in_cs = csc->in_cs;
--      ic->out_cs = csc->out_cs;
--
--      ret = init_csc(ic, csc, 0);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--
--int ipu_ic_task_init(struct ipu_ic *ic,
--                   const struct ipu_ic_csc *csc,
--                   int in_width, int in_height,
--                   int out_width, int out_height)
--{
--      return ipu_ic_task_init_rsc(ic, csc,
--                                  in_width, in_height,
--                                  out_width, out_height, 0);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_init);
--
--int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
--                        u32 width, u32 height, int burst_size,
--                        enum ipu_rotate_mode rot)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--      u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
--      u32 temp_rot = bitrev8(rot) >> 5;
--      bool need_hor_flip = false;
--      unsigned long flags;
--      int ret = 0;
--
--      if ((burst_size != 8) && (burst_size != 16)) {
--              dev_err(ipu->dev, "Illegal burst length for IC\n");
--              return -EINVAL;
--      }
--
--      width--;
--      height--;
--
--      if (temp_rot & 0x2)     /* Need horizontal flip */
--              need_hor_flip = true;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
--      ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
--      ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
--
--      switch (channel->num) {
--      case IPUV3_CHANNEL_IC_PP_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_IC_PP:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_PP:
--              ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_IC_PRP_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
--              break;
--      case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_ENC:
--              ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_IC_PRP_VF_MEM:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
--
--              if (need_hor_flip)
--                      ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
--
--              ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
--              ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
--
--              ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
--              ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
--              break;
--      case IPUV3_CHANNEL_MEM_ROT_VF:
--              ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
--              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
--              break;
--      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
--              break;
--      case IPUV3_CHANNEL_G_MEM_IC_PP:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
--              break;
--      case IPUV3_CHANNEL_VDI_MEM_IC_VF:
--              if (burst_size == 16)
--                      ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
--              else
--                      ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
--              break;
--      default:
--              goto unlock;
--      }
--
--      ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
--      ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
--      ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
--
--      if (ipu_rot_mode_is_irt(rot))
--              ic->rotation = true;
--
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
--
--static void ipu_irt_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--
--      if (!priv->irt_use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
--
--      priv->irt_use_count++;
--}
--
--static void ipu_irt_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--
--      if (priv->irt_use_count) {
--              if (!--priv->irt_use_count)
--                      ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
--      }
--}
--
--int ipu_ic_enable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
--
--      priv->use_count++;
--
--      if (ic->rotation)
--              ipu_irt_enable(ic);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_enable);
--
--int ipu_ic_disable(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      if (ic->rotation)
--              ipu_irt_disable(ic);
--
--      ic->rotation = ic->graphics = false;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_disable);
--
--struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
--{
--      struct ipu_ic_priv *priv = ipu->ic_priv;
--      unsigned long flags;
--      struct ipu_ic *ic, *ret;
--
--      if (task >= IC_NUM_TASKS)
--              return ERR_PTR(-EINVAL);
--
--      ic = &priv->task[task];
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (ic->in_use) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      ic->in_use = true;
--      ret = ic;
--
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_ic_get);
--
--void ipu_ic_put(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--      ic->in_use = false;
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_ic_put);
--
--int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long tpmem_base)
--{
--      struct ipu_ic_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->ic_priv = priv;
--
--      spin_lock_init(&priv->lock);
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--      priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
--      if (!priv->tpmem_base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
--
--      priv->ipu = ipu;
--
--      for (i = 0; i < IC_NUM_TASKS; i++) {
--              priv->task[i].task = i;
--              priv->task[i].priv = priv;
--              priv->task[i].reg = &ic_task_reg[i];
--              priv->task[i].bit = &ic_task_bit[i];
--      }
--
--      return 0;
--}
--
--void ipu_ic_exit(struct ipu_soc *ipu)
--{
--}
--
--void ipu_ic_dump(struct ipu_ic *ic)
--{
--      struct ipu_ic_priv *priv = ic->priv;
--      struct ipu_soc *ipu = priv->ipu;
--
--      dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CONF));
--      dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PRP_ENC_RSC));
--      dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PRP_VF_RSC));
--      dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
--              ipu_ic_read(ic, IC_PP_RSC));
--      dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CMBP_1));
--      dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_CMBP_2));
--      dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_1));
--      dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_2));
--      dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_3));
--      dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
--              ipu_ic_read(ic, IC_IDMAC_4));
--}
--EXPORT_SYMBOL_GPL(ipu_ic_dump);
---- a/drivers/gpu/imx/ipu-v3/ipu-image-convert.c
-+++ /dev/null
-@@ -1,2475 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2016 Mentor Graphics Inc.
-- *
-- * Queued image conversion support, with tiling and rotation.
-- */
--
--#include <linux/interrupt.h>
--#include <linux/dma-mapping.h>
--#include <video/imx-ipu-image-convert.h>
--#include "ipu-prv.h"
--
--/*
-- * The IC Resizer has a restriction that the output frame from the
-- * resizer must be 1024 or less in both width (pixels) and height
-- * (lines).
-- *
-- * The image converter attempts to split up a conversion when
-- * the desired output (converted) frame resolution exceeds the
-- * IC resizer limit of 1024 in either dimension.
-- *
-- * If either dimension of the output frame exceeds the limit, the
-- * dimension is split into 1, 2, or 4 equal stripes, for a maximum
-- * of 4*4 or 16 tiles. A conversion is then carried out for each
-- * tile (but taking care to pass the full frame stride length to
-- * the DMA channel's parameter memory!). IDMA double-buffering is used
-- * to convert each tile back-to-back when possible (see note below
-- * when double_buffering boolean is set).
-- *
-- * Note that the input frame must be split up into the same number
-- * of tiles as the output frame:
-- *
-- *                       +---------+-----+
-- *   +-----+---+         |  A      | B   |
-- *   | A   | B |         |         |     |
-- *   +-----+---+   -->   +---------+-----+
-- *   | C   | D |         |  C      | D   |
-- *   +-----+---+         |         |     |
-- *                       +---------+-----+
-- *
-- * Clockwise 90° rotations are handled by first rescaling into a
-- * reusable temporary tile buffer and then rotating with the 8x8
-- * block rotator, writing to the correct destination:
-- *
-- *                                         +-----+-----+
-- *                                         |     |     |
-- *   +-----+---+         +---------+       | C   | A   |
-- *   | A   | B |         | A,B, |  |       |     |     |
-- *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
-- *   | C   | D |         +---------+       +-----+-----+
-- *   +-----+---+                           | D   | B   |
-- *                                         |     |     |
-- *                                         +-----+-----+
-- *
-- * If the 8x8 block rotator is used, horizontal or vertical flipping
-- * is done during the rotation step, otherwise flipping is done
-- * during the scaling step.
-- * With rotation or flipping, tile order changes between input and
-- * output image. Tiles are numbered row major from top left to bottom
-- * right for both input and output image.
-- */
--
--#define MAX_STRIPES_W    4
--#define MAX_STRIPES_H    4
--#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
--
--#define MIN_W     16
--#define MIN_H     8
--#define MAX_W     4096
--#define MAX_H     4096
--
--enum ipu_image_convert_type {
--      IMAGE_CONVERT_IN = 0,
--      IMAGE_CONVERT_OUT,
--};
--
--struct ipu_image_convert_dma_buf {
--      void          *virt;
--      dma_addr_t    phys;
--      unsigned long len;
--};
--
--struct ipu_image_convert_dma_chan {
--      int in;
--      int out;
--      int rot_in;
--      int rot_out;
--      int vdi_in_p;
--      int vdi_in;
--      int vdi_in_n;
--};
--
--/* dimensions of one tile */
--struct ipu_image_tile {
--      u32 width;
--      u32 height;
--      u32 left;
--      u32 top;
--      /* size and strides are in bytes */
--      u32 size;
--      u32 stride;
--      u32 rot_stride;
--      /* start Y or packed offset of this tile */
--      u32 offset;
--      /* offset from start to tile in U plane, for planar formats */
--      u32 u_off;
--      /* offset from start to tile in V plane, for planar formats */
--      u32 v_off;
--};
--
--struct ipu_image_convert_image {
--      struct ipu_image base;
--      enum ipu_image_convert_type type;
--
--      const struct ipu_image_pixfmt *fmt;
--      unsigned int stride;
--
--      /* # of rows (horizontal stripes) if dest height is > 1024 */
--      unsigned int num_rows;
--      /* # of columns (vertical stripes) if dest width is > 1024 */
--      unsigned int num_cols;
--
--      struct ipu_image_tile tile[MAX_TILES];
--};
--
--struct ipu_image_pixfmt {
--      u32     fourcc;        /* V4L2 fourcc */
--      int     bpp;           /* total bpp */
--      int     uv_width_dec;  /* decimation in width for U/V planes */
--      int     uv_height_dec; /* decimation in height for U/V planes */
--      bool    planar;        /* planar format */
--      bool    uv_swapped;    /* U and V planes are swapped */
--      bool    uv_packed;     /* partial planar (U and V in same plane) */
--};
--
--struct ipu_image_convert_ctx;
--struct ipu_image_convert_chan;
--struct ipu_image_convert_priv;
--
--struct ipu_image_convert_ctx {
--      struct ipu_image_convert_chan *chan;
--
--      ipu_image_convert_cb_t complete;
--      void *complete_context;
--
--      /* Source/destination image data and rotation mode */
--      struct ipu_image_convert_image in;
--      struct ipu_image_convert_image out;
--      struct ipu_ic_csc csc;
--      enum ipu_rotate_mode rot_mode;
--      u32 downsize_coeff_h;
--      u32 downsize_coeff_v;
--      u32 image_resize_coeff_h;
--      u32 image_resize_coeff_v;
--      u32 resize_coeffs_h[MAX_STRIPES_W];
--      u32 resize_coeffs_v[MAX_STRIPES_H];
--
--      /* intermediate buffer for rotation */
--      struct ipu_image_convert_dma_buf rot_intermediate[2];
--
--      /* current buffer number for double buffering */
--      int cur_buf_num;
--
--      bool aborting;
--      struct completion aborted;
--
--      /* can we use double-buffering for this conversion operation? */
--      bool double_buffering;
--      /* num_rows * num_cols */
--      unsigned int num_tiles;
--      /* next tile to process */
--      unsigned int next_tile;
--      /* where to place converted tile in dest image */
--      unsigned int out_tile_map[MAX_TILES];
--
--      struct list_head list;
--};
--
--struct ipu_image_convert_chan {
--      struct ipu_image_convert_priv *priv;
--
--      enum ipu_ic_task ic_task;
--      const struct ipu_image_convert_dma_chan *dma_ch;
--
--      struct ipu_ic *ic;
--      struct ipuv3_channel *in_chan;
--      struct ipuv3_channel *out_chan;
--      struct ipuv3_channel *rotation_in_chan;
--      struct ipuv3_channel *rotation_out_chan;
--
--      /* the IPU end-of-frame irqs */
--      int out_eof_irq;
--      int rot_out_eof_irq;
--
--      spinlock_t irqlock;
--
--      /* list of convert contexts */
--      struct list_head ctx_list;
--      /* queue of conversion runs */
--      struct list_head pending_q;
--      /* queue of completed runs */
--      struct list_head done_q;
--
--      /* the current conversion run */
--      struct ipu_image_convert_run *current_run;
--};
--
--struct ipu_image_convert_priv {
--      struct ipu_image_convert_chan chan[IC_NUM_TASKS];
--      struct ipu_soc *ipu;
--};
--
--static const struct ipu_image_convert_dma_chan
--image_convert_dma_chan[IC_NUM_TASKS] = {
--      [IC_TASK_VIEWFINDER] = {
--              .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
--              .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
--              .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
--              .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
--              .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
--              .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
--              .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
--      },
--      [IC_TASK_POST_PROCESSOR] = {
--              .in = IPUV3_CHANNEL_MEM_IC_PP,
--              .out = IPUV3_CHANNEL_IC_PP_MEM,
--              .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
--              .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
--      },
--};
--
--static const struct ipu_image_pixfmt image_convert_formats[] = {
--      {
--              .fourcc = V4L2_PIX_FMT_RGB565,
--              .bpp    = 16,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGB24,
--              .bpp    = 24,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGR24,
--              .bpp    = 24,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGB32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGR32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_XRGB32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_XBGR32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_BGRX32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_RGBX32,
--              .bpp    = 32,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUYV,
--              .bpp    = 16,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_UYVY,
--              .bpp    = 16,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUV420,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YVU420,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--              .uv_swapped = true,
--      }, {
--              .fourcc = V4L2_PIX_FMT_NV12,
--              .bpp    = 12,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 2,
--              .uv_packed = true,
--      }, {
--              .fourcc = V4L2_PIX_FMT_YUV422P,
--              .bpp    = 16,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--      }, {
--              .fourcc = V4L2_PIX_FMT_NV16,
--              .bpp    = 16,
--              .planar = true,
--              .uv_width_dec = 2,
--              .uv_height_dec = 1,
--              .uv_packed = true,
--      },
--};
--
--static const struct ipu_image_pixfmt *get_format(u32 fourcc)
--{
--      const struct ipu_image_pixfmt *ret = NULL;
--      unsigned int i;
--
--      for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
--              if (image_convert_formats[i].fourcc == fourcc) {
--                      ret = &image_convert_formats[i];
--                      break;
--              }
--      }
--
--      return ret;
--}
--
--static void dump_format(struct ipu_image_convert_ctx *ctx,
--                      struct ipu_image_convert_image *ic_image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev,
--              "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
--              chan->ic_task, ctx,
--              ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
--              ic_image->base.pix.width, ic_image->base.pix.height,
--              ic_image->num_cols, ic_image->num_rows,
--              ic_image->fmt->fourcc & 0xff,
--              (ic_image->fmt->fourcc >> 8) & 0xff,
--              (ic_image->fmt->fourcc >> 16) & 0xff,
--              (ic_image->fmt->fourcc >> 24) & 0xff);
--}
--
--int ipu_image_convert_enum_format(int index, u32 *fourcc)
--{
--      const struct ipu_image_pixfmt *fmt;
--
--      if (index >= (int)ARRAY_SIZE(image_convert_formats))
--              return -EINVAL;
--
--      /* Format found */
--      fmt = &image_convert_formats[index];
--      *fourcc = fmt->fourcc;
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
--
--static void free_dma_buf(struct ipu_image_convert_priv *priv,
--                       struct ipu_image_convert_dma_buf *buf)
--{
--      if (buf->virt)
--              dma_free_coherent(priv->ipu->dev,
--                                buf->len, buf->virt, buf->phys);
--      buf->virt = NULL;
--      buf->phys = 0;
--}
--
--static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
--                       struct ipu_image_convert_dma_buf *buf,
--                       int size)
--{
--      buf->len = PAGE_ALIGN(size);
--      buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
--                                     GFP_DMA | GFP_KERNEL);
--      if (!buf->virt) {
--              dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
--              return -ENOMEM;
--      }
--
--      return 0;
--}
--
--static inline int num_stripes(int dim)
--{
--      return (dim - 1) / 1024 + 1;
--}
--
--/*
-- * Calculate downsizing coefficients, which are the same for all tiles,
-- * and initial bilinear resizing coefficients, which are used to find the
-- * best seam positions.
-- * Also determine the number of tiles necessary to guarantee that no tile
-- * is larger than 1024 pixels in either dimension at the output and between
-- * IC downsizing and main processing sections.
-- */
--static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
--                                        struct ipu_image *in,
--                                        struct ipu_image *out)
--{
--      u32 downsized_width = in->rect.width;
--      u32 downsized_height = in->rect.height;
--      u32 downsize_coeff_v = 0;
--      u32 downsize_coeff_h = 0;
--      u32 resized_width = out->rect.width;
--      u32 resized_height = out->rect.height;
--      u32 resize_coeff_h;
--      u32 resize_coeff_v;
--      u32 cols;
--      u32 rows;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              resized_width = out->rect.height;
--              resized_height = out->rect.width;
--      }
--
--      /* Do not let invalid input lead to an endless loop below */
--      if (WARN_ON(resized_width == 0 || resized_height == 0))
--              return -EINVAL;
--
--      while (downsized_width >= resized_width * 2) {
--              downsized_width >>= 1;
--              downsize_coeff_h++;
--      }
--
--      while (downsized_height >= resized_height * 2) {
--              downsized_height >>= 1;
--              downsize_coeff_v++;
--      }
--
--      /*
--       * Calculate the bilinear resizing coefficients that could be used if
--       * we were converting with a single tile. The bottom right output pixel
--       * should sample as close as possible to the bottom right input pixel
--       * out of the decimator, but not overshoot it:
--       */
--      resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
--      resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
--
--      /*
--       * Both the output of the IC downsizing section before being passed to
--       * the IC main processing section and the final output of the IC main
--       * processing section must be <= 1024 pixels in both dimensions.
--       */
--      cols = num_stripes(max_t(u32, downsized_width, resized_width));
--      rows = num_stripes(max_t(u32, downsized_height, resized_height));
--
--      dev_dbg(ctx->chan->priv->ipu->dev,
--              "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
--              __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
--              resize_coeff_v, cols, rows);
--
--      if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
--          resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
--              return -EINVAL;
--
--      ctx->downsize_coeff_h = downsize_coeff_h;
--      ctx->downsize_coeff_v = downsize_coeff_v;
--      ctx->image_resize_coeff_h = resize_coeff_h;
--      ctx->image_resize_coeff_v = resize_coeff_v;
--      ctx->in.num_cols = cols;
--      ctx->in.num_rows = rows;
--
--      return 0;
--}
--
--#define round_closest(x, y) round_down((x) + (y)/2, (y))
--
--/*
-- * Find the best aligned seam position for the given column / row index.
-- * Rotation and image offsets are out of scope.
-- *
-- * @index: column / row index, used to calculate valid interval
-- * @in_edge: input right / bottom edge
-- * @out_edge: output right / bottom edge
-- * @in_align: input alignment, either horizontal 8-byte line start address
-- *            alignment, or pixel alignment due to image format
-- * @out_align: output alignment, either horizontal 8-byte line start address
-- *             alignment, or pixel alignment due to image format or rotator
-- *             block size
-- * @in_burst: horizontal input burst size in case of horizontal flip
-- * @out_burst: horizontal output burst size or rotator block size
-- * @downsize_coeff: downsizing section coefficient
-- * @resize_coeff: main processing section resizing coefficient
-- * @_in_seam: aligned input seam position return value
-- * @_out_seam: aligned output seam position return value
-- */
--static void find_best_seam(struct ipu_image_convert_ctx *ctx,
--                         unsigned int index,
--                         unsigned int in_edge,
--                         unsigned int out_edge,
--                         unsigned int in_align,
--                         unsigned int out_align,
--                         unsigned int in_burst,
--                         unsigned int out_burst,
--                         unsigned int downsize_coeff,
--                         unsigned int resize_coeff,
--                         u32 *_in_seam,
--                         u32 *_out_seam)
--{
--      struct device *dev = ctx->chan->priv->ipu->dev;
--      unsigned int out_pos;
--      /* Input / output seam position candidates */
--      unsigned int out_seam = 0;
--      unsigned int in_seam = 0;
--      unsigned int min_diff = UINT_MAX;
--      unsigned int out_start;
--      unsigned int out_end;
--      unsigned int in_start;
--      unsigned int in_end;
--
--      /* Start within 1024 pixels of the right / bottom edge */
--      out_start = max_t(int, index * out_align, out_edge - 1024);
--      /* End before having to add more columns to the left / rows above */
--      out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
--
--      /*
--       * Limit input seam position to make sure that the downsized input tile
--       * to the right or bottom does not exceed 1024 pixels.
--       */
--      in_start = max_t(int, index * in_align,
--                       in_edge - (1024 << downsize_coeff));
--      in_end = min_t(unsigned int, in_edge,
--                     index * (1024 << downsize_coeff) + 1);
--
--      /*
--       * Output tiles must start at a multiple of 8 bytes horizontally and
--       * possibly at an even line horizontally depending on the pixel format.
--       * Only consider output aligned positions for the seam.
--       */
--      out_start = round_up(out_start, out_align);
--      for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
--              unsigned int in_pos;
--              unsigned int in_pos_aligned;
--              unsigned int in_pos_rounded;
--              unsigned int abs_diff;
--
--              /*
--               * Tiles in the right row / bottom column may not be allowed to
--               * overshoot horizontally / vertically. out_burst may be the
--               * actual DMA burst size, or the rotator block size.
--               */
--              if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
--                      continue;
--
--              /*
--               * Input sample position, corresponding to out_pos, 19.13 fixed
--               * point.
--               */
--              in_pos = (out_pos * resize_coeff) << downsize_coeff;
--              /*
--               * The closest input sample position that we could actually
--               * start the input tile at, 19.13 fixed point.
--               */
--              in_pos_aligned = round_closest(in_pos, 8192U * in_align);
--              /* Convert 19.13 fixed point to integer */
--              in_pos_rounded = in_pos_aligned / 8192U;
--
--              if (in_pos_rounded < in_start)
--                      continue;
--              if (in_pos_rounded >= in_end)
--                      break;
--
--              if ((in_burst > 1) &&
--                  (in_edge - in_pos_rounded) % in_burst)
--                      continue;
--
--              if (in_pos < in_pos_aligned)
--                      abs_diff = in_pos_aligned - in_pos;
--              else
--                      abs_diff = in_pos - in_pos_aligned;
--
--              if (abs_diff < min_diff) {
--                      in_seam = in_pos_rounded;
--                      out_seam = out_pos;
--                      min_diff = abs_diff;
--              }
--      }
--
--      *_out_seam = out_seam;
--      *_in_seam = in_seam;
--
--      dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
--              __func__, out_seam, out_align, out_start, out_end,
--              in_seam, in_align, in_start, in_end, min_diff / 8192,
--              DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
--}
--
--/*
-- * Tile left edges are required to be aligned to multiples of 8 bytes
-- * by the IDMAC.
-- */
--static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
--{
--      if (fmt->planar)
--              return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
--      else
--              return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
--}
--
--/*
-- * Tile top edge alignment is only limited by chroma subsampling.
-- */
--static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
--{
--      return fmt->uv_height_dec > 1 ? 2 : 1;
--}
--
--static inline u32 tile_width_align(enum ipu_image_convert_type type,
--                                 const struct ipu_image_pixfmt *fmt,
--                                 enum ipu_rotate_mode rot_mode)
--{
--      if (type == IMAGE_CONVERT_IN) {
--              /*
--               * The IC burst reads 8 pixels at a time. Reading beyond the
--               * end of the line is usually acceptable. Those pixels are
--               * ignored, unless the IC has to write the scaled line in
--               * reverse.
--               */
--              return (!ipu_rot_mode_is_irt(rot_mode) &&
--                      (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
--      }
--
--      /*
--       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
--       * formats to guarantee 8-byte aligned line start addresses in the
--       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
--       * for all other formats.
--       */
--      return (ipu_rot_mode_is_irt(rot_mode) &&
--              fmt->planar && !fmt->uv_packed) ?
--              8 * fmt->uv_width_dec : 8;
--}
--
--static inline u32 tile_height_align(enum ipu_image_convert_type type,
--                                  const struct ipu_image_pixfmt *fmt,
--                                  enum ipu_rotate_mode rot_mode)
--{
--      if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
--              return 2;
--
--      /*
--       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
--       * formats to guarantee 8-byte aligned line start addresses in the
--       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
--       * for all other formats.
--       */
--      return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
--}
--
--/*
-- * Fill in left position and width and for all tiles in an input column, and
-- * for all corresponding output tiles. If the 90° rotator is used, the output
-- * tiles are in a row, and output tile top position and height are set.
-- */
--static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
--                           unsigned int col,
--                           struct ipu_image_convert_image *in,
--                           unsigned int in_left, unsigned int in_width,
--                           struct ipu_image_convert_image *out,
--                           unsigned int out_left, unsigned int out_width)
--{
--      unsigned int row, tile_idx;
--      struct ipu_image_tile *in_tile, *out_tile;
--
--      for (row = 0; row < in->num_rows; row++) {
--              tile_idx = in->num_cols * row + col;
--              in_tile = &in->tile[tile_idx];
--              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
--
--              in_tile->left = in_left;
--              in_tile->width = in_width;
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--                      out_tile->top = out_left;
--                      out_tile->height = out_width;
--              } else {
--                      out_tile->left = out_left;
--                      out_tile->width = out_width;
--              }
--      }
--}
--
--/*
-- * Fill in top position and height and for all tiles in an input row, and
-- * for all corresponding output tiles. If the 90° rotator is used, the output
-- * tiles are in a column, and output tile left position and width are set.
-- */
--static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
--                        struct ipu_image_convert_image *in,
--                        unsigned int in_top, unsigned int in_height,
--                        struct ipu_image_convert_image *out,
--                        unsigned int out_top, unsigned int out_height)
--{
--      unsigned int col, tile_idx;
--      struct ipu_image_tile *in_tile, *out_tile;
--
--      for (col = 0; col < in->num_cols; col++) {
--              tile_idx = in->num_cols * row + col;
--              in_tile = &in->tile[tile_idx];
--              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
--
--              in_tile->top = in_top;
--              in_tile->height = in_height;
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--                      out_tile->left = out_top;
--                      out_tile->width = out_height;
--              } else {
--                      out_tile->top = out_top;
--                      out_tile->height = out_height;
--              }
--      }
--}
--
--/*
-- * Find the best horizontal and vertical seam positions to split into tiles.
-- * Minimize the fractional part of the input sampling position for the
-- * top / left pixels of each tile.
-- */
--static void find_seams(struct ipu_image_convert_ctx *ctx,
--                     struct ipu_image_convert_image *in,
--                     struct ipu_image_convert_image *out)
--{
--      struct device *dev = ctx->chan->priv->ipu->dev;
--      unsigned int resized_width = out->base.rect.width;
--      unsigned int resized_height = out->base.rect.height;
--      unsigned int col;
--      unsigned int row;
--      unsigned int in_left_align = tile_left_align(in->fmt);
--      unsigned int in_top_align = tile_top_align(in->fmt);
--      unsigned int out_left_align = tile_left_align(out->fmt);
--      unsigned int out_top_align = tile_top_align(out->fmt);
--      unsigned int out_width_align = tile_width_align(out->type, out->fmt,
--                                                      ctx->rot_mode);
--      unsigned int out_height_align = tile_height_align(out->type, out->fmt,
--                                                        ctx->rot_mode);
--      unsigned int in_right = in->base.rect.width;
--      unsigned int in_bottom = in->base.rect.height;
--      unsigned int out_right = out->base.rect.width;
--      unsigned int out_bottom = out->base.rect.height;
--      unsigned int flipped_out_left;
--      unsigned int flipped_out_top;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* Switch width/height and align top left to IRT block size */
--              resized_width = out->base.rect.height;
--              resized_height = out->base.rect.width;
--              out_left_align = out_height_align;
--              out_top_align = out_width_align;
--              out_width_align = out_left_align;
--              out_height_align = out_top_align;
--              out_right = out->base.rect.height;
--              out_bottom = out->base.rect.width;
--      }
--
--      for (col = in->num_cols - 1; col > 0; col--) {
--              bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
--                                        !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              bool allow_out_overshoot = (col < in->num_cols - 1) &&
--                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              unsigned int in_left;
--              unsigned int out_left;
--
--              /*
--               * Align input width to burst length if the scaling step flips
--               * horizontally.
--               */
--
--              find_best_seam(ctx, col,
--                             in_right, out_right,
--                             in_left_align, out_left_align,
--                             allow_in_overshoot ? 1 : 8 /* burst length */,
--                             allow_out_overshoot ? 1 : out_width_align,
--                             ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
--                             &in_left, &out_left);
--
--              if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
--                      flipped_out_left = resized_width - out_right;
--              else
--                      flipped_out_left = out_left;
--
--              fill_tile_column(ctx, col, in, in_left, in_right - in_left,
--                               out, flipped_out_left, out_right - out_left);
--
--              dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
--                      in_left, in_right - in_left,
--                      flipped_out_left, out_right - out_left);
--
--              in_right = in_left;
--              out_right = out_left;
--      }
--
--      flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
--                         resized_width - out_right : 0;
--
--      fill_tile_column(ctx, 0, in, 0, in_right,
--                       out, flipped_out_left, out_right);
--
--      dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
--              in_right, flipped_out_left, out_right);
--
--      for (row = in->num_rows - 1; row > 0; row--) {
--              bool allow_overshoot = row < in->num_rows - 1;
--              unsigned int in_top;
--              unsigned int out_top;
--
--              find_best_seam(ctx, row,
--                             in_bottom, out_bottom,
--                             in_top_align, out_top_align,
--                             1, allow_overshoot ? 1 : out_height_align,
--                             ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
--                             &in_top, &out_top);
--
--              if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
--                  ipu_rot_mode_is_irt(ctx->rot_mode))
--                      flipped_out_top = resized_height - out_bottom;
--              else
--                      flipped_out_top = out_top;
--
--              fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
--                            out, flipped_out_top, out_bottom - out_top);
--
--              dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
--                      in_top, in_bottom - in_top,
--                      flipped_out_top, out_bottom - out_top);
--
--              in_bottom = in_top;
--              out_bottom = out_top;
--      }
--
--      if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
--          ipu_rot_mode_is_irt(ctx->rot_mode))
--              flipped_out_top = resized_height - out_bottom;
--      else
--              flipped_out_top = 0;
--
--      fill_tile_row(ctx, 0, in, 0, in_bottom,
--                    out, flipped_out_top, out_bottom);
--
--      dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
--              in_bottom, flipped_out_top, out_bottom);
--}
--
--static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
--                              struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      unsigned int max_width = 1024;
--      unsigned int max_height = 1024;
--      unsigned int i;
--
--      if (image->type == IMAGE_CONVERT_IN) {
--              /* Up to 4096x4096 input tile size */
--              max_width <<= ctx->downsize_coeff_h;
--              max_height <<= ctx->downsize_coeff_v;
--      }
--
--      for (i = 0; i < ctx->num_tiles; i++) {
--              struct ipu_image_tile *tile;
--              const unsigned int row = i / image->num_cols;
--              const unsigned int col = i % image->num_cols;
--
--              if (image->type == IMAGE_CONVERT_OUT)
--                      tile = &image->tile[ctx->out_tile_map[i]];
--              else
--                      tile = &image->tile[i];
--
--              tile->size = ((tile->height * image->fmt->bpp) >> 3) *
--                      tile->width;
--
--              if (image->fmt->planar) {
--                      tile->stride = tile->width;
--                      tile->rot_stride = tile->height;
--              } else {
--                      tile->stride =
--                              (image->fmt->bpp * tile->width) >> 3;
--                      tile->rot_stride =
--                              (image->fmt->bpp * tile->height) >> 3;
--              }
--
--              dev_dbg(priv->ipu->dev,
--                      "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
--                      chan->ic_task, ctx,
--                      image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
--                      row, col,
--                      tile->width, tile->height, tile->left, tile->top);
--
--              if (!tile->width || tile->width > max_width ||
--                  !tile->height || tile->height > max_height) {
--                      dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
--                              image->type == IMAGE_CONVERT_IN ? "input" :
--                              "output", tile->width, tile->height);
--                      return -EINVAL;
--              }
--      }
--
--      return 0;
--}
--
--/*
-- * Use the rotation transformation to find the tile coordinates
-- * (row, col) of a tile in the destination frame that corresponds
-- * to the given tile coordinates of a source frame. The destination
-- * coordinate is then converted to a tile index.
-- */
--static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
--                              int src_row, int src_col)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      int dst_row, dst_col;
--
--      /* with no rotation it's a 1:1 mapping */
--      if (ctx->rot_mode == IPU_ROTATE_NONE)
--              return src_row * s_image->num_cols + src_col;
--
--      /*
--       * before doing the transform, first we have to translate
--       * source row,col for an origin in the center of s_image
--       */
--      src_row = src_row * 2 - (s_image->num_rows - 1);
--      src_col = src_col * 2 - (s_image->num_cols - 1);
--
--      /* do the rotation transform */
--      if (ctx->rot_mode & IPU_ROT_BIT_90) {
--              dst_col = -src_row;
--              dst_row = src_col;
--      } else {
--              dst_col = src_col;
--              dst_row = src_row;
--      }
--
--      /* apply flip */
--      if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
--              dst_col = -dst_col;
--      if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
--              dst_row = -dst_row;
--
--      dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
--              chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
--
--      /*
--       * finally translate dest row,col using an origin in upper
--       * left of d_image
--       */
--      dst_row += d_image->num_rows - 1;
--      dst_col += d_image->num_cols - 1;
--      dst_row /= 2;
--      dst_col /= 2;
--
--      return dst_row * d_image->num_cols + dst_col;
--}
--
--/*
-- * Fill the out_tile_map[] with transformed destination tile indeces.
-- */
--static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      unsigned int row, col, tile = 0;
--
--      for (row = 0; row < s_image->num_rows; row++) {
--              for (col = 0; col < s_image->num_cols; col++) {
--                      ctx->out_tile_map[tile] =
--                              transform_tile_index(ctx, row, col);
--                      tile++;
--              }
--      }
--}
--
--static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
--                                  struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      const struct ipu_image_pixfmt *fmt = image->fmt;
--      unsigned int row, col, tile = 0;
--      u32 H, top, y_stride, uv_stride;
--      u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
--      u32 y_row_off, y_col_off, y_off;
--      u32 y_size, uv_size;
--
--      /* setup some convenience vars */
--      H = image->base.pix.height;
--
--      y_stride = image->stride;
--      uv_stride = y_stride / fmt->uv_width_dec;
--      if (fmt->uv_packed)
--              uv_stride *= 2;
--
--      y_size = H * y_stride;
--      uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
--
--      for (row = 0; row < image->num_rows; row++) {
--              top = image->tile[tile].top;
--              y_row_off = top * y_stride;
--              uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
--
--              for (col = 0; col < image->num_cols; col++) {
--                      y_col_off = image->tile[tile].left;
--                      uv_col_off = y_col_off / fmt->uv_width_dec;
--                      if (fmt->uv_packed)
--                              uv_col_off *= 2;
--
--                      y_off = y_row_off + y_col_off;
--                      uv_off = uv_row_off + uv_col_off;
--
--                      u_off = y_size - y_off + uv_off;
--                      v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
--                      if (fmt->uv_swapped) {
--                              tmp = u_off;
--                              u_off = v_off;
--                              v_off = tmp;
--                      }
--
--                      image->tile[tile].offset = y_off;
--                      image->tile[tile].u_off = u_off;
--                      image->tile[tile++].v_off = v_off;
--
--                      if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
--                              dev_err(priv->ipu->dev,
--                                      "task %u: ctx %p: %s@[%d,%d]: "
--                                      "y_off %08x, u_off %08x, v_off %08x\n",
--                                      chan->ic_task, ctx,
--                                      image->type == IMAGE_CONVERT_IN ?
--                                      "Input" : "Output", row, col,
--                                      y_off, u_off, v_off);
--                              return -EINVAL;
--                      }
--              }
--      }
--
--      return 0;
--}
--
--static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
--                                  struct ipu_image_convert_image *image)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      const struct ipu_image_pixfmt *fmt = image->fmt;
--      unsigned int row, col, tile = 0;
--      u32 bpp, stride, offset;
--      u32 row_off, col_off;
--
--      /* setup some convenience vars */
--      stride = image->stride;
--      bpp = fmt->bpp;
--
--      for (row = 0; row < image->num_rows; row++) {
--              row_off = image->tile[tile].top * stride;
--
--              for (col = 0; col < image->num_cols; col++) {
--                      col_off = (image->tile[tile].left * bpp) >> 3;
--
--                      offset = row_off + col_off;
--
--                      image->tile[tile].offset = offset;
--                      image->tile[tile].u_off = 0;
--                      image->tile[tile++].v_off = 0;
--
--                      if (offset & 0x7) {
--                              dev_err(priv->ipu->dev,
--                                      "task %u: ctx %p: %s@[%d,%d]: "
--                                      "phys %08x\n",
--                                      chan->ic_task, ctx,
--                                      image->type == IMAGE_CONVERT_IN ?
--                                      "Input" : "Output", row, col,
--                                      row_off + col_off);
--                              return -EINVAL;
--                      }
--              }
--      }
--
--      return 0;
--}
--
--static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
--                            struct ipu_image_convert_image *image)
--{
--      if (image->fmt->planar)
--              return calc_tile_offsets_planar(ctx, image);
--
--      return calc_tile_offsets_packed(ctx, image);
--}
--
--/*
-- * Calculate the resizing ratio for the IC main processing section given input
-- * size, fixed downsizing coefficient, and output size.
-- * Either round to closest for the next tile's first pixel to minimize seams
-- * and distortion (for all but right column / bottom row), or round down to
-- * avoid sampling beyond the edges of the input image for this tile's last
-- * pixel.
-- * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
-- */
--static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
--                           u32 output_size, bool allow_overshoot)
--{
--      u32 downsized = input_size >> downsize_coeff;
--
--      if (allow_overshoot)
--              return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
--      else
--              return 8192 * (downsized - 1) / (output_size - 1);
--}
--
--/*
-- * Slightly modify resize coefficients per tile to hide the bilinear
-- * interpolator reset at tile borders, shifting the right / bottom edge
-- * by up to a half input pixel. This removes noticeable seams between
-- * tiles at higher upscaling factors.
-- */
--static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_tile *in_tile, *out_tile;
--      unsigned int col, row, tile_idx;
--      unsigned int last_output;
--
--      for (col = 0; col < ctx->in.num_cols; col++) {
--              bool closest = (col < ctx->in.num_cols - 1) &&
--                             !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
--              u32 resized_width;
--              u32 resize_coeff_h;
--              u32 in_width;
--
--              tile_idx = col;
--              in_tile = &ctx->in.tile[tile_idx];
--              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      resized_width = out_tile->height;
--              else
--                      resized_width = out_tile->width;
--
--              resize_coeff_h = calc_resize_coeff(in_tile->width,
--                                                 ctx->downsize_coeff_h,
--                                                 resized_width, closest);
--
--              dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
--                      __func__, col, resize_coeff_h);
--
--              /*
--               * With the horizontal scaling factor known, round up resized
--               * width (output width or height) to burst size.
--               */
--              resized_width = round_up(resized_width, 8);
--
--              /*
--               * Calculate input width from the last accessed input pixel
--               * given resized width and scaling coefficients. Round up to
--               * burst size.
--               */
--              last_output = resized_width - 1;
--              if (closest && ((last_output * resize_coeff_h) % 8192))
--                      last_output++;
--              in_width = round_up(
--                      (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
--                      << ctx->downsize_coeff_h, 8);
--
--              for (row = 0; row < ctx->in.num_rows; row++) {
--                      tile_idx = row * ctx->in.num_cols + col;
--                      in_tile = &ctx->in.tile[tile_idx];
--                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                              out_tile->height = resized_width;
--                      else
--                              out_tile->width = resized_width;
--
--                      in_tile->width = in_width;
--              }
--
--              ctx->resize_coeffs_h[col] = resize_coeff_h;
--      }
--
--      for (row = 0; row < ctx->in.num_rows; row++) {
--              bool closest = (row < ctx->in.num_rows - 1) &&
--                             !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
--              u32 resized_height;
--              u32 resize_coeff_v;
--              u32 in_height;
--
--              tile_idx = row * ctx->in.num_cols;
--              in_tile = &ctx->in.tile[tile_idx];
--              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      resized_height = out_tile->width;
--              else
--                      resized_height = out_tile->height;
--
--              resize_coeff_v = calc_resize_coeff(in_tile->height,
--                                                 ctx->downsize_coeff_v,
--                                                 resized_height, closest);
--
--              dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
--                      __func__, row, resize_coeff_v);
--
--              /*
--               * With the vertical scaling factor known, round up resized
--               * height (output width or height) to IDMAC limitations.
--               */
--              resized_height = round_up(resized_height, 2);
--
--              /*
--               * Calculate input width from the last accessed input pixel
--               * given resized height and scaling coefficients. Align to
--               * IDMAC restrictions.
--               */
--              last_output = resized_height - 1;
--              if (closest && ((last_output * resize_coeff_v) % 8192))
--                      last_output++;
--              in_height = round_up(
--                      (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
--                      << ctx->downsize_coeff_v, 2);
--
--              for (col = 0; col < ctx->in.num_cols; col++) {
--                      tile_idx = row * ctx->in.num_cols + col;
--                      in_tile = &ctx->in.tile[tile_idx];
--                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
--
--                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                              out_tile->width = resized_height;
--                      else
--                              out_tile->height = resized_height;
--
--                      in_tile->height = in_height;
--              }
--
--              ctx->resize_coeffs_v[row] = resize_coeff_v;
--      }
--}
--
--/*
-- * return the number of runs in given queue (pending_q or done_q)
-- * for this context. hold irqlock when calling.
-- */
--static int get_run_count(struct ipu_image_convert_ctx *ctx,
--                       struct list_head *q)
--{
--      struct ipu_image_convert_run *run;
--      int count = 0;
--
--      lockdep_assert_held(&ctx->chan->irqlock);
--
--      list_for_each_entry(run, q, list) {
--              if (run->ctx == ctx)
--                      count++;
--      }
--
--      return count;
--}
--
--static void convert_stop(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
--              __func__, chan->ic_task, ctx, run);
--
--      /* disable IC tasks and the channels */
--      ipu_ic_task_disable(chan->ic);
--      ipu_idmac_disable_channel(chan->in_chan);
--      ipu_idmac_disable_channel(chan->out_chan);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_idmac_disable_channel(chan->rotation_in_chan);
--              ipu_idmac_disable_channel(chan->rotation_out_chan);
--              ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
--      }
--
--      ipu_ic_disable(chan->ic);
--}
--
--static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
--                             struct ipuv3_channel *channel,
--                             struct ipu_image_convert_image *image,
--                             enum ipu_rotate_mode rot_mode,
--                             bool rot_swap_width_height,
--                             unsigned int tile)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      unsigned int burst_size;
--      u32 width, height, stride;
--      dma_addr_t addr0, addr1 = 0;
--      struct ipu_image tile_image;
--      unsigned int tile_idx[2];
--
--      if (image->type == IMAGE_CONVERT_OUT) {
--              tile_idx[0] = ctx->out_tile_map[tile];
--              tile_idx[1] = ctx->out_tile_map[1];
--      } else {
--              tile_idx[0] = tile;
--              tile_idx[1] = 1;
--      }
--
--      if (rot_swap_width_height) {
--              width = image->tile[tile_idx[0]].height;
--              height = image->tile[tile_idx[0]].width;
--              stride = image->tile[tile_idx[0]].rot_stride;
--              addr0 = ctx->rot_intermediate[0].phys;
--              if (ctx->double_buffering)
--                      addr1 = ctx->rot_intermediate[1].phys;
--      } else {
--              width = image->tile[tile_idx[0]].width;
--              height = image->tile[tile_idx[0]].height;
--              stride = image->stride;
--              addr0 = image->base.phys0 +
--                      image->tile[tile_idx[0]].offset;
--              if (ctx->double_buffering)
--                      addr1 = image->base.phys0 +
--                              image->tile[tile_idx[1]].offset;
--      }
--
--      ipu_cpmem_zero(channel);
--
--      memset(&tile_image, 0, sizeof(tile_image));
--      tile_image.pix.width = tile_image.rect.width = width;
--      tile_image.pix.height = tile_image.rect.height = height;
--      tile_image.pix.bytesperline = stride;
--      tile_image.pix.pixelformat =  image->fmt->fourcc;
--      tile_image.phys0 = addr0;
--      tile_image.phys1 = addr1;
--      if (image->fmt->planar && !rot_swap_width_height) {
--              tile_image.u_offset = image->tile[tile_idx[0]].u_off;
--              tile_image.v_offset = image->tile[tile_idx[0]].v_off;
--      }
--
--      ipu_cpmem_set_image(channel, &tile_image);
--
--      if (rot_mode)
--              ipu_cpmem_set_rotation(channel, rot_mode);
--
--      /*
--       * Skip writing U and V components to odd rows in the output
--       * channels for planar 4:2:0.
--       */
--      if ((channel == chan->out_chan ||
--           channel == chan->rotation_out_chan) &&
--          image->fmt->planar && image->fmt->uv_height_dec == 2)
--              ipu_cpmem_skip_odd_chroma_rows(channel);
--
--      if (channel == chan->rotation_in_chan ||
--          channel == chan->rotation_out_chan) {
--              burst_size = 8;
--              ipu_cpmem_set_block_mode(channel);
--      } else
--              burst_size = (width % 16) ? 8 : 16;
--
--      ipu_cpmem_set_burstsize(channel, burst_size);
--
--      ipu_ic_task_idma_init(chan->ic, channel, width, height,
--                            burst_size, rot_mode);
--
--      /*
--       * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
--       * only do this when there is no PRG present.
--       */
--      if (!channel->ipu->prg_priv)
--              ipu_cpmem_set_axi_id(channel, 1);
--
--      ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
--}
--
--static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      unsigned int dst_tile = ctx->out_tile_map[tile];
--      unsigned int dest_width, dest_height;
--      unsigned int col, row;
--      u32 rsc;
--      int ret;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
--              __func__, chan->ic_task, ctx, run, tile, dst_tile);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* swap width/height for resizer */
--              dest_width = d_image->tile[dst_tile].height;
--              dest_height = d_image->tile[dst_tile].width;
--      } else {
--              dest_width = d_image->tile[dst_tile].width;
--              dest_height = d_image->tile[dst_tile].height;
--      }
--
--      row = tile / s_image->num_cols;
--      col = tile % s_image->num_cols;
--
--      rsc =  (ctx->downsize_coeff_v << 30) |
--             (ctx->resize_coeffs_v[row] << 16) |
--             (ctx->downsize_coeff_h << 14) |
--             (ctx->resize_coeffs_h[col]);
--
--      dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
--              __func__, s_image->tile[tile].width,
--              s_image->tile[tile].height, dest_width, dest_height, rsc);
--
--      /* setup the IC resizer and CSC */
--      ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
--                                 s_image->tile[tile].width,
--                                 s_image->tile[tile].height,
--                                 dest_width,
--                                 dest_height,
--                                 rsc);
--      if (ret) {
--              dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
--              return ret;
--      }
--
--      /* init the source MEM-->IC PP IDMAC channel */
--      init_idmac_channel(ctx, chan->in_chan, s_image,
--                         IPU_ROTATE_NONE, false, tile);
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* init the IC PP-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->out_chan, d_image,
--                                 IPU_ROTATE_NONE, true, tile);
--
--              /* init the MEM-->IC PP ROT IDMAC channel */
--              init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
--                                 ctx->rot_mode, true, tile);
--
--              /* init the destination IC PP ROT-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
--                                 IPU_ROTATE_NONE, false, tile);
--
--              /* now link IC PP-->MEM to MEM-->IC PP ROT */
--              ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
--      } else {
--              /* init the destination IC PP-->MEM IDMAC channel */
--              init_idmac_channel(ctx, chan->out_chan, d_image,
--                                 ctx->rot_mode, false, tile);
--      }
--
--      /* enable the IC */
--      ipu_ic_enable(chan->ic);
--
--      /* set buffers ready */
--      ipu_idmac_select_buffer(chan->in_chan, 0);
--      ipu_idmac_select_buffer(chan->out_chan, 0);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode))
--              ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
--      if (ctx->double_buffering) {
--              ipu_idmac_select_buffer(chan->in_chan, 1);
--              ipu_idmac_select_buffer(chan->out_chan, 1);
--              if (ipu_rot_mode_is_irt(ctx->rot_mode))
--                      ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
--      }
--
--      /* enable the channels! */
--      ipu_idmac_enable_channel(chan->in_chan);
--      ipu_idmac_enable_channel(chan->out_chan);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_idmac_enable_channel(chan->rotation_in_chan);
--              ipu_idmac_enable_channel(chan->rotation_out_chan);
--      }
--
--      ipu_ic_task_enable(chan->ic);
--
--      ipu_cpmem_dump(chan->in_chan);
--      ipu_cpmem_dump(chan->out_chan);
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              ipu_cpmem_dump(chan->rotation_in_chan);
--              ipu_cpmem_dump(chan->rotation_out_chan);
--      }
--
--      ipu_dump(priv->ipu);
--
--      return 0;
--}
--
--/* hold irqlock when calling */
--static int do_run(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      ctx->in.base.phys0 = run->in_phys;
--      ctx->out.base.phys0 = run->out_phys;
--
--      ctx->cur_buf_num = 0;
--      ctx->next_tile = 1;
--
--      /* remove run from pending_q and set as current */
--      list_del(&run->list);
--      chan->current_run = run;
--
--      return convert_start(run, 0);
--}
--
--/* hold irqlock when calling */
--static void run_next(struct ipu_image_convert_chan *chan)
--{
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run, *tmp;
--      int ret;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
--              /* skip contexts that are aborting */
--              if (run->ctx->aborting) {
--                      dev_dbg(priv->ipu->dev,
--                              "%s: task %u: skipping aborting ctx %p run %p\n",
--                              __func__, chan->ic_task, run->ctx, run);
--                      continue;
--              }
--
--              ret = do_run(run);
--              if (!ret)
--                      break;
--
--              /*
--               * something went wrong with start, add the run
--               * to done q and continue to the next run in the
--               * pending q.
--               */
--              run->status = ret;
--              list_add_tail(&run->list, &chan->done_q);
--              chan->current_run = NULL;
--      }
--}
--
--static void empty_done_q(struct ipu_image_convert_chan *chan)
--{
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      while (!list_empty(&chan->done_q)) {
--              run = list_entry(chan->done_q.next,
--                               struct ipu_image_convert_run,
--                               list);
--
--              list_del(&run->list);
--
--              dev_dbg(priv->ipu->dev,
--                      "%s: task %u: completing ctx %p run %p with %d\n",
--                      __func__, chan->ic_task, run->ctx, run, run->status);
--
--              /* call the completion callback and free the run */
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              run->ctx->complete(run, run->ctx->complete_context);
--              spin_lock_irqsave(&chan->irqlock, flags);
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--}
--
--/*
-- * the bottom half thread clears out the done_q, calling the
-- * completion handler for each.
-- */
--static irqreturn_t do_bh(int irq, void *dev_id)
--{
--      struct ipu_image_convert_chan *chan = dev_id;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
--              chan->ic_task);
--
--      empty_done_q(chan);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /*
--       * the done_q is cleared out, signal any contexts
--       * that are aborting that abort can complete.
--       */
--      list_for_each_entry(ctx, &chan->ctx_list, list) {
--              if (ctx->aborting) {
--                      dev_dbg(priv->ipu->dev,
--                              "%s: task %u: signaling abort for ctx %p\n",
--                              __func__, chan->ic_task, ctx);
--                      complete_all(&ctx->aborted);
--              }
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
--              chan->ic_task);
--
--      return IRQ_HANDLED;
--}
--
--static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
--{
--      unsigned int cur_tile = ctx->next_tile - 1;
--      unsigned int next_tile = ctx->next_tile;
--
--      if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
--          ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
--          ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
--          ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
--          ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
--          ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
--          ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
--          ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
--              return true;
--
--      return false;
--}
--
--/* hold irqlock when calling */
--static irqreturn_t do_irq(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_ctx *ctx = run->ctx;
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_tile *src_tile, *dst_tile;
--      struct ipu_image_convert_image *s_image = &ctx->in;
--      struct ipu_image_convert_image *d_image = &ctx->out;
--      struct ipuv3_channel *outch;
--      unsigned int dst_idx;
--
--      lockdep_assert_held(&chan->irqlock);
--
--      outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
--              chan->rotation_out_chan : chan->out_chan;
--
--      /*
--       * It is difficult to stop the channel DMA before the channels
--       * enter the paused state. Without double-buffering the channels
--       * are always in a paused state when the EOF irq occurs, so it
--       * is safe to stop the channels now. For double-buffering we
--       * just ignore the abort until the operation completes, when it
--       * is safe to shut down.
--       */
--      if (ctx->aborting && !ctx->double_buffering) {
--              convert_stop(run);
--              run->status = -EIO;
--              goto done;
--      }
--
--      if (ctx->next_tile == ctx->num_tiles) {
--              /*
--               * the conversion is complete
--               */
--              convert_stop(run);
--              run->status = 0;
--              goto done;
--      }
--
--      /*
--       * not done, place the next tile buffers.
--       */
--      if (!ctx->double_buffering) {
--              if (ic_settings_changed(ctx)) {
--                      convert_stop(run);
--                      convert_start(run, ctx->next_tile);
--              } else {
--                      src_tile = &s_image->tile[ctx->next_tile];
--                      dst_idx = ctx->out_tile_map[ctx->next_tile];
--                      dst_tile = &d_image->tile[dst_idx];
--
--                      ipu_cpmem_set_buffer(chan->in_chan, 0,
--                                           s_image->base.phys0 +
--                                           src_tile->offset);
--                      ipu_cpmem_set_buffer(outch, 0,
--                                           d_image->base.phys0 +
--                                           dst_tile->offset);
--                      if (s_image->fmt->planar)
--                              ipu_cpmem_set_uv_offset(chan->in_chan,
--                                                      src_tile->u_off,
--                                                      src_tile->v_off);
--                      if (d_image->fmt->planar)
--                              ipu_cpmem_set_uv_offset(outch,
--                                                      dst_tile->u_off,
--                                                      dst_tile->v_off);
--
--                      ipu_idmac_select_buffer(chan->in_chan, 0);
--                      ipu_idmac_select_buffer(outch, 0);
--              }
--      } else if (ctx->next_tile < ctx->num_tiles - 1) {
--
--              src_tile = &s_image->tile[ctx->next_tile + 1];
--              dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
--              dst_tile = &d_image->tile[dst_idx];
--
--              ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
--                                   s_image->base.phys0 + src_tile->offset);
--              ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
--                                   d_image->base.phys0 + dst_tile->offset);
--
--              ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
--              ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
--
--              ctx->cur_buf_num ^= 1;
--      }
--
--      ctx->next_tile++;
--      return IRQ_HANDLED;
--done:
--      list_add_tail(&run->list, &chan->done_q);
--      chan->current_run = NULL;
--      run_next(chan);
--      return IRQ_WAKE_THREAD;
--}
--
--static irqreturn_t norotate_irq(int irq, void *data)
--{
--      struct ipu_image_convert_chan *chan = data;
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--      irqreturn_t ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* get current run and its context */
--      run = chan->current_run;
--      if (!run) {
--              ret = IRQ_NONE;
--              goto out;
--      }
--
--      ctx = run->ctx;
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* this is a rotation operation, just ignore */
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              return IRQ_HANDLED;
--      }
--
--      ret = do_irq(run);
--out:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--
--static irqreturn_t rotate_irq(int irq, void *data)
--{
--      struct ipu_image_convert_chan *chan = data;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--      irqreturn_t ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* get current run and its context */
--      run = chan->current_run;
--      if (!run) {
--              ret = IRQ_NONE;
--              goto out;
--      }
--
--      ctx = run->ctx;
--
--      if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              /* this was NOT a rotation operation, shouldn't happen */
--              dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
--              spin_unlock_irqrestore(&chan->irqlock, flags);
--              return IRQ_HANDLED;
--      }
--
--      ret = do_irq(run);
--out:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--
--/*
-- * try to force the completion of runs for this ctx. Called when
-- * abort wait times out in ipu_image_convert_abort().
-- */
--static void force_abort(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_run *run;
--      unsigned long flags;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      run = chan->current_run;
--      if (run && run->ctx == ctx) {
--              convert_stop(run);
--              run->status = -EIO;
--              list_add_tail(&run->list, &chan->done_q);
--              chan->current_run = NULL;
--              run_next(chan);
--      }
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      empty_done_q(chan);
--}
--
--static void release_ipu_resources(struct ipu_image_convert_chan *chan)
--{
--      if (chan->out_eof_irq >= 0)
--              free_irq(chan->out_eof_irq, chan);
--      if (chan->rot_out_eof_irq >= 0)
--              free_irq(chan->rot_out_eof_irq, chan);
--
--      if (!IS_ERR_OR_NULL(chan->in_chan))
--              ipu_idmac_put(chan->in_chan);
--      if (!IS_ERR_OR_NULL(chan->out_chan))
--              ipu_idmac_put(chan->out_chan);
--      if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
--              ipu_idmac_put(chan->rotation_in_chan);
--      if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
--              ipu_idmac_put(chan->rotation_out_chan);
--      if (!IS_ERR_OR_NULL(chan->ic))
--              ipu_ic_put(chan->ic);
--
--      chan->in_chan = chan->out_chan = chan->rotation_in_chan =
--              chan->rotation_out_chan = NULL;
--      chan->out_eof_irq = chan->rot_out_eof_irq = -1;
--}
--
--static int get_ipu_resources(struct ipu_image_convert_chan *chan)
--{
--      const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      int ret;
--
--      /* get IC */
--      chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
--      if (IS_ERR(chan->ic)) {
--              dev_err(priv->ipu->dev, "could not acquire IC\n");
--              ret = PTR_ERR(chan->ic);
--              goto err;
--      }
--
--      /* get IDMAC channels */
--      chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
--      chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
--      if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
--              dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
--              ret = -EBUSY;
--              goto err;
--      }
--
--      chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
--      chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
--      if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
--              dev_err(priv->ipu->dev,
--                      "could not acquire idmac rotation channels\n");
--              ret = -EBUSY;
--              goto err;
--      }
--
--      /* acquire the EOF interrupts */
--      chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
--                                                chan->out_chan,
--                                                IPU_IRQ_EOF);
--
--      ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
--                                 0, "ipu-ic", chan);
--      if (ret < 0) {
--              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
--                       chan->out_eof_irq);
--              chan->out_eof_irq = -1;
--              goto err;
--      }
--
--      chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
--                                                   chan->rotation_out_chan,
--                                                   IPU_IRQ_EOF);
--
--      ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
--                                 0, "ipu-ic", chan);
--      if (ret < 0) {
--              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
--                      chan->rot_out_eof_irq);
--              chan->rot_out_eof_irq = -1;
--              goto err;
--      }
--
--      return 0;
--err:
--      release_ipu_resources(chan);
--      return ret;
--}
--
--static int fill_image(struct ipu_image_convert_ctx *ctx,
--                    struct ipu_image_convert_image *ic_image,
--                    struct ipu_image *image,
--                    enum ipu_image_convert_type type)
--{
--      struct ipu_image_convert_priv *priv = ctx->chan->priv;
--
--      ic_image->base = *image;
--      ic_image->type = type;
--
--      ic_image->fmt = get_format(image->pix.pixelformat);
--      if (!ic_image->fmt) {
--              dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
--                      type == IMAGE_CONVERT_OUT ? "Output" : "Input");
--              return -EINVAL;
--      }
--
--      if (ic_image->fmt->planar)
--              ic_image->stride = ic_image->base.pix.width;
--      else
--              ic_image->stride  = ic_image->base.pix.bytesperline;
--
--      return 0;
--}
--
--/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
--static unsigned int clamp_align(unsigned int x, unsigned int min,
--                              unsigned int max, unsigned int align)
--{
--      /* Bits that must be zero to be aligned */
--      unsigned int mask = ~((1 << align) - 1);
--
--      /* Clamp to aligned min and max */
--      x = clamp(x, (min + ~mask) & mask, max & mask);
--
--      /* Round to nearest aligned value */
--      if (align)
--              x = (x + (1 << (align - 1))) & mask;
--
--      return x;
--}
--
--/* Adjusts input/output images to IPU restrictions */
--void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
--                            enum ipu_rotate_mode rot_mode)
--{
--      const struct ipu_image_pixfmt *infmt, *outfmt;
--      u32 w_align_out, h_align_out;
--      u32 w_align_in, h_align_in;
--
--      infmt = get_format(in->pix.pixelformat);
--      outfmt = get_format(out->pix.pixelformat);
--
--      /* set some default pixel formats if needed */
--      if (!infmt) {
--              in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
--              infmt = get_format(V4L2_PIX_FMT_RGB24);
--      }
--      if (!outfmt) {
--              out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
--              outfmt = get_format(V4L2_PIX_FMT_RGB24);
--      }
--
--      /* image converter does not handle fields */
--      in->pix.field = out->pix.field = V4L2_FIELD_NONE;
--
--      /* resizer cannot downsize more than 4:1 */
--      if (ipu_rot_mode_is_irt(rot_mode)) {
--              out->pix.height = max_t(__u32, out->pix.height,
--                                      in->pix.width / 4);
--              out->pix.width = max_t(__u32, out->pix.width,
--                                     in->pix.height / 4);
--      } else {
--              out->pix.width = max_t(__u32, out->pix.width,
--                                     in->pix.width / 4);
--              out->pix.height = max_t(__u32, out->pix.height,
--                                      in->pix.height / 4);
--      }
--
--      /* align input width/height */
--      w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
--                                          rot_mode));
--      h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
--                                           rot_mode));
--      in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
--                                  w_align_in);
--      in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
--                                   h_align_in);
--
--      /* align output width/height */
--      w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
--                                           rot_mode));
--      h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
--                                            rot_mode));
--      out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
--                                   w_align_out);
--      out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
--                                    h_align_out);
--
--      /* set input/output strides and image sizes */
--      in->pix.bytesperline = infmt->planar ?
--              clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
--                          w_align_in) :
--              clamp_align((in->pix.width * infmt->bpp) >> 3,
--                          ((2 << w_align_in) * infmt->bpp) >> 3,
--                          (MAX_W * infmt->bpp) >> 3,
--                          w_align_in);
--      in->pix.sizeimage = infmt->planar ?
--              (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
--              in->pix.height * in->pix.bytesperline;
--      out->pix.bytesperline = outfmt->planar ? out->pix.width :
--              (out->pix.width * outfmt->bpp) >> 3;
--      out->pix.sizeimage = outfmt->planar ?
--              (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
--              out->pix.height * out->pix.bytesperline;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
--
--/*
-- * this is used by ipu_image_convert_prepare() to verify set input and
-- * output images are valid before starting the conversion. Clients can
-- * also call it before calling ipu_image_convert_prepare().
-- */
--int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
--                           enum ipu_rotate_mode rot_mode)
--{
--      struct ipu_image testin, testout;
--
--      testin = *in;
--      testout = *out;
--
--      ipu_image_convert_adjust(&testin, &testout, rot_mode);
--
--      if (testin.pix.width != in->pix.width ||
--          testin.pix.height != in->pix.height ||
--          testout.pix.width != out->pix.width ||
--          testout.pix.height != out->pix.height)
--              return -EINVAL;
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
--
--/*
-- * Call ipu_image_convert_prepare() to prepare for the conversion of
-- * given images and rotation mode. Returns a new conversion context.
-- */
--struct ipu_image_convert_ctx *
--ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                        struct ipu_image *in, struct ipu_image *out,
--                        enum ipu_rotate_mode rot_mode,
--                        ipu_image_convert_cb_t complete,
--                        void *complete_context)
--{
--      struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
--      struct ipu_image_convert_image *s_image, *d_image;
--      struct ipu_image_convert_chan *chan;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--      unsigned int i;
--      bool get_res;
--      int ret;
--
--      if (!in || !out || !complete ||
--          (ic_task != IC_TASK_VIEWFINDER &&
--           ic_task != IC_TASK_POST_PROCESSOR))
--              return ERR_PTR(-EINVAL);
--
--      /* verify the in/out images before continuing */
--      ret = ipu_image_convert_verify(in, out, rot_mode);
--      if (ret) {
--              dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
--                      __func__);
--              return ERR_PTR(ret);
--      }
--
--      chan = &priv->chan[ic_task];
--
--      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
--      if (!ctx)
--              return ERR_PTR(-ENOMEM);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
--              chan->ic_task, ctx);
--
--      ctx->chan = chan;
--      init_completion(&ctx->aborted);
--
--      ctx->rot_mode = rot_mode;
--
--      /* Sets ctx->in.num_rows/cols as well */
--      ret = calc_image_resize_coefficients(ctx, in, out);
--      if (ret)
--              goto out_free;
--
--      s_image = &ctx->in;
--      d_image = &ctx->out;
--
--      /* set tiling and rotation */
--      if (ipu_rot_mode_is_irt(rot_mode)) {
--              d_image->num_rows = s_image->num_cols;
--              d_image->num_cols = s_image->num_rows;
--      } else {
--              d_image->num_rows = s_image->num_rows;
--              d_image->num_cols = s_image->num_cols;
--      }
--
--      ctx->num_tiles = d_image->num_cols * d_image->num_rows;
--
--      ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
--      if (ret)
--              goto out_free;
--      ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
--      if (ret)
--              goto out_free;
--
--      calc_out_tile_map(ctx);
--
--      find_seams(ctx, s_image, d_image);
--
--      ret = calc_tile_dimensions(ctx, s_image);
--      if (ret)
--              goto out_free;
--
--      ret = calc_tile_offsets(ctx, s_image);
--      if (ret)
--              goto out_free;
--
--      calc_tile_dimensions(ctx, d_image);
--      ret = calc_tile_offsets(ctx, d_image);
--      if (ret)
--              goto out_free;
--
--      calc_tile_resize_coefficients(ctx);
--
--      ret = ipu_ic_calc_csc(&ctx->csc,
--                      s_image->base.pix.ycbcr_enc,
--                      s_image->base.pix.quantization,
--                      ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
--                      d_image->base.pix.ycbcr_enc,
--                      d_image->base.pix.quantization,
--                      ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
--      if (ret)
--              goto out_free;
--
--      dump_format(ctx, s_image);
--      dump_format(ctx, d_image);
--
--      ctx->complete = complete;
--      ctx->complete_context = complete_context;
--
--      /*
--       * Can we use double-buffering for this operation? If there is
--       * only one tile (the whole image can be converted in a single
--       * operation) there's no point in using double-buffering. Also,
--       * the IPU's IDMAC channels allow only a single U and V plane
--       * offset shared between both buffers, but these offsets change
--       * for every tile, and therefore would have to be updated for
--       * each buffer which is not possible. So double-buffering is
--       * impossible when either the source or destination images are
--       * a planar format (YUV420, YUV422P, etc.). Further, differently
--       * sized tiles or different resizing coefficients per tile
--       * prevent double-buffering as well.
--       */
--      ctx->double_buffering = (ctx->num_tiles > 1 &&
--                               !s_image->fmt->planar &&
--                               !d_image->fmt->planar);
--      for (i = 1; i < ctx->num_tiles; i++) {
--              if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
--                  ctx->in.tile[i].height != ctx->in.tile[0].height ||
--                  ctx->out.tile[i].width != ctx->out.tile[0].width ||
--                  ctx->out.tile[i].height != ctx->out.tile[0].height) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--      for (i = 1; i < ctx->in.num_cols; i++) {
--              if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--      for (i = 1; i < ctx->in.num_rows; i++) {
--              if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
--                      ctx->double_buffering = false;
--                      break;
--              }
--      }
--
--      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
--              unsigned long intermediate_size = d_image->tile[0].size;
--
--              for (i = 1; i < ctx->num_tiles; i++) {
--                      if (d_image->tile[i].size > intermediate_size)
--                              intermediate_size = d_image->tile[i].size;
--              }
--
--              ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
--                                  intermediate_size);
--              if (ret)
--                      goto out_free;
--              if (ctx->double_buffering) {
--                      ret = alloc_dma_buf(priv,
--                                          &ctx->rot_intermediate[1],
--                                          intermediate_size);
--                      if (ret)
--                              goto out_free_dmabuf0;
--              }
--      }
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      get_res = list_empty(&chan->ctx_list);
--
--      list_add_tail(&ctx->list, &chan->ctx_list);
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (get_res) {
--              ret = get_ipu_resources(chan);
--              if (ret)
--                      goto out_free_dmabuf1;
--      }
--
--      return ctx;
--
--out_free_dmabuf1:
--      free_dma_buf(priv, &ctx->rot_intermediate[1]);
--      spin_lock_irqsave(&chan->irqlock, flags);
--      list_del(&ctx->list);
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--out_free_dmabuf0:
--      free_dma_buf(priv, &ctx->rot_intermediate[0]);
--out_free:
--      kfree(ctx);
--      return ERR_PTR(ret);
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
--
--/*
-- * Carry out a single image conversion run. Only the physaddr's of the input
-- * and output image buffers are needed. The conversion context must have
-- * been created previously with ipu_image_convert_prepare().
-- */
--int ipu_image_convert_queue(struct ipu_image_convert_run *run)
--{
--      struct ipu_image_convert_chan *chan;
--      struct ipu_image_convert_priv *priv;
--      struct ipu_image_convert_ctx *ctx;
--      unsigned long flags;
--      int ret = 0;
--
--      if (!run || !run->ctx || !run->in_phys || !run->out_phys)
--              return -EINVAL;
--
--      ctx = run->ctx;
--      chan = ctx->chan;
--      priv = chan->priv;
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
--              chan->ic_task, ctx, run);
--
--      INIT_LIST_HEAD(&run->list);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      if (ctx->aborting) {
--              ret = -EIO;
--              goto unlock;
--      }
--
--      list_add_tail(&run->list, &chan->pending_q);
--
--      if (!chan->current_run) {
--              ret = do_run(run);
--              if (ret)
--                      chan->current_run = NULL;
--      }
--unlock:
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
--
--/* Abort any active or pending conversions for this context */
--static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      struct ipu_image_convert_run *run, *active_run, *tmp;
--      unsigned long flags;
--      int run_count, ret;
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      /* move all remaining pending runs in this context to done_q */
--      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
--              if (run->ctx != ctx)
--                      continue;
--              run->status = -EIO;
--              list_move_tail(&run->list, &chan->done_q);
--      }
--
--      run_count = get_run_count(ctx, &chan->done_q);
--      active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
--              chan->current_run : NULL;
--
--      if (active_run)
--              reinit_completion(&ctx->aborted);
--
--      ctx->aborting = true;
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (!run_count && !active_run) {
--              dev_dbg(priv->ipu->dev,
--                      "%s: task %u: no abort needed for ctx %p\n",
--                      __func__, chan->ic_task, ctx);
--              return;
--      }
--
--      if (!active_run) {
--              empty_done_q(chan);
--              return;
--      }
--
--      dev_dbg(priv->ipu->dev,
--              "%s: task %u: wait for completion: %d runs\n",
--              __func__, chan->ic_task, run_count);
--
--      ret = wait_for_completion_timeout(&ctx->aborted,
--                                        msecs_to_jiffies(10000));
--      if (ret == 0) {
--              dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
--              force_abort(ctx);
--      }
--}
--
--void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
--{
--      __ipu_image_convert_abort(ctx);
--      ctx->aborting = false;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
--
--/* Unprepare image conversion context */
--void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
--{
--      struct ipu_image_convert_chan *chan = ctx->chan;
--      struct ipu_image_convert_priv *priv = chan->priv;
--      unsigned long flags;
--      bool put_res;
--
--      /* make sure no runs are hanging around */
--      __ipu_image_convert_abort(ctx);
--
--      dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
--              chan->ic_task, ctx);
--
--      spin_lock_irqsave(&chan->irqlock, flags);
--
--      list_del(&ctx->list);
--
--      put_res = list_empty(&chan->ctx_list);
--
--      spin_unlock_irqrestore(&chan->irqlock, flags);
--
--      if (put_res)
--              release_ipu_resources(chan);
--
--      free_dma_buf(priv, &ctx->rot_intermediate[1]);
--      free_dma_buf(priv, &ctx->rot_intermediate[0]);
--
--      kfree(ctx);
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
--
--/*
-- * "Canned" asynchronous single image conversion. Allocates and returns
-- * a new conversion run.  On successful return the caller must free the
-- * run and call ipu_image_convert_unprepare() after conversion completes.
-- */
--struct ipu_image_convert_run *
--ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                struct ipu_image *in, struct ipu_image *out,
--                enum ipu_rotate_mode rot_mode,
--                ipu_image_convert_cb_t complete,
--                void *complete_context)
--{
--      struct ipu_image_convert_ctx *ctx;
--      struct ipu_image_convert_run *run;
--      int ret;
--
--      ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
--                                      complete, complete_context);
--      if (IS_ERR(ctx))
--              return ERR_CAST(ctx);
--
--      run = kzalloc(sizeof(*run), GFP_KERNEL);
--      if (!run) {
--              ipu_image_convert_unprepare(ctx);
--              return ERR_PTR(-ENOMEM);
--      }
--
--      run->ctx = ctx;
--      run->in_phys = in->phys0;
--      run->out_phys = out->phys0;
--
--      ret = ipu_image_convert_queue(run);
--      if (ret) {
--              ipu_image_convert_unprepare(ctx);
--              kfree(run);
--              return ERR_PTR(ret);
--      }
--
--      return run;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert);
--
--/* "Canned" synchronous single image conversion */
--static void image_convert_sync_complete(struct ipu_image_convert_run *run,
--                                      void *data)
--{
--      struct completion *comp = data;
--
--      complete(comp);
--}
--
--int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
--                         struct ipu_image *in, struct ipu_image *out,
--                         enum ipu_rotate_mode rot_mode)
--{
--      struct ipu_image_convert_run *run;
--      struct completion comp;
--      int ret;
--
--      init_completion(&comp);
--
--      run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
--                              image_convert_sync_complete, &comp);
--      if (IS_ERR(run))
--              return PTR_ERR(run);
--
--      ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
--      ret = (ret == 0) ? -ETIMEDOUT : 0;
--
--      ipu_image_convert_unprepare(run->ctx);
--      kfree(run);
--
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
--
--int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
--{
--      struct ipu_image_convert_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->image_convert_priv = priv;
--      priv->ipu = ipu;
--
--      for (i = 0; i < IC_NUM_TASKS; i++) {
--              struct ipu_image_convert_chan *chan = &priv->chan[i];
--
--              chan->ic_task = i;
--              chan->priv = priv;
--              chan->dma_ch = &image_convert_dma_chan[i];
--              chan->out_eof_irq = -1;
--              chan->rot_out_eof_irq = -1;
--
--              spin_lock_init(&chan->irqlock);
--              INIT_LIST_HEAD(&chan->ctx_list);
--              INIT_LIST_HEAD(&chan->pending_q);
--              INIT_LIST_HEAD(&chan->done_q);
--      }
--
--      return 0;
--}
--
--void ipu_image_convert_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-pre.c
-+++ /dev/null
-@@ -1,346 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-only
--/*
-- * Copyright (c) 2017 Lucas Stach, Pengutronix
-- */
--
--#include <drm/drm_fourcc.h>
--#include <linux/clk.h>
--#include <linux/err.h>
--#include <linux/genalloc.h>
--#include <linux/module.h>
--#include <linux/of.h>
--#include <linux/platform_device.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--#define IPU_PRE_MAX_WIDTH     2048
--#define IPU_PRE_NUM_SCANLINES 8
--
--#define IPU_PRE_CTRL                                  0x000
--#define IPU_PRE_CTRL_SET                              0x004
--#define  IPU_PRE_CTRL_ENABLE                          (1 << 0)
--#define  IPU_PRE_CTRL_BLOCK_EN                                (1 << 1)
--#define  IPU_PRE_CTRL_BLOCK_16                                (1 << 2)
--#define  IPU_PRE_CTRL_SDW_UPDATE                      (1 << 4)
--#define  IPU_PRE_CTRL_VFLIP                           (1 << 5)
--#define  IPU_PRE_CTRL_SO                              (1 << 6)
--#define  IPU_PRE_CTRL_INTERLACED_FIELD                        (1 << 7)
--#define  IPU_PRE_CTRL_HANDSHAKE_EN                    (1 << 8)
--#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)           ((v & 0x3) << 9)
--#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN         (1 << 11)
--#define  IPU_PRE_CTRL_EN_REPEAT                               (1 << 28)
--#define  IPU_PRE_CTRL_TPR_REST_SEL                    (1 << 29)
--#define  IPU_PRE_CTRL_CLKGATE                         (1 << 30)
--#define  IPU_PRE_CTRL_SFTRST                          (1 << 31)
--
--#define IPU_PRE_CUR_BUF                                       0x030
--
--#define IPU_PRE_NEXT_BUF                              0x040
--
--#define IPU_PRE_TPR_CTRL                              0x070
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)              ((v & 0xff) << 0)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK            0xff
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT          (1 << 0)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF               (1 << 4)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF      (1 << 5)
--#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED     (1 << 6)
--
--#define IPU_PRE_PREFETCH_ENG_CTRL                     0x080
--#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN            (1 << 0)
--#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)                ((v & 0x7) << 1)
--#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)    ((v & 0x3) << 4)
--#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)  ((v & 0x7) << 8)
--#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS           (1 << 11)
--#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE          (1 << 12)
--#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP                (1 << 14)
--#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN     (1 << 15)
--
--#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                       0x0a0
--#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)     ((v & 0xffff) << 0)
--#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)    ((v & 0xffff) << 16)
--
--#define IPU_PRE_PREFETCH_ENG_PITCH                    0x0d0
--#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)              ((v & 0xffff) << 0)
--#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)             ((v & 0xffff) << 16)
--
--#define IPU_PRE_STORE_ENG_CTRL                                0x110
--#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN              (1 << 0)
--#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)               ((v & 0x7) << 1)
--#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)  ((v & 0x3) << 4)
--
--#define IPU_PRE_STORE_ENG_STATUS                      0x120
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK  0xffff
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK  0x3fff
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL     (1 << 30)
--#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD         (1 << 31)
--
--#define IPU_PRE_STORE_ENG_SIZE                                0x130
--#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)                ((v & 0xffff) << 0)
--#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)               ((v & 0xffff) << 16)
--
--#define IPU_PRE_STORE_ENG_PITCH                               0x140
--#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)         ((v & 0xffff) << 0)
--
--#define IPU_PRE_STORE_ENG_ADDR                                0x150
--
--struct ipu_pre {
--      struct list_head        list;
--      struct device           *dev;
--
--      void __iomem            *regs;
--      struct clk              *clk_axi;
--      struct gen_pool         *iram;
--
--      dma_addr_t              buffer_paddr;
--      void                    *buffer_virt;
--      bool                    in_use;
--      unsigned int            safe_window_end;
--      unsigned int            last_bufaddr;
--};
--
--static DEFINE_MUTEX(ipu_pre_list_mutex);
--static LIST_HEAD(ipu_pre_list);
--static int available_pres;
--
--int ipu_pre_get_available_count(void)
--{
--      return available_pres;
--}
--
--struct ipu_pre *
--ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
--{
--      struct device_node *pre_node = of_parse_phandle(dev->of_node,
--                                                      name, index);
--      struct ipu_pre *pre;
--
--      mutex_lock(&ipu_pre_list_mutex);
--      list_for_each_entry(pre, &ipu_pre_list, list) {
--              if (pre_node == pre->dev->of_node) {
--                      mutex_unlock(&ipu_pre_list_mutex);
--                      device_link_add(dev, pre->dev,
--                                      DL_FLAG_AUTOREMOVE_CONSUMER);
--                      of_node_put(pre_node);
--                      return pre;
--              }
--      }
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      of_node_put(pre_node);
--
--      return NULL;
--}
--
--int ipu_pre_get(struct ipu_pre *pre)
--{
--      u32 val;
--
--      if (pre->in_use)
--              return -EBUSY;
--
--      /* first get the engine out of reset and remove clock gating */
--      writel(0, pre->regs + IPU_PRE_CTRL);
--
--      /* init defaults that should be applied to all streams */
--      val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
--            IPU_PRE_CTRL_HANDSHAKE_EN |
--            IPU_PRE_CTRL_TPR_REST_SEL |
--            IPU_PRE_CTRL_SDW_UPDATE;
--      writel(val, pre->regs + IPU_PRE_CTRL);
--
--      pre->in_use = true;
--      return 0;
--}
--
--void ipu_pre_put(struct ipu_pre *pre)
--{
--      writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
--
--      pre->in_use = false;
--}
--
--void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
--                     unsigned int height, unsigned int stride, u32 format,
--                     uint64_t modifier, unsigned int bufaddr)
--{
--      const struct drm_format_info *info = drm_format_info(format);
--      u32 active_bpp = info->cpp[0] >> 1;
--      u32 val;
--
--      /* calculate safe window for ctrl register updates */
--      if (modifier == DRM_FORMAT_MOD_LINEAR)
--              pre->safe_window_end = height - 2;
--      else
--              pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
--
--      writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
--      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
--      pre->last_bufaddr = bufaddr;
--
--      val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
--            IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
--            IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
--            IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
--            IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
--
--      val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
--            IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
--
--      val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
--      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
--
--      val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
--            IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
--            IPU_PRE_STORE_ENG_CTRL_STORE_EN;
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
--
--      val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
--            IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
--
--      val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
--      writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
--
--      writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
--
--      val = readl(pre->regs + IPU_PRE_TPR_CTRL);
--      val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
--      if (modifier != DRM_FORMAT_MOD_LINEAR) {
--              /* only support single buffer formats for now */
--              val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
--              if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
--                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
--              if (info->cpp[0] == 2)
--                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
--      }
--      writel(val, pre->regs + IPU_PRE_TPR_CTRL);
--
--      val = readl(pre->regs + IPU_PRE_CTRL);
--      val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
--             IPU_PRE_CTRL_SDW_UPDATE;
--      if (modifier == DRM_FORMAT_MOD_LINEAR)
--              val &= ~IPU_PRE_CTRL_BLOCK_EN;
--      else
--              val |= IPU_PRE_CTRL_BLOCK_EN;
--      writel(val, pre->regs + IPU_PRE_CTRL);
--}
--
--void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
--{
--      unsigned long timeout = jiffies + msecs_to_jiffies(5);
--      unsigned short current_yblock;
--      u32 val;
--
--      if (bufaddr == pre->last_bufaddr)
--              return;
--
--      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
--      pre->last_bufaddr = bufaddr;
--
--      do {
--              if (time_after(jiffies, timeout)) {
--                      dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
--                      return;
--              }
--
--              val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
--              current_yblock =
--                      (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
--                      IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
--      } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
--
--      writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
--}
--
--bool ipu_pre_update_pending(struct ipu_pre *pre)
--{
--      return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
--                IPU_PRE_CTRL_SDW_UPDATE);
--}
--
--u32 ipu_pre_get_baddr(struct ipu_pre *pre)
--{
--      return (u32)pre->buffer_paddr;
--}
--
--static int ipu_pre_probe(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      struct resource *res;
--      struct ipu_pre *pre;
--
--      pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
--      if (!pre)
--              return -ENOMEM;
--
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      pre->regs = devm_ioremap_resource(&pdev->dev, res);
--      if (IS_ERR(pre->regs))
--              return PTR_ERR(pre->regs);
--
--      pre->clk_axi = devm_clk_get(dev, "axi");
--      if (IS_ERR(pre->clk_axi))
--              return PTR_ERR(pre->clk_axi);
--
--      pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
--      if (!pre->iram)
--              return -EPROBE_DEFER;
--
--      /*
--       * Allocate IRAM buffer with maximum size. This could be made dynamic,
--       * but as there is no other user of this IRAM region and we can fit all
--       * max sized buffers into it, there is no need yet.
--       */
--      pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
--                                            IPU_PRE_NUM_SCANLINES * 4,
--                                            &pre->buffer_paddr);
--      if (!pre->buffer_virt)
--              return -ENOMEM;
--
--      clk_prepare_enable(pre->clk_axi);
--
--      pre->dev = dev;
--      platform_set_drvdata(pdev, pre);
--      mutex_lock(&ipu_pre_list_mutex);
--      list_add(&pre->list, &ipu_pre_list);
--      available_pres++;
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      return 0;
--}
--
--static int ipu_pre_remove(struct platform_device *pdev)
--{
--      struct ipu_pre *pre = platform_get_drvdata(pdev);
--
--      mutex_lock(&ipu_pre_list_mutex);
--      list_del(&pre->list);
--      available_pres--;
--      mutex_unlock(&ipu_pre_list_mutex);
--
--      clk_disable_unprepare(pre->clk_axi);
--
--      if (pre->buffer_virt)
--              gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
--                            IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
--      return 0;
--}
--
--static const struct of_device_id ipu_pre_dt_ids[] = {
--      { .compatible = "fsl,imx6qp-pre", },
--      { /* sentinel */ },
--};
--
--struct platform_driver ipu_pre_drv = {
--      .probe          = ipu_pre_probe,
--      .remove         = ipu_pre_remove,
--      .driver         = {
--              .name   = "imx-ipu-pre",
--              .of_match_table = ipu_pre_dt_ids,
--      },
--};
---- a/drivers/gpu/imx/ipu-v3/ipu-prg.c
-+++ /dev/null
-@@ -1,483 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-only
--/*
-- * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
-- */
--
--#include <drm/drm_fourcc.h>
--#include <linux/clk.h>
--#include <linux/err.h>
--#include <linux/iopoll.h>
--#include <linux/mfd/syscon.h>
--#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
--#include <linux/module.h>
--#include <linux/of.h>
--#include <linux/platform_device.h>
--#include <linux/pm_runtime.h>
--#include <linux/regmap.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--#define IPU_PRG_CTL                           0x00
--#define  IPU_PRG_CTL_BYPASS(i)                        (1 << (0 + i))
--#define  IPU_PRG_CTL_SOFT_ARID_MASK           0x3
--#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)               (8 + i * 2)
--#define  IPU_PRG_CTL_SOFT_ARID(i, v)          ((v & 0x3) << (8 + 2 * i))
--#define  IPU_PRG_CTL_SO(i)                    (1 << (16 + i))
--#define  IPU_PRG_CTL_VFLIP(i)                 (1 << (19 + i))
--#define  IPU_PRG_CTL_BLOCK_MODE(i)            (1 << (22 + i))
--#define  IPU_PRG_CTL_CNT_LOAD_EN(i)           (1 << (25 + i))
--#define  IPU_PRG_CTL_SOFTRST                  (1 << 30)
--#define  IPU_PRG_CTL_SHADOW_EN                        (1 << 31)
--
--#define IPU_PRG_STATUS                                0x04
--#define  IPU_PRG_STATUS_BUFFER0_READY(i)      (1 << (0 + i * 2))
--#define  IPU_PRG_STATUS_BUFFER1_READY(i)      (1 << (1 + i * 2))
--
--#define IPU_PRG_QOS                           0x08
--#define  IPU_PRG_QOS_ARID_MASK                        0xf
--#define  IPU_PRG_QOS_ARID_SHIFT(i)            (0 + i * 4)
--
--#define IPU_PRG_REG_UPDATE                    0x0c
--#define  IPU_PRG_REG_UPDATE_REG_UPDATE                (1 << 0)
--
--#define IPU_PRG_STRIDE(i)                     (0x10 + i * 0x4)
--#define  IPU_PRG_STRIDE_STRIDE_MASK           0x3fff
--
--#define IPU_PRG_CROP_LINE                     0x1c
--
--#define IPU_PRG_THD                           0x20
--
--#define IPU_PRG_BADDR(i)                      (0x24 + i * 0x4)
--
--#define IPU_PRG_OFFSET(i)                     (0x30 + i * 0x4)
--
--#define IPU_PRG_ILO(i)                                (0x3c + i * 0x4)
--
--#define IPU_PRG_HEIGHT(i)                     (0x48 + i * 0x4)
--#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK               0xfff
--#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT      0
--#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK               0xfff
--#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT      16
--
--struct ipu_prg_channel {
--      bool                    enabled;
--      int                     used_pre;
--};
--
--struct ipu_prg {
--      struct list_head        list;
--      struct device           *dev;
--      int                     id;
--
--      void __iomem            *regs;
--      struct clk              *clk_ipg, *clk_axi;
--      struct regmap           *iomuxc_gpr;
--      struct ipu_pre          *pres[3];
--
--      struct ipu_prg_channel  chan[3];
--};
--
--static DEFINE_MUTEX(ipu_prg_list_mutex);
--static LIST_HEAD(ipu_prg_list);
--
--struct ipu_prg *
--ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
--{
--      struct device_node *prg_node = of_parse_phandle(dev->of_node,
--                                                      name, 0);
--      struct ipu_prg *prg;
--
--      mutex_lock(&ipu_prg_list_mutex);
--      list_for_each_entry(prg, &ipu_prg_list, list) {
--              if (prg_node == prg->dev->of_node) {
--                      mutex_unlock(&ipu_prg_list_mutex);
--                      device_link_add(dev, prg->dev,
--                                      DL_FLAG_AUTOREMOVE_CONSUMER);
--                      prg->id = ipu_id;
--                      of_node_put(prg_node);
--                      return prg;
--              }
--      }
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      of_node_put(prg_node);
--
--      return NULL;
--}
--
--int ipu_prg_max_active_channels(void)
--{
--      return ipu_pre_get_available_count();
--}
--EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
--
--bool ipu_prg_present(struct ipu_soc *ipu)
--{
--      if (ipu->prg_priv)
--              return true;
--
--      return false;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_present);
--
--bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
--                            uint64_t modifier)
--{
--      const struct drm_format_info *info = drm_format_info(format);
--
--      if (info->num_planes != 1)
--              return false;
--
--      switch (modifier) {
--      case DRM_FORMAT_MOD_LINEAR:
--      case DRM_FORMAT_MOD_VIVANTE_TILED:
--      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
--              return true;
--      default:
--              return false;
--      }
--}
--EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
--
--int ipu_prg_enable(struct ipu_soc *ipu)
--{
--      struct ipu_prg *prg = ipu->prg_priv;
--
--      if (!prg)
--              return 0;
--
--      return pm_runtime_get_sync(prg->dev);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_enable);
--
--void ipu_prg_disable(struct ipu_soc *ipu)
--{
--      struct ipu_prg *prg = ipu->prg_priv;
--
--      if (!prg)
--              return;
--
--      pm_runtime_put(prg->dev);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_disable);
--
--/*
-- * The channel configuartion functions below are not thread safe, as they
-- * must be only called from the atomic commit path in the DRM driver, which
-- * is properly serialized.
-- */
--static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
--{
--      /*
--       * This isn't clearly documented in the RM, but IPU to PRG channel
--       * assignment is fixed, as only with this mapping the control signals
--       * match up.
--       */
--      switch (ipu_chan) {
--      case IPUV3_CHANNEL_MEM_BG_SYNC:
--              return 0;
--      case IPUV3_CHANNEL_MEM_FG_SYNC:
--              return 1;
--      case IPUV3_CHANNEL_MEM_DC_SYNC:
--              return 2;
--      default:
--              return -EINVAL;
--      }
--}
--
--static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
--{
--      int i, ret;
--
--      /* channel 0 is special as it is hardwired to one of the PREs */
--      if (prg_chan == 0) {
--              ret = ipu_pre_get(prg->pres[0]);
--              if (ret)
--                      goto fail;
--              prg->chan[prg_chan].used_pre = 0;
--              return 0;
--      }
--
--      for (i = 1; i < 3; i++) {
--              ret = ipu_pre_get(prg->pres[i]);
--              if (!ret) {
--                      u32 val, mux;
--                      int shift;
--
--                      prg->chan[prg_chan].used_pre = i;
--
--                      /* configure the PRE to PRG channel mux */
--                      shift = (i == 1) ? 12 : 14;
--                      mux = (prg->id << 1) | (prg_chan - 1);
--                      regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
--                                         0x3 << shift, mux << shift);
--
--                      /* check other mux, must not point to same channel */
--                      shift = (i == 1) ? 14 : 12;
--                      regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
--                      if (((val >> shift) & 0x3) == mux) {
--                              regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
--                                                 0x3 << shift,
--                                                 (mux ^ 0x1) << shift);
--                      }
--
--                      return 0;
--              }
--      }
--
--fail:
--      dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
--      return ret;
--}
--
--static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
--{
--      struct ipu_prg_channel *chan = &prg->chan[prg_chan];
--
--      ipu_pre_put(prg->pres[chan->used_pre]);
--      chan->used_pre = -1;
--}
--
--void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--      u32 val;
--
--      if (prg_chan < 0)
--              return;
--
--      chan = &prg->chan[prg_chan];
--      if (!chan->enabled)
--              return;
--
--      pm_runtime_get_sync(prg->dev);
--
--      val = readl(prg->regs + IPU_PRG_CTL);
--      val |= IPU_PRG_CTL_BYPASS(prg_chan);
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
--      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
--
--      pm_runtime_put(prg->dev);
--
--      ipu_prg_put_pre(prg, prg_chan);
--
--      chan->enabled = false;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
--
--int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
--                            unsigned int axi_id, unsigned int width,
--                            unsigned int height, unsigned int stride,
--                            u32 format, uint64_t modifier, unsigned long *eba)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--      u32 val;
--      int ret;
--
--      if (prg_chan < 0)
--              return prg_chan;
--
--      chan = &prg->chan[prg_chan];
--
--      if (chan->enabled) {
--              ipu_pre_update(prg->pres[chan->used_pre], *eba);
--              return 0;
--      }
--
--      ret = ipu_prg_get_pre(prg, prg_chan);
--      if (ret)
--              return ret;
--
--      ipu_pre_configure(prg->pres[chan->used_pre],
--                        width, height, stride, format, modifier, *eba);
--
--
--      pm_runtime_get_sync(prg->dev);
--
--      val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
--      writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
--
--      val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
--             IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
--            ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
--             IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
--      writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
--
--      val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
--      *eba = val;
--      writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
--
--      val = readl(prg->regs + IPU_PRG_CTL);
--      /* config AXI ID */
--      val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
--               IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
--      val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
--      /* enable channel */
--      val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
--      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
--
--      /* wait for both double buffers to be filled */
--      readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
--                         (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
--                         (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
--                         5, 1000);
--
--      pm_runtime_put(prg->dev);
--
--      chan->enabled = true;
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
--
--bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
--{
--      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
--      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
--      struct ipu_prg_channel *chan;
--
--      if (prg_chan < 0)
--              return false;
--
--      chan = &prg->chan[prg_chan];
--      WARN_ON(!chan->enabled);
--
--      return ipu_pre_update_pending(prg->pres[chan->used_pre]);
--}
--EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
--
--static int ipu_prg_probe(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      struct resource *res;
--      struct ipu_prg *prg;
--      u32 val;
--      int i, ret;
--
--      prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
--      if (!prg)
--              return -ENOMEM;
--
--      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--      prg->regs = devm_ioremap_resource(&pdev->dev, res);
--      if (IS_ERR(prg->regs))
--              return PTR_ERR(prg->regs);
--
--
--      prg->clk_ipg = devm_clk_get(dev, "ipg");
--      if (IS_ERR(prg->clk_ipg))
--              return PTR_ERR(prg->clk_ipg);
--
--      prg->clk_axi = devm_clk_get(dev, "axi");
--      if (IS_ERR(prg->clk_axi))
--              return PTR_ERR(prg->clk_axi);
--
--      prg->iomuxc_gpr =
--              syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
--      if (IS_ERR(prg->iomuxc_gpr))
--              return PTR_ERR(prg->iomuxc_gpr);
--
--      for (i = 0; i < 3; i++) {
--              prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
--              if (!prg->pres[i])
--                      return -EPROBE_DEFER;
--      }
--
--      ret = clk_prepare_enable(prg->clk_ipg);
--      if (ret)
--              return ret;
--
--      ret = clk_prepare_enable(prg->clk_axi);
--      if (ret) {
--              clk_disable_unprepare(prg->clk_ipg);
--              return ret;
--      }
--
--      /* init to free running mode */
--      val = readl(prg->regs + IPU_PRG_CTL);
--      val |= IPU_PRG_CTL_SHADOW_EN;
--      writel(val, prg->regs + IPU_PRG_CTL);
--
--      /* disable address threshold */
--      writel(0xffffffff, prg->regs + IPU_PRG_THD);
--
--      pm_runtime_set_active(dev);
--      pm_runtime_enable(dev);
--
--      prg->dev = dev;
--      platform_set_drvdata(pdev, prg);
--      mutex_lock(&ipu_prg_list_mutex);
--      list_add(&prg->list, &ipu_prg_list);
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      return 0;
--}
--
--static int ipu_prg_remove(struct platform_device *pdev)
--{
--      struct ipu_prg *prg = platform_get_drvdata(pdev);
--
--      mutex_lock(&ipu_prg_list_mutex);
--      list_del(&prg->list);
--      mutex_unlock(&ipu_prg_list_mutex);
--
--      return 0;
--}
--
--#ifdef CONFIG_PM
--static int prg_suspend(struct device *dev)
--{
--      struct ipu_prg *prg = dev_get_drvdata(dev);
--
--      clk_disable_unprepare(prg->clk_axi);
--      clk_disable_unprepare(prg->clk_ipg);
--
--      return 0;
--}
--
--static int prg_resume(struct device *dev)
--{
--      struct ipu_prg *prg = dev_get_drvdata(dev);
--      int ret;
--
--      ret = clk_prepare_enable(prg->clk_ipg);
--      if (ret)
--              return ret;
--
--      ret = clk_prepare_enable(prg->clk_axi);
--      if (ret) {
--              clk_disable_unprepare(prg->clk_ipg);
--              return ret;
--      }
--
--      return 0;
--}
--#endif
--
--static const struct dev_pm_ops prg_pm_ops = {
--      SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
--};
--
--static const struct of_device_id ipu_prg_dt_ids[] = {
--      { .compatible = "fsl,imx6qp-prg", },
--      { /* sentinel */ },
--};
--
--struct platform_driver ipu_prg_drv = {
--      .probe          = ipu_prg_probe,
--      .remove         = ipu_prg_remove,
--      .driver         = {
--              .name   = "imx-ipu-prg",
--              .pm     = &prg_pm_ops,
--              .of_match_table = ipu_prg_dt_ids,
--      },
--};
---- a/drivers/gpu/imx/ipu-v3/ipu-prv.h
-+++ /dev/null
-@@ -1,274 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0-or-later */
--/*
-- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#ifndef __IPU_PRV_H__
--#define __IPU_PRV_H__
--
--struct ipu_soc;
--
--#include <linux/types.h>
--#include <linux/device.h>
--#include <linux/clk.h>
--#include <linux/platform_device.h>
--
--#include <video/imx-ipu-v3.h>
--
--#define IPU_MCU_T_DEFAULT     8
--#define IPU_CM_IDMAC_REG_OFS  0x00008000
--#define IPU_CM_IC_REG_OFS     0x00020000
--#define IPU_CM_IRT_REG_OFS    0x00028000
--#define IPU_CM_CSI0_REG_OFS   0x00030000
--#define IPU_CM_CSI1_REG_OFS   0x00038000
--#define IPU_CM_SMFC_REG_OFS   0x00050000
--#define IPU_CM_DC_REG_OFS     0x00058000
--#define IPU_CM_DMFC_REG_OFS   0x00060000
--
--/* Register addresses */
--/* IPU Common registers */
--#define IPU_CM_REG(offset)    (offset)
--
--#define IPU_CONF                      IPU_CM_REG(0)
--
--#define IPU_SRM_PRI1                  IPU_CM_REG(0x00a0)
--#define IPU_SRM_PRI2                  IPU_CM_REG(0x00a4)
--#define IPU_FS_PROC_FLOW1             IPU_CM_REG(0x00a8)
--#define IPU_FS_PROC_FLOW2             IPU_CM_REG(0x00ac)
--#define IPU_FS_PROC_FLOW3             IPU_CM_REG(0x00b0)
--#define IPU_FS_DISP_FLOW1             IPU_CM_REG(0x00b4)
--#define IPU_FS_DISP_FLOW2             IPU_CM_REG(0x00b8)
--#define IPU_SKIP                      IPU_CM_REG(0x00bc)
--#define IPU_DISP_ALT_CONF             IPU_CM_REG(0x00c0)
--#define IPU_DISP_GEN                  IPU_CM_REG(0x00c4)
--#define IPU_DISP_ALT1                 IPU_CM_REG(0x00c8)
--#define IPU_DISP_ALT2                 IPU_CM_REG(0x00cc)
--#define IPU_DISP_ALT3                 IPU_CM_REG(0x00d0)
--#define IPU_DISP_ALT4                 IPU_CM_REG(0x00d4)
--#define IPU_SNOOP                     IPU_CM_REG(0x00d8)
--#define IPU_MEM_RST                   IPU_CM_REG(0x00dc)
--#define IPU_PM                                IPU_CM_REG(0x00e0)
--#define IPU_GPR                               IPU_CM_REG(0x00e4)
--#define IPU_CHA_DB_MODE_SEL(ch)               IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_DB_MODE_SEL(ch)   IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
--#define IPU_CHA_CUR_BUF(ch)           IPU_CM_REG(0x023C + 4 * ((ch) / 32))
--#define IPU_ALT_CUR_BUF0              IPU_CM_REG(0x0244)
--#define IPU_ALT_CUR_BUF1              IPU_CM_REG(0x0248)
--#define IPU_SRM_STAT                  IPU_CM_REG(0x024C)
--#define IPU_PROC_TASK_STAT            IPU_CM_REG(0x0250)
--#define IPU_DISP_TASK_STAT            IPU_CM_REG(0x0254)
--#define IPU_CHA_BUF0_RDY(ch)          IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
--#define IPU_CHA_BUF1_RDY(ch)          IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
--#define IPU_CHA_BUF2_RDY(ch)          IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_BUF0_RDY(ch)      IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
--#define IPU_ALT_CHA_BUF1_RDY(ch)      IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
--
--#define IPU_INT_CTRL(n)               IPU_CM_REG(0x003C + 4 * (n))
--#define IPU_INT_STAT(n)               IPU_CM_REG(0x0200 + 4 * (n))
--
--/* SRM_PRI2 */
--#define DP_S_SRM_MODE_MASK            (0x3 << 3)
--#define DP_S_SRM_MODE_NOW             (0x3 << 3)
--#define DP_S_SRM_MODE_NEXT_FRAME      (0x1 << 3)
--
--/* FS_PROC_FLOW1 */
--#define FS_PRPENC_ROT_SRC_SEL_MASK    (0xf << 0)
--#define FS_PRPENC_ROT_SRC_SEL_ENC             (0x7 << 0)
--#define FS_PRPVF_ROT_SRC_SEL_MASK     (0xf << 8)
--#define FS_PRPVF_ROT_SRC_SEL_VF                       (0x8 << 8)
--#define FS_PP_SRC_SEL_MASK            (0xf << 12)
--#define FS_PP_ROT_SRC_SEL_MASK                (0xf << 16)
--#define FS_PP_ROT_SRC_SEL_PP                  (0x5 << 16)
--#define FS_VDI1_SRC_SEL_MASK          (0x3 << 20)
--#define FS_VDI3_SRC_SEL_MASK          (0x3 << 20)
--#define FS_PRP_SRC_SEL_MASK           (0xf << 24)
--#define FS_VDI_SRC_SEL_MASK           (0x3 << 28)
--#define FS_VDI_SRC_SEL_CSI_DIRECT             (0x1 << 28)
--#define FS_VDI_SRC_SEL_VDOA                   (0x2 << 28)
--
--/* FS_PROC_FLOW2 */
--#define FS_PRP_ENC_DEST_SEL_MASK      (0xf << 0)
--#define FS_PRP_ENC_DEST_SEL_IRT_ENC           (0x1 << 0)
--#define FS_PRPVF_DEST_SEL_MASK                (0xf << 4)
--#define FS_PRPVF_DEST_SEL_IRT_VF              (0x1 << 4)
--#define FS_PRPVF_ROT_DEST_SEL_MASK    (0xf << 8)
--#define FS_PP_DEST_SEL_MASK           (0xf << 12)
--#define FS_PP_DEST_SEL_IRT_PP                 (0x3 << 12)
--#define FS_PP_ROT_DEST_SEL_MASK               (0xf << 16)
--#define FS_PRPENC_ROT_DEST_SEL_MASK   (0xf << 20)
--#define FS_PRP_DEST_SEL_MASK          (0xf << 24)
--
--#define IPU_DI0_COUNTER_RELEASE                       (1 << 24)
--#define IPU_DI1_COUNTER_RELEASE                       (1 << 25)
--
--#define IPU_IDMAC_REG(offset) (offset)
--
--#define IDMAC_CONF                    IPU_IDMAC_REG(0x0000)
--#define IDMAC_CHA_EN(ch)              IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
--#define IDMAC_SEP_ALPHA                       IPU_IDMAC_REG(0x000c)
--#define IDMAC_ALT_SEP_ALPHA           IPU_IDMAC_REG(0x0010)
--#define IDMAC_CHA_PRI(ch)             IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
--#define IDMAC_WM_EN(ch)                       IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
--#define IDMAC_CH_LOCK_EN_1            IPU_IDMAC_REG(0x0024)
--#define IDMAC_CH_LOCK_EN_2            IPU_IDMAC_REG(0x0028)
--#define IDMAC_SUB_ADDR_0              IPU_IDMAC_REG(0x002c)
--#define IDMAC_SUB_ADDR_1              IPU_IDMAC_REG(0x0030)
--#define IDMAC_SUB_ADDR_2              IPU_IDMAC_REG(0x0034)
--#define IDMAC_BAND_EN(ch)             IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
--#define IDMAC_CHA_BUSY(ch)            IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
--
--#define IPU_NUM_IRQS  (32 * 15)
--
--enum ipu_modules {
--      IPU_CONF_CSI0_EN                = (1 << 0),
--      IPU_CONF_CSI1_EN                = (1 << 1),
--      IPU_CONF_IC_EN                  = (1 << 2),
--      IPU_CONF_ROT_EN                 = (1 << 3),
--      IPU_CONF_ISP_EN                 = (1 << 4),
--      IPU_CONF_DP_EN                  = (1 << 5),
--      IPU_CONF_DI0_EN                 = (1 << 6),
--      IPU_CONF_DI1_EN                 = (1 << 7),
--      IPU_CONF_SMFC_EN                = (1 << 8),
--      IPU_CONF_DC_EN                  = (1 << 9),
--      IPU_CONF_DMFC_EN                = (1 << 10),
--
--      IPU_CONF_VDI_EN                 = (1 << 12),
--
--      IPU_CONF_IDMAC_DIS              = (1 << 22),
--
--      IPU_CONF_IC_DMFC_SEL            = (1 << 25),
--      IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
--      IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
--
--      IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
--      IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
--      IPU_CONF_IC_INPUT               = (1 << 30),
--      IPU_CONF_CSI_SEL                = (1 << 31),
--};
--
--struct ipuv3_channel {
--      unsigned int num;
--      struct ipu_soc *ipu;
--      struct list_head list;
--};
--
--struct ipu_cpmem;
--struct ipu_csi;
--struct ipu_dc_priv;
--struct ipu_dmfc_priv;
--struct ipu_di;
--struct ipu_ic_priv;
--struct ipu_vdi;
--struct ipu_image_convert_priv;
--struct ipu_smfc_priv;
--struct ipu_pre;
--struct ipu_prg;
--
--struct ipu_devtype;
--
--struct ipu_soc {
--      struct device           *dev;
--      const struct ipu_devtype        *devtype;
--      enum ipuv3_type         ipu_type;
--      spinlock_t              lock;
--      struct mutex            channel_lock;
--      struct list_head        channels;
--
--      void __iomem            *cm_reg;
--      void __iomem            *idmac_reg;
--
--      int                     id;
--      int                     usecount;
--
--      struct clk              *clk;
--
--      int                     irq_sync;
--      int                     irq_err;
--      struct irq_domain       *domain;
--
--      struct ipu_cpmem        *cpmem_priv;
--      struct ipu_dc_priv      *dc_priv;
--      struct ipu_dp_priv      *dp_priv;
--      struct ipu_dmfc_priv    *dmfc_priv;
--      struct ipu_di           *di_priv[2];
--      struct ipu_csi          *csi_priv[2];
--      struct ipu_ic_priv      *ic_priv;
--      struct ipu_vdi          *vdi_priv;
--      struct ipu_image_convert_priv *image_convert_priv;
--      struct ipu_smfc_priv    *smfc_priv;
--      struct ipu_prg          *prg_priv;
--};
--
--static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
--{
--      return readl(ipu->idmac_reg + offset);
--}
--
--static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
--                                 unsigned offset)
--{
--      writel(value, ipu->idmac_reg + offset);
--}
--
--void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
--
--int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
--int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
--
--bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
--
--int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
--               unsigned long base, u32 module, struct clk *clk_ipu);
--void ipu_csi_exit(struct ipu_soc *ipu, int id);
--
--int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
--              unsigned long base, unsigned long tpmem_base);
--void ipu_ic_exit(struct ipu_soc *ipu);
--
--int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
--               unsigned long base, u32 module);
--void ipu_vdi_exit(struct ipu_soc *ipu);
--
--int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
--void ipu_image_convert_exit(struct ipu_soc *ipu);
--
--int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
--              unsigned long base, u32 module, struct clk *ipu_clk);
--void ipu_di_exit(struct ipu_soc *ipu, int id);
--
--int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              struct clk *ipu_clk);
--void ipu_dmfc_exit(struct ipu_soc *ipu);
--
--int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_dp_exit(struct ipu_soc *ipu);
--
--int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
--              unsigned long template_base);
--void ipu_dc_exit(struct ipu_soc *ipu);
--
--int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_cpmem_exit(struct ipu_soc *ipu);
--
--int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
--void ipu_smfc_exit(struct ipu_soc *ipu);
--
--struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
--                                        int index);
--int ipu_pre_get_available_count(void);
--int ipu_pre_get(struct ipu_pre *pre);
--void ipu_pre_put(struct ipu_pre *pre);
--u32 ipu_pre_get_baddr(struct ipu_pre *pre);
--void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
--                     unsigned int height, unsigned int stride, u32 format,
--                     uint64_t modifier, unsigned int bufaddr);
--void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
--bool ipu_pre_update_pending(struct ipu_pre *pre);
--
--struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
--                                        int ipu_id);
--
--extern struct platform_driver ipu_pre_drv;
--extern struct platform_driver ipu_prg_drv;
--
--#endif                                /* __IPU_PRV_H__ */
---- a/drivers/gpu/imx/ipu-v3/ipu-smfc.c
-+++ /dev/null
-@@ -1,202 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-- */
--#include <linux/export.h>
--#include <linux/types.h>
--#include <linux/init.h>
--#include <linux/io.h>
--#include <linux/errno.h>
--#include <linux/spinlock.h>
--#include <linux/delay.h>
--#include <linux/clk.h>
--#include <video/imx-ipu-v3.h>
--
--#include "ipu-prv.h"
--
--struct ipu_smfc {
--      struct ipu_smfc_priv *priv;
--      int chno;
--      bool inuse;
--};
--
--struct ipu_smfc_priv {
--      void __iomem *base;
--      spinlock_t lock;
--      struct ipu_soc *ipu;
--      struct ipu_smfc channel[4];
--      int use_count;
--};
--
--/*SMFC Registers */
--#define SMFC_MAP      0x0000
--#define SMFC_WMC      0x0004
--#define SMFC_BS               0x0008
--
--int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 4;
--      val = readl(priv->base + SMFC_BS);
--      val &= ~(0xf << shift);
--      val |= burstsize << shift;
--      writel(val, priv->base + SMFC_BS);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
--
--int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 3;
--      val = readl(priv->base + SMFC_MAP);
--      val &= ~(0x7 << shift);
--      val |= ((csi_id << 2) | mipi_id) << shift;
--      writel(val, priv->base + SMFC_MAP);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
--
--int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--      u32 val, shift;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
--      val = readl(priv->base + SMFC_WMC);
--      val &= ~(0x3f << shift);
--      val |= ((clr_level << 3) | set_level) << shift;
--      writel(val, priv->base + SMFC_WMC);
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
--
--int ipu_smfc_enable(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (!priv->use_count)
--              ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
--
--      priv->use_count++;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_enable);
--
--int ipu_smfc_disable(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      priv->use_count--;
--
--      if (!priv->use_count)
--              ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
--
--      if (priv->use_count < 0)
--              priv->use_count = 0;
--
--      spin_unlock_irqrestore(&priv->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_disable);
--
--struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
--{
--      struct ipu_smfc_priv *priv = ipu->smfc_priv;
--      struct ipu_smfc *smfc, *ret;
--      unsigned long flags;
--
--      if (chno >= 4)
--              return ERR_PTR(-EINVAL);
--
--      smfc = &priv->channel[chno];
--      ret = smfc;
--
--      spin_lock_irqsave(&priv->lock, flags);
--
--      if (smfc->inuse) {
--              ret = ERR_PTR(-EBUSY);
--              goto unlock;
--      }
--
--      smfc->inuse = true;
--unlock:
--      spin_unlock_irqrestore(&priv->lock, flags);
--      return ret;
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_get);
--
--void ipu_smfc_put(struct ipu_smfc *smfc)
--{
--      struct ipu_smfc_priv *priv = smfc->priv;
--      unsigned long flags;
--
--      spin_lock_irqsave(&priv->lock, flags);
--      smfc->inuse = false;
--      spin_unlock_irqrestore(&priv->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_smfc_put);
--
--int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
--                unsigned long base)
--{
--      struct ipu_smfc_priv *priv;
--      int i;
--
--      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ipu->smfc_priv = priv;
--      spin_lock_init(&priv->lock);
--      priv->ipu = ipu;
--
--      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!priv->base)
--              return -ENOMEM;
--
--      for (i = 0; i < 4; i++) {
--              priv->channel[i].priv = priv;
--              priv->channel[i].chno = i;
--      }
--
--      pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
--
--      return 0;
--}
--
--void ipu_smfc_exit(struct ipu_soc *ipu)
--{
--}
---- a/drivers/gpu/imx/ipu-v3/ipu-vdi.c
-+++ /dev/null
-@@ -1,234 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0-or-later
--/*
-- * Copyright (C) 2012-2016 Mentor Graphics Inc.
-- * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-- */
--#include <linux/io.h>
--#include "ipu-prv.h"
--
--struct ipu_vdi {
--      void __iomem *base;
--      u32 module;
--      spinlock_t lock;
--      int use_count;
--      struct ipu_soc *ipu;
--};
--
--
--/* VDI Register Offsets */
--#define VDI_FSIZE 0x0000
--#define VDI_C     0x0004
--
--/* VDI Register Fields */
--#define VDI_C_CH_420             (0 << 1)
--#define VDI_C_CH_422             (1 << 1)
--#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
--#define VDI_C_MOT_SEL_FULL       (2 << 2)
--#define VDI_C_MOT_SEL_LOW        (1 << 2)
--#define VDI_C_MOT_SEL_MED        (0 << 2)
--#define VDI_C_BURST_SIZE1_4      (3 << 4)
--#define VDI_C_BURST_SIZE2_4      (3 << 8)
--#define VDI_C_BURST_SIZE3_4      (3 << 12)
--#define VDI_C_BURST_SIZE_MASK    0xF
--#define VDI_C_BURST_SIZE1_OFFSET 4
--#define VDI_C_BURST_SIZE2_OFFSET 8
--#define VDI_C_BURST_SIZE3_OFFSET 12
--#define VDI_C_VWM1_SET_1         (0 << 16)
--#define VDI_C_VWM1_SET_2         (1 << 16)
--#define VDI_C_VWM1_CLR_2         (1 << 19)
--#define VDI_C_VWM3_SET_1         (0 << 22)
--#define VDI_C_VWM3_SET_2         (1 << 22)
--#define VDI_C_VWM3_CLR_2         (1 << 25)
--#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
--#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
--
--static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
--{
--      return readl(vdi->base + offset);
--}
--
--static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
--                               unsigned int offset)
--{
--      writel(value, vdi->base + offset);
--}
--
--void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
--{
--      bool top_field_0 = false;
--      unsigned long flags;
--      u32 reg;
--
--      switch (field) {
--      case V4L2_FIELD_INTERLACED_TB:
--      case V4L2_FIELD_SEQ_TB:
--      case V4L2_FIELD_TOP:
--              top_field_0 = true;
--              break;
--      case V4L2_FIELD_INTERLACED_BT:
--      case V4L2_FIELD_SEQ_BT:
--      case V4L2_FIELD_BOTTOM:
--              top_field_0 = false;
--              break;
--      default:
--              top_field_0 = (std & V4L2_STD_525_60) ? true : false;
--              break;
--      }
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--      if (top_field_0)
--              reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
--      else
--              reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
--
--void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
--{
--      unsigned long flags;
--      u32 reg;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--
--      reg &= ~VDI_C_MOT_SEL_MASK;
--
--      switch (motion_sel) {
--      case MED_MOTION:
--              reg |= VDI_C_MOT_SEL_MED;
--              break;
--      case HIGH_MOTION:
--              reg |= VDI_C_MOT_SEL_FULL;
--              break;
--      default:
--              reg |= VDI_C_MOT_SEL_LOW;
--              break;
--      }
--
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
--
--void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
--{
--      unsigned long flags;
--      u32 pixel_fmt, reg;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      reg = ((yres - 1) << 16) | (xres - 1);
--      ipu_vdi_write(vdi, reg, VDI_FSIZE);
--
--      /*
--       * Full motion, only vertical filter is used.
--       * Burst size is 4 accesses
--       */
--      if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
--          code == MEDIA_BUS_FMT_UYVY8_1X16 ||
--          code == MEDIA_BUS_FMT_YUYV8_2X8 ||
--          code == MEDIA_BUS_FMT_YUYV8_1X16)
--              pixel_fmt = VDI_C_CH_422;
--      else
--              pixel_fmt = VDI_C_CH_420;
--
--      reg = ipu_vdi_read(vdi, VDI_C);
--      reg |= pixel_fmt;
--      reg |= VDI_C_BURST_SIZE2_4;
--      reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
--      reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
--      ipu_vdi_write(vdi, reg, VDI_C);
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_setup);
--
--void ipu_vdi_unsetup(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--      ipu_vdi_write(vdi, 0, VDI_FSIZE);
--      ipu_vdi_write(vdi, 0, VDI_C);
--      spin_unlock_irqrestore(&vdi->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
--
--int ipu_vdi_enable(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      if (!vdi->use_count)
--              ipu_module_enable(vdi->ipu, vdi->module);
--
--      vdi->use_count++;
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_enable);
--
--int ipu_vdi_disable(struct ipu_vdi *vdi)
--{
--      unsigned long flags;
--
--      spin_lock_irqsave(&vdi->lock, flags);
--
--      if (vdi->use_count) {
--              if (!--vdi->use_count)
--                      ipu_module_disable(vdi->ipu, vdi->module);
--      }
--
--      spin_unlock_irqrestore(&vdi->lock, flags);
--
--      return 0;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_disable);
--
--struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
--{
--      return ipu->vdi_priv;
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_get);
--
--void ipu_vdi_put(struct ipu_vdi *vdi)
--{
--}
--EXPORT_SYMBOL_GPL(ipu_vdi_put);
--
--int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
--               unsigned long base, u32 module)
--{
--      struct ipu_vdi *vdi;
--
--      vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
--      if (!vdi)
--              return -ENOMEM;
--
--      ipu->vdi_priv = vdi;
--
--      spin_lock_init(&vdi->lock);
--      vdi->module = module;
--      vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
--      if (!vdi->base)
--              return -ENOMEM;
--
--      dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
--      vdi->ipu = ipu;
--
--      return 0;
--}
--
--void ipu_vdi_exit(struct ipu_soc *ipu)
--{
--}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/Kconfig
-@@ -0,0 +1,11 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+config IMX_IPUV3_CORE
-+      tristate "IPUv3 core support"
-+      depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM || COMPILE_TEST
-+      depends on DRM || !DRM # if DRM=m, this can't be 'y'
-+      select BITREVERSE
-+      select GENERIC_ALLOCATOR if DRM
-+      select GENERIC_IRQ_CHIP
-+      help
-+        Choose this if you have a i.MX5/6 system and want to use the Image
-+        Processing Unit. This option only enables IPU base support.
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/Makefile
-@@ -0,0 +1,10 @@
-+# SPDX-License-Identifier: GPL-2.0
-+obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
-+
-+imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
-+              ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
-+              ipu-image-convert.o ipu-smfc.o ipu-vdi.o
-+
-+ifdef CONFIG_DRM
-+      imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
-+endif
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-common.c
-@@ -0,0 +1,1565 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/module.h>
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/reset.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/clk.h>
-+#include <linux/list.h>
-+#include <linux/irq.h>
-+#include <linux/irqchip/chained_irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/of_device.h>
-+#include <linux/of_graph.h>
-+
-+#include <drm/drm_fourcc.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
-+{
-+      return readl(ipu->cm_reg + offset);
-+}
-+
-+static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
-+{
-+      writel(value, ipu->cm_reg + offset);
-+}
-+
-+int ipu_get_num(struct ipu_soc *ipu)
-+{
-+      return ipu->id;
-+}
-+EXPORT_SYMBOL_GPL(ipu_get_num);
-+
-+void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync)
-+{
-+      u32 val;
-+
-+      val = ipu_cm_read(ipu, IPU_SRM_PRI2);
-+      val &= ~DP_S_SRM_MODE_MASK;
-+      val |= sync ? DP_S_SRM_MODE_NEXT_FRAME :
-+                    DP_S_SRM_MODE_NOW;
-+      ipu_cm_write(ipu, val, IPU_SRM_PRI2);
-+}
-+EXPORT_SYMBOL_GPL(ipu_srm_dp_update);
-+
-+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
-+{
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_ARGB1555:
-+      case DRM_FORMAT_ABGR1555:
-+      case DRM_FORMAT_RGBA5551:
-+      case DRM_FORMAT_BGRA5551:
-+      case DRM_FORMAT_RGB565:
-+      case DRM_FORMAT_BGR565:
-+      case DRM_FORMAT_RGB888:
-+      case DRM_FORMAT_BGR888:
-+      case DRM_FORMAT_ARGB4444:
-+      case DRM_FORMAT_XRGB8888:
-+      case DRM_FORMAT_XBGR8888:
-+      case DRM_FORMAT_RGBX8888:
-+      case DRM_FORMAT_BGRX8888:
-+      case DRM_FORMAT_ARGB8888:
-+      case DRM_FORMAT_ABGR8888:
-+      case DRM_FORMAT_RGBA8888:
-+      case DRM_FORMAT_BGRA8888:
-+      case DRM_FORMAT_RGB565_A8:
-+      case DRM_FORMAT_BGR565_A8:
-+      case DRM_FORMAT_RGB888_A8:
-+      case DRM_FORMAT_BGR888_A8:
-+      case DRM_FORMAT_RGBX8888_A8:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              return IPUV3_COLORSPACE_RGB;
-+      case DRM_FORMAT_YUYV:
-+      case DRM_FORMAT_UYVY:
-+      case DRM_FORMAT_YUV420:
-+      case DRM_FORMAT_YVU420:
-+      case DRM_FORMAT_YUV422:
-+      case DRM_FORMAT_YVU422:
-+      case DRM_FORMAT_YUV444:
-+      case DRM_FORMAT_YVU444:
-+      case DRM_FORMAT_NV12:
-+      case DRM_FORMAT_NV21:
-+      case DRM_FORMAT_NV16:
-+      case DRM_FORMAT_NV61:
-+              return IPUV3_COLORSPACE_YUV;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
-+
-+enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_UYVY:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              return IPUV3_COLORSPACE_YUV;
-+      case V4L2_PIX_FMT_RGB565:
-+      case V4L2_PIX_FMT_BGR24:
-+      case V4L2_PIX_FMT_RGB24:
-+      case V4L2_PIX_FMT_ABGR32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_BGRA32:
-+      case V4L2_PIX_FMT_BGRX32:
-+      case V4L2_PIX_FMT_RGBA32:
-+      case V4L2_PIX_FMT_RGBX32:
-+      case V4L2_PIX_FMT_ARGB32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              return IPUV3_COLORSPACE_RGB;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_pixelformat_to_colorspace);
-+
-+bool ipu_pixelformat_is_planar(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              return true;
-+      }
-+
-+      return false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);
-+
-+enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
-+{
-+      switch (mbus_code & 0xf000) {
-+      case 0x1000:
-+              return IPUV3_COLORSPACE_RGB;
-+      case 0x2000:
-+              return IPUV3_COLORSPACE_YUV;
-+      default:
-+              return IPUV3_COLORSPACE_UNKNOWN;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_mbus_code_to_colorspace);
-+
-+int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+      case V4L2_PIX_FMT_YUV422P:
-+      case V4L2_PIX_FMT_NV12:
-+      case V4L2_PIX_FMT_NV21:
-+      case V4L2_PIX_FMT_NV16:
-+      case V4L2_PIX_FMT_NV61:
-+              /*
-+               * for the planar YUV formats, the stride passed to
-+               * cpmem must be the stride in bytes of the Y plane.
-+               * And all the planar YUV formats have an 8-bit
-+               * Y component.
-+               */
-+              return (8 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_RGB565:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_UYVY:
-+              return (16 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_BGR24:
-+      case V4L2_PIX_FMT_RGB24:
-+              return (24 * pixel_stride) >> 3;
-+      case V4L2_PIX_FMT_BGR32:
-+      case V4L2_PIX_FMT_RGB32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              return (32 * pixel_stride) >> 3;
-+      default:
-+              break;
-+      }
-+
-+      return -EINVAL;
-+}
-+EXPORT_SYMBOL_GPL(ipu_stride_to_bytes);
-+
-+int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
-+                          bool hflip, bool vflip)
-+{
-+      u32 r90, vf, hf;
-+
-+      switch (degrees) {
-+      case 0:
-+              vf = hf = r90 = 0;
-+              break;
-+      case 90:
-+              vf = hf = 0;
-+              r90 = 1;
-+              break;
-+      case 180:
-+              vf = hf = 1;
-+              r90 = 0;
-+              break;
-+      case 270:
-+              vf = hf = r90 = 1;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      hf ^= (u32)hflip;
-+      vf ^= (u32)vflip;
-+
-+      *mode = (enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_degrees_to_rot_mode);
-+
-+int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
-+                          bool hflip, bool vflip)
-+{
-+      u32 r90, vf, hf;
-+
-+      r90 = ((u32)mode >> 2) & 0x1;
-+      hf = ((u32)mode >> 1) & 0x1;
-+      vf = ((u32)mode >> 0) & 0x1;
-+      hf ^= (u32)hflip;
-+      vf ^= (u32)vflip;
-+
-+      switch ((enum ipu_rotate_mode)((r90 << 2) | (hf << 1) | vf)) {
-+      case IPU_ROTATE_NONE:
-+              *degrees = 0;
-+              break;
-+      case IPU_ROTATE_90_RIGHT:
-+              *degrees = 90;
-+              break;
-+      case IPU_ROTATE_180:
-+              *degrees = 180;
-+              break;
-+      case IPU_ROTATE_90_LEFT:
-+              *degrees = 270;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_rot_mode_to_degrees);
-+
-+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
-+{
-+      struct ipuv3_channel *channel;
-+
-+      dev_dbg(ipu->dev, "%s %d\n", __func__, num);
-+
-+      if (num > 63)
-+              return ERR_PTR(-ENODEV);
-+
-+      mutex_lock(&ipu->channel_lock);
-+
-+      list_for_each_entry(channel, &ipu->channels, list) {
-+              if (channel->num == num) {
-+                      channel = ERR_PTR(-EBUSY);
-+                      goto out;
-+              }
-+      }
-+
-+      channel = kzalloc(sizeof(*channel), GFP_KERNEL);
-+      if (!channel) {
-+              channel = ERR_PTR(-ENOMEM);
-+              goto out;
-+      }
-+
-+      channel->num = num;
-+      channel->ipu = ipu;
-+      list_add(&channel->list, &ipu->channels);
-+
-+out:
-+      mutex_unlock(&ipu->channel_lock);
-+
-+      return channel;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_get);
-+
-+void ipu_idmac_put(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+
-+      dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
-+
-+      mutex_lock(&ipu->channel_lock);
-+
-+      list_del(&channel->list);
-+      kfree(channel);
-+
-+      mutex_unlock(&ipu->channel_lock);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_put);
-+
-+#define idma_mask(ch)                 (1 << ((ch) & 0x1f))
-+
-+/*
-+ * This is an undocumented feature, a write one to a channel bit in
-+ * IPU_CHA_CUR_BUF and IPU_CHA_TRIPLE_CUR_BUF will reset the channel's
-+ * internal current buffer pointer so that transfers start from buffer
-+ * 0 on the next channel enable (that's the theory anyway, the imx6 TRM
-+ * only says these are read-only registers). This operation is required
-+ * for channel linking to work correctly, for instance video capture
-+ * pipelines that carry out image rotations will fail after the first
-+ * streaming unless this function is called for each channel before
-+ * re-enabling the channels.
-+ */
-+static void __ipu_idmac_reset_current_buffer(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+
-+      ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_CUR_BUF(chno));
-+}
-+
-+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
-+              bool doublebuffer)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-+      if (doublebuffer)
-+              reg |= idma_mask(channel->num);
-+      else
-+              reg &= ~idma_mask(channel->num);
-+      ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
-+
-+      __ipu_idmac_reset_current_buffer(channel);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
-+
-+static const struct {
-+      int chnum;
-+      u32 reg;
-+      int shift;
-+} idmac_lock_en_info[] = {
-+      { .chnum =  5, .reg = IDMAC_CH_LOCK_EN_1, .shift =  0, },
-+      { .chnum = 11, .reg = IDMAC_CH_LOCK_EN_1, .shift =  2, },
-+      { .chnum = 12, .reg = IDMAC_CH_LOCK_EN_1, .shift =  4, },
-+      { .chnum = 14, .reg = IDMAC_CH_LOCK_EN_1, .shift =  6, },
-+      { .chnum = 15, .reg = IDMAC_CH_LOCK_EN_1, .shift =  8, },
-+      { .chnum = 20, .reg = IDMAC_CH_LOCK_EN_1, .shift = 10, },
-+      { .chnum = 21, .reg = IDMAC_CH_LOCK_EN_1, .shift = 12, },
-+      { .chnum = 22, .reg = IDMAC_CH_LOCK_EN_1, .shift = 14, },
-+      { .chnum = 23, .reg = IDMAC_CH_LOCK_EN_1, .shift = 16, },
-+      { .chnum = 27, .reg = IDMAC_CH_LOCK_EN_1, .shift = 18, },
-+      { .chnum = 28, .reg = IDMAC_CH_LOCK_EN_1, .shift = 20, },
-+      { .chnum = 45, .reg = IDMAC_CH_LOCK_EN_2, .shift =  0, },
-+      { .chnum = 46, .reg = IDMAC_CH_LOCK_EN_2, .shift =  2, },
-+      { .chnum = 47, .reg = IDMAC_CH_LOCK_EN_2, .shift =  4, },
-+      { .chnum = 48, .reg = IDMAC_CH_LOCK_EN_2, .shift =  6, },
-+      { .chnum = 49, .reg = IDMAC_CH_LOCK_EN_2, .shift =  8, },
-+      { .chnum = 50, .reg = IDMAC_CH_LOCK_EN_2, .shift = 10, },
-+};
-+
-+int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 bursts, regval;
-+      int i;
-+
-+      switch (num_bursts) {
-+      case 0:
-+      case 1:
-+              bursts = 0x00; /* locking disabled */
-+              break;
-+      case 2:
-+              bursts = 0x01;
-+              break;
-+      case 4:
-+              bursts = 0x02;
-+              break;
-+      case 8:
-+              bursts = 0x03;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      /*
-+       * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M /
-+       * i.MX53 channel arbitration locking doesn't seem to work properly.
-+       * Allow enabling the lock feature on IPUv3H / i.MX6 only.
-+       */
-+      if (bursts && ipu->ipu_type != IPUV3H)
-+              return -EINVAL;
-+
-+      for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) {
-+              if (channel->num == idmac_lock_en_info[i].chnum)
-+                      break;
-+      }
-+      if (i >= ARRAY_SIZE(idmac_lock_en_info))
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      regval = ipu_idmac_read(ipu, idmac_lock_en_info[i].reg);
-+      regval &= ~(0x03 << idmac_lock_en_info[i].shift);
-+      regval |= (bursts << idmac_lock_en_info[i].shift);
-+      ipu_idmac_write(ipu, regval, idmac_lock_en_info[i].reg);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_lock_enable);
-+
-+int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
-+{
-+      unsigned long lock_flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, lock_flags);
-+
-+      val = ipu_cm_read(ipu, IPU_DISP_GEN);
-+
-+      if (mask & IPU_CONF_DI0_EN)
-+              val |= IPU_DI0_COUNTER_RELEASE;
-+      if (mask & IPU_CONF_DI1_EN)
-+              val |= IPU_DI1_COUNTER_RELEASE;
-+
-+      ipu_cm_write(ipu, val, IPU_DISP_GEN);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      val |= mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, lock_flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_module_enable);
-+
-+int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
-+{
-+      unsigned long lock_flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, lock_flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      val &= ~mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      val = ipu_cm_read(ipu, IPU_DISP_GEN);
-+
-+      if (mask & IPU_CONF_DI0_EN)
-+              val &= ~IPU_DI0_COUNTER_RELEASE;
-+      if (mask & IPU_CONF_DI1_EN)
-+              val &= ~IPU_DI1_COUNTER_RELEASE;
-+
-+      ipu_cm_write(ipu, val, IPU_DISP_GEN);
-+
-+      spin_unlock_irqrestore(&ipu->lock, lock_flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_module_disable);
-+
-+int ipu_idmac_get_current_buffer(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+
-+      return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 : 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);
-+
-+bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 reg = 0;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+      switch (buf_num) {
-+      case 0:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num));
-+              break;
-+      case 1:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num));
-+              break;
-+      case 2:
-+              reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(channel->num));
-+              break;
-+      }
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return ((reg & idma_mask(channel->num)) != 0);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_buffer_is_ready);
-+
-+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      /* Mark buffer as ready. */
-+      if (buf_num == 0)
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
-+      else
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
-+
-+void ipu_idmac_clear_buffer(struct ipuv3_channel *channel, u32 buf_num)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned int chno = channel->num;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
-+      switch (buf_num) {
-+      case 0:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
-+              break;
-+      case 1:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
-+              break;
-+      case 2:
-+              ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF2_RDY(chno));
-+              break;
-+      default:
-+              break;
-+      }
-+      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_clear_buffer);
-+
-+int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      u32 val;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-+      val |= idma_mask(channel->num);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
-+
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
-+{
-+      return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
-+
-+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long timeout;
-+
-+      timeout = jiffies + msecs_to_jiffies(ms);
-+      while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              if (time_after(jiffies, timeout))
-+                      return -ETIMEDOUT;
-+              cpu_relax();
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
-+
-+int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      u32 val;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      /* Disable DMA channel(s) */
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
-+      val &= ~idma_mask(channel->num);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
-+
-+      __ipu_idmac_reset_current_buffer(channel);
-+
-+      /* Set channel buffers NOT to be ready */
-+      ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
-+
-+      if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              ipu_cm_write(ipu, idma_mask(channel->num),
-+                           IPU_CHA_BUF0_RDY(channel->num));
-+      }
-+
-+      if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
-+                      idma_mask(channel->num)) {
-+              ipu_cm_write(ipu, idma_mask(channel->num),
-+                           IPU_CHA_BUF1_RDY(channel->num));
-+      }
-+
-+      ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
-+
-+      /* Reset the double buffer */
-+      val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
-+      val &= ~idma_mask(channel->num);
-+      ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
-+
-+/*
-+ * The imx6 rev. D TRM says that enabling the WM feature will increase
-+ * a channel's priority. Refer to Table 36-8 Calculated priority value.
-+ * The sub-module that is the sink or source for the channel must enable
-+ * watermark signal for this to take effect (SMFC_WM for instance).
-+ */
-+void ipu_idmac_enable_watermark(struct ipuv3_channel *channel, bool enable)
-+{
-+      struct ipu_soc *ipu = channel->ipu;
-+      unsigned long flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_WM_EN(channel->num));
-+      if (enable)
-+              val |= 1 << (channel->num % 32);
-+      else
-+              val &= ~(1 << (channel->num % 32));
-+      ipu_idmac_write(ipu, val, IDMAC_WM_EN(channel->num));
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_enable_watermark);
-+
-+static int ipu_memory_reset(struct ipu_soc *ipu)
-+{
-+      unsigned long timeout;
-+
-+      ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
-+
-+      timeout = jiffies + msecs_to_jiffies(1000);
-+      while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
-+              if (time_after(jiffies, timeout))
-+                      return -ETIME;
-+              cpu_relax();
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Set the source mux for the given CSI. Selects either parallel or
-+ * MIPI CSI2 sources.
-+ */
-+void ipu_set_csi_src_mux(struct ipu_soc *ipu, int csi_id, bool mipi_csi2)
-+{
-+      unsigned long flags;
-+      u32 val, mask;
-+
-+      mask = (csi_id == 1) ? IPU_CONF_CSI1_DATA_SOURCE :
-+              IPU_CONF_CSI0_DATA_SOURCE;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      if (mipi_csi2)
-+              val |= mask;
-+      else
-+              val &= ~mask;
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_set_csi_src_mux);
-+
-+/*
-+ * Set the source mux for the IC. Selects either CSI[01] or the VDI.
-+ */
-+void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
-+{
-+      unsigned long flags;
-+      u32 val;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      val = ipu_cm_read(ipu, IPU_CONF);
-+      if (vdi)
-+              val |= IPU_CONF_IC_INPUT;
-+      else
-+              val &= ~IPU_CONF_IC_INPUT;
-+
-+      if (csi_id == 1)
-+              val |= IPU_CONF_CSI_SEL;
-+      else
-+              val &= ~IPU_CONF_CSI_SEL;
-+
-+      ipu_cm_write(ipu, val, IPU_CONF);
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);
-+
-+
-+/* Frame Synchronization Unit Channel Linking */
-+
-+struct fsu_link_reg_info {
-+      int chno;
-+      u32 reg;
-+      u32 mask;
-+      u32 val;
-+};
-+
-+struct fsu_link_info {
-+      struct fsu_link_reg_info src;
-+      struct fsu_link_reg_info sink;
-+};
-+
-+static const struct fsu_link_info fsu_link_info[] = {
-+      {
-+              .src  = { IPUV3_CHANNEL_IC_PRP_ENC_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PRP_ENC_DEST_SEL_MASK, FS_PRP_ENC_DEST_SEL_IRT_ENC },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_ENC, IPU_FS_PROC_FLOW1,
-+                        FS_PRPENC_ROT_SRC_SEL_MASK, FS_PRPENC_ROT_SRC_SEL_ENC },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_IC_PRP_VF_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PRPVF_DEST_SEL_MASK, FS_PRPVF_DEST_SEL_IRT_VF },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_VF, IPU_FS_PROC_FLOW1,
-+                        FS_PRPVF_ROT_SRC_SEL_MASK, FS_PRPVF_ROT_SRC_SEL_VF },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_IC_PP_MEM, IPU_FS_PROC_FLOW2,
-+                        FS_PP_DEST_SEL_MASK, FS_PP_DEST_SEL_IRT_PP },
-+              .sink = { IPUV3_CHANNEL_MEM_ROT_PP, IPU_FS_PROC_FLOW1,
-+                        FS_PP_ROT_SRC_SEL_MASK, FS_PP_ROT_SRC_SEL_PP },
-+      }, {
-+              .src =  { IPUV3_CHANNEL_CSI_DIRECT, 0 },
-+              .sink = { IPUV3_CHANNEL_CSI_VDI_PREV, IPU_FS_PROC_FLOW1,
-+                        FS_VDI_SRC_SEL_MASK, FS_VDI_SRC_SEL_CSI_DIRECT },
-+      },
-+};
-+
-+static const struct fsu_link_info *find_fsu_link_info(int src, int sink)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(fsu_link_info); i++) {
-+              if (src == fsu_link_info[i].src.chno &&
-+                  sink == fsu_link_info[i].sink.chno)
-+                      return &fsu_link_info[i];
-+      }
-+
-+      return NULL;
-+}
-+
-+/*
-+ * Links a source channel to a sink channel in the FSU.
-+ */
-+int ipu_fsu_link(struct ipu_soc *ipu, int src_ch, int sink_ch)
-+{
-+      const struct fsu_link_info *link;
-+      u32 src_reg, sink_reg;
-+      unsigned long flags;
-+
-+      link = find_fsu_link_info(src_ch, sink_ch);
-+      if (!link)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      if (link->src.mask) {
-+              src_reg = ipu_cm_read(ipu, link->src.reg);
-+              src_reg &= ~link->src.mask;
-+              src_reg |= link->src.val;
-+              ipu_cm_write(ipu, src_reg, link->src.reg);
-+      }
-+
-+      if (link->sink.mask) {
-+              sink_reg = ipu_cm_read(ipu, link->sink.reg);
-+              sink_reg &= ~link->sink.mask;
-+              sink_reg |= link->sink.val;
-+              ipu_cm_write(ipu, sink_reg, link->sink.reg);
-+      }
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_fsu_link);
-+
-+/*
-+ * Unlinks source and sink channels in the FSU.
-+ */
-+int ipu_fsu_unlink(struct ipu_soc *ipu, int src_ch, int sink_ch)
-+{
-+      const struct fsu_link_info *link;
-+      u32 src_reg, sink_reg;
-+      unsigned long flags;
-+
-+      link = find_fsu_link_info(src_ch, sink_ch);
-+      if (!link)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&ipu->lock, flags);
-+
-+      if (link->src.mask) {
-+              src_reg = ipu_cm_read(ipu, link->src.reg);
-+              src_reg &= ~link->src.mask;
-+              ipu_cm_write(ipu, src_reg, link->src.reg);
-+      }
-+
-+      if (link->sink.mask) {
-+              sink_reg = ipu_cm_read(ipu, link->sink.reg);
-+              sink_reg &= ~link->sink.mask;
-+              ipu_cm_write(ipu, sink_reg, link->sink.reg);
-+      }
-+
-+      spin_unlock_irqrestore(&ipu->lock, flags);
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_fsu_unlink);
-+
-+/* Link IDMAC channels in the FSU */
-+int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
-+{
-+      return ipu_fsu_link(src->ipu, src->num, sink->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_link);
-+
-+/* Unlink IDMAC channels in the FSU */
-+int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
-+{
-+      return ipu_fsu_unlink(src->ipu, src->num, sink->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
-+
-+struct ipu_devtype {
-+      const char *name;
-+      unsigned long cm_ofs;
-+      unsigned long cpmem_ofs;
-+      unsigned long srm_ofs;
-+      unsigned long tpm_ofs;
-+      unsigned long csi0_ofs;
-+      unsigned long csi1_ofs;
-+      unsigned long ic_ofs;
-+      unsigned long disp0_ofs;
-+      unsigned long disp1_ofs;
-+      unsigned long dc_tmpl_ofs;
-+      unsigned long vdi_ofs;
-+      enum ipuv3_type type;
-+};
-+
-+static struct ipu_devtype ipu_type_imx51 = {
-+      .name = "IPUv3EX",
-+      .cm_ofs = 0x1e000000,
-+      .cpmem_ofs = 0x1f000000,
-+      .srm_ofs = 0x1f040000,
-+      .tpm_ofs = 0x1f060000,
-+      .csi0_ofs = 0x1e030000,
-+      .csi1_ofs = 0x1e038000,
-+      .ic_ofs = 0x1e020000,
-+      .disp0_ofs = 0x1e040000,
-+      .disp1_ofs = 0x1e048000,
-+      .dc_tmpl_ofs = 0x1f080000,
-+      .vdi_ofs = 0x1e068000,
-+      .type = IPUV3EX,
-+};
-+
-+static struct ipu_devtype ipu_type_imx53 = {
-+      .name = "IPUv3M",
-+      .cm_ofs = 0x06000000,
-+      .cpmem_ofs = 0x07000000,
-+      .srm_ofs = 0x07040000,
-+      .tpm_ofs = 0x07060000,
-+      .csi0_ofs = 0x06030000,
-+      .csi1_ofs = 0x06038000,
-+      .ic_ofs = 0x06020000,
-+      .disp0_ofs = 0x06040000,
-+      .disp1_ofs = 0x06048000,
-+      .dc_tmpl_ofs = 0x07080000,
-+      .vdi_ofs = 0x06068000,
-+      .type = IPUV3M,
-+};
-+
-+static struct ipu_devtype ipu_type_imx6q = {
-+      .name = "IPUv3H",
-+      .cm_ofs = 0x00200000,
-+      .cpmem_ofs = 0x00300000,
-+      .srm_ofs = 0x00340000,
-+      .tpm_ofs = 0x00360000,
-+      .csi0_ofs = 0x00230000,
-+      .csi1_ofs = 0x00238000,
-+      .ic_ofs = 0x00220000,
-+      .disp0_ofs = 0x00240000,
-+      .disp1_ofs = 0x00248000,
-+      .dc_tmpl_ofs = 0x00380000,
-+      .vdi_ofs = 0x00268000,
-+      .type = IPUV3H,
-+};
-+
-+static const struct of_device_id imx_ipu_dt_ids[] = {
-+      { .compatible = "fsl,imx51-ipu", .data = &ipu_type_imx51, },
-+      { .compatible = "fsl,imx53-ipu", .data = &ipu_type_imx53, },
-+      { .compatible = "fsl,imx6q-ipu", .data = &ipu_type_imx6q, },
-+      { .compatible = "fsl,imx6qp-ipu", .data = &ipu_type_imx6q, },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, imx_ipu_dt_ids);
-+
-+static int ipu_submodules_init(struct ipu_soc *ipu,
-+              struct platform_device *pdev, unsigned long ipu_base,
-+              struct clk *ipu_clk)
-+{
-+      char *unit;
-+      int ret;
-+      struct device *dev = &pdev->dev;
-+      const struct ipu_devtype *devtype = ipu->devtype;
-+
-+      ret = ipu_cpmem_init(ipu, dev, ipu_base + devtype->cpmem_ofs);
-+      if (ret) {
-+              unit = "cpmem";
-+              goto err_cpmem;
-+      }
-+
-+      ret = ipu_csi_init(ipu, dev, 0, ipu_base + devtype->csi0_ofs,
-+                         IPU_CONF_CSI0_EN, ipu_clk);
-+      if (ret) {
-+              unit = "csi0";
-+              goto err_csi_0;
-+      }
-+
-+      ret = ipu_csi_init(ipu, dev, 1, ipu_base + devtype->csi1_ofs,
-+                         IPU_CONF_CSI1_EN, ipu_clk);
-+      if (ret) {
-+              unit = "csi1";
-+              goto err_csi_1;
-+      }
-+
-+      ret = ipu_ic_init(ipu, dev,
-+                        ipu_base + devtype->ic_ofs,
-+                        ipu_base + devtype->tpm_ofs);
-+      if (ret) {
-+              unit = "ic";
-+              goto err_ic;
-+      }
-+
-+      ret = ipu_vdi_init(ipu, dev, ipu_base + devtype->vdi_ofs,
-+                         IPU_CONF_VDI_EN | IPU_CONF_ISP_EN |
-+                         IPU_CONF_IC_INPUT);
-+      if (ret) {
-+              unit = "vdi";
-+              goto err_vdi;
-+      }
-+
-+      ret = ipu_image_convert_init(ipu, dev);
-+      if (ret) {
-+              unit = "image_convert";
-+              goto err_image_convert;
-+      }
-+
-+      ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
-+                        IPU_CONF_DI0_EN, ipu_clk);
-+      if (ret) {
-+              unit = "di0";
-+              goto err_di_0;
-+      }
-+
-+      ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
-+                      IPU_CONF_DI1_EN, ipu_clk);
-+      if (ret) {
-+              unit = "di1";
-+              goto err_di_1;
-+      }
-+
-+      ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
-+                      IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
-+      if (ret) {
-+              unit = "dc_template";
-+              goto err_dc;
-+      }
-+
-+      ret = ipu_dmfc_init(ipu, dev, ipu_base +
-+                      devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
-+      if (ret) {
-+              unit = "dmfc";
-+              goto err_dmfc;
-+      }
-+
-+      ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
-+      if (ret) {
-+              unit = "dp";
-+              goto err_dp;
-+      }
-+
-+      ret = ipu_smfc_init(ipu, dev, ipu_base +
-+                      devtype->cm_ofs + IPU_CM_SMFC_REG_OFS);
-+      if (ret) {
-+              unit = "smfc";
-+              goto err_smfc;
-+      }
-+
-+      return 0;
-+
-+err_smfc:
-+      ipu_dp_exit(ipu);
-+err_dp:
-+      ipu_dmfc_exit(ipu);
-+err_dmfc:
-+      ipu_dc_exit(ipu);
-+err_dc:
-+      ipu_di_exit(ipu, 1);
-+err_di_1:
-+      ipu_di_exit(ipu, 0);
-+err_di_0:
-+      ipu_image_convert_exit(ipu);
-+err_image_convert:
-+      ipu_vdi_exit(ipu);
-+err_vdi:
-+      ipu_ic_exit(ipu);
-+err_ic:
-+      ipu_csi_exit(ipu, 1);
-+err_csi_1:
-+      ipu_csi_exit(ipu, 0);
-+err_csi_0:
-+      ipu_cpmem_exit(ipu);
-+err_cpmem:
-+      dev_err(&pdev->dev, "init %s failed with %d\n", unit, ret);
-+      return ret;
-+}
-+
-+static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
-+{
-+      unsigned long status;
-+      int i, bit, irq;
-+
-+      for (i = 0; i < num_regs; i++) {
-+
-+              status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i]));
-+              status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i]));
-+
-+              for_each_set_bit(bit, &status, 32) {
-+                      irq = irq_linear_revmap(ipu->domain,
-+                                              regs[i] * 32 + bit);
-+                      if (irq)
-+                              generic_handle_irq(irq);
-+              }
-+      }
-+}
-+
-+static void ipu_irq_handler(struct irq_desc *desc)
-+{
-+      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14};
-+
-+      chained_irq_enter(chip, desc);
-+
-+      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void ipu_err_irq_handler(struct irq_desc *desc)
-+{
-+      struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      static const int int_reg[] = { 4, 5, 8, 9};
-+
-+      chained_irq_enter(chip, desc);
-+
-+      ipu_irq_handle(ipu, int_reg, ARRAY_SIZE(int_reg));
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+int ipu_map_irq(struct ipu_soc *ipu, int irq)
-+{
-+      int virq;
-+
-+      virq = irq_linear_revmap(ipu->domain, irq);
-+      if (!virq)
-+              virq = irq_create_mapping(ipu->domain, irq);
-+
-+      return virq;
-+}
-+EXPORT_SYMBOL_GPL(ipu_map_irq);
-+
-+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-+              enum ipu_channel_irq irq_type)
-+{
-+      return ipu_map_irq(ipu, irq_type + channel->num);
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
-+
-+static void ipu_submodules_exit(struct ipu_soc *ipu)
-+{
-+      ipu_smfc_exit(ipu);
-+      ipu_dp_exit(ipu);
-+      ipu_dmfc_exit(ipu);
-+      ipu_dc_exit(ipu);
-+      ipu_di_exit(ipu, 1);
-+      ipu_di_exit(ipu, 0);
-+      ipu_image_convert_exit(ipu);
-+      ipu_vdi_exit(ipu);
-+      ipu_ic_exit(ipu);
-+      ipu_csi_exit(ipu, 1);
-+      ipu_csi_exit(ipu, 0);
-+      ipu_cpmem_exit(ipu);
-+}
-+
-+static int platform_remove_devices_fn(struct device *dev, void *unused)
-+{
-+      struct platform_device *pdev = to_platform_device(dev);
-+
-+      platform_device_unregister(pdev);
-+
-+      return 0;
-+}
-+
-+static void platform_device_unregister_children(struct platform_device *pdev)
-+{
-+      device_for_each_child(&pdev->dev, NULL, platform_remove_devices_fn);
-+}
-+
-+struct ipu_platform_reg {
-+      struct ipu_client_platformdata pdata;
-+      const char *name;
-+};
-+
-+/* These must be in the order of the corresponding device tree port nodes */
-+static struct ipu_platform_reg client_reg[] = {
-+      {
-+              .pdata = {
-+                      .csi = 0,
-+                      .dma[0] = IPUV3_CHANNEL_CSI0,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-csi",
-+      }, {
-+              .pdata = {
-+                      .csi = 1,
-+                      .dma[0] = IPUV3_CHANNEL_CSI1,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-csi",
-+      }, {
-+              .pdata = {
-+                      .di = 0,
-+                      .dc = 5,
-+                      .dp = IPU_DP_FLOW_SYNC_BG,
-+                      .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-+                      .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
-+              },
-+              .name = "imx-ipuv3-crtc",
-+      }, {
-+              .pdata = {
-+                      .di = 1,
-+                      .dc = 1,
-+                      .dp = -EINVAL,
-+                      .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
-+                      .dma[1] = -EINVAL,
-+              },
-+              .name = "imx-ipuv3-crtc",
-+      },
-+};
-+
-+static DEFINE_MUTEX(ipu_client_id_mutex);
-+static int ipu_client_id;
-+
-+static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
-+{
-+      struct device *dev = ipu->dev;
-+      unsigned i;
-+      int id, ret;
-+
-+      mutex_lock(&ipu_client_id_mutex);
-+      id = ipu_client_id;
-+      ipu_client_id += ARRAY_SIZE(client_reg);
-+      mutex_unlock(&ipu_client_id_mutex);
-+
-+      for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-+              struct ipu_platform_reg *reg = &client_reg[i];
-+              struct platform_device *pdev;
-+              struct device_node *of_node;
-+
-+              /* Associate subdevice with the corresponding port node */
-+              of_node = of_graph_get_port_by_id(dev->of_node, i);
-+              if (!of_node) {
-+                      dev_info(dev,
-+                               "no port@%d node in %pOF, not using %s%d\n",
-+                               i, dev->of_node,
-+                               (i / 2) ? "DI" : "CSI", i % 2);
-+                      continue;
-+              }
-+
-+              pdev = platform_device_alloc(reg->name, id++);
-+              if (!pdev) {
-+                      ret = -ENOMEM;
-+                      goto err_register;
-+              }
-+
-+              pdev->dev.parent = dev;
-+
-+              reg->pdata.of_node = of_node;
-+              ret = platform_device_add_data(pdev, &reg->pdata,
-+                                             sizeof(reg->pdata));
-+              if (!ret)
-+                      ret = platform_device_add(pdev);
-+              if (ret) {
-+                      platform_device_put(pdev);
-+                      goto err_register;
-+              }
-+      }
-+
-+      return 0;
-+
-+err_register:
-+      platform_device_unregister_children(to_platform_device(dev));
-+
-+      return ret;
-+}
-+
-+
-+static int ipu_irq_init(struct ipu_soc *ipu)
-+{
-+      struct irq_chip_generic *gc;
-+      struct irq_chip_type *ct;
-+      unsigned long unused[IPU_NUM_IRQS / 32] = {
-+              0x400100d0, 0xffe000fd,
-+              0x400100d0, 0xffe000fd,
-+              0x400100d0, 0xffe000fd,
-+              0x4077ffff, 0xffe7e1fd,
-+              0x23fffffe, 0x8880fff0,
-+              0xf98fe7d0, 0xfff81fff,
-+              0x400100d0, 0xffe000fd,
-+              0x00000000,
-+      };
-+      int ret, i;
-+
-+      ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS,
-+                                          &irq_generic_chip_ops, ipu);
-+      if (!ipu->domain) {
-+              dev_err(ipu->dev, "failed to add irq domain\n");
-+              return -ENODEV;
-+      }
-+
-+      ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
-+                                           handle_level_irq, 0, 0, 0);
-+      if (ret < 0) {
-+              dev_err(ipu->dev, "failed to alloc generic irq chips\n");
-+              irq_domain_remove(ipu->domain);
-+              return ret;
-+      }
-+
-+      /* Mask and clear all interrupts */
-+      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
-+              ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
-+              ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
-+      }
-+
-+      for (i = 0; i < IPU_NUM_IRQS; i += 32) {
-+              gc = irq_get_domain_generic_chip(ipu->domain, i);
-+              gc->reg_base = ipu->cm_reg;
-+              gc->unused = unused[i / 32];
-+              ct = gc->chip_types;
-+              ct->chip.irq_ack = irq_gc_ack_set_bit;
-+              ct->chip.irq_mask = irq_gc_mask_clr_bit;
-+              ct->chip.irq_unmask = irq_gc_mask_set_bit;
-+              ct->regs.ack = IPU_INT_STAT(i / 32);
-+              ct->regs.mask = IPU_INT_CTRL(i / 32);
-+      }
-+
-+      irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
-+      irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
-+                                       ipu);
-+
-+      return 0;
-+}
-+
-+static void ipu_irq_exit(struct ipu_soc *ipu)
-+{
-+      int i, irq;
-+
-+      irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
-+      irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
-+
-+      /* TODO: remove irq_domain_generic_chips */
-+
-+      for (i = 0; i < IPU_NUM_IRQS; i++) {
-+              irq = irq_linear_revmap(ipu->domain, i);
-+              if (irq)
-+                      irq_dispose_mapping(irq);
-+      }
-+
-+      irq_domain_remove(ipu->domain);
-+}
-+
-+void ipu_dump(struct ipu_soc *ipu)
-+{
-+      int i;
-+
-+      dev_dbg(ipu->dev, "IPU_CONF = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CONF));
-+      dev_dbg(ipu->dev, "IDMAC_CONF = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CONF));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_EN1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_EN(0)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_EN2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_EN(32)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_PRI1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_PRI(0)));
-+      dev_dbg(ipu->dev, "IDMAC_CHA_PRI2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_CHA_PRI(32)));
-+      dev_dbg(ipu->dev, "IDMAC_BAND_EN1 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_BAND_EN(0)));
-+      dev_dbg(ipu->dev, "IDMAC_BAND_EN2 = \t0x%08X\n",
-+              ipu_idmac_read(ipu, IDMAC_BAND_EN(32)));
-+      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(0)));
-+      dev_dbg(ipu->dev, "IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(32)));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW1));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW2 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW2));
-+      dev_dbg(ipu->dev, "IPU_FS_PROC_FLOW3 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_PROC_FLOW3));
-+      dev_dbg(ipu->dev, "IPU_FS_DISP_FLOW1 = \t0x%08X\n",
-+              ipu_cm_read(ipu, IPU_FS_DISP_FLOW1));
-+      for (i = 0; i < 15; i++)
-+              dev_dbg(ipu->dev, "IPU_INT_CTRL(%d) = \t%08X\n", i,
-+                      ipu_cm_read(ipu, IPU_INT_CTRL(i)));
-+}
-+EXPORT_SYMBOL_GPL(ipu_dump);
-+
-+static int ipu_probe(struct platform_device *pdev)
-+{
-+      struct device_node *np = pdev->dev.of_node;
-+      struct ipu_soc *ipu;
-+      struct resource *res;
-+      unsigned long ipu_base;
-+      int ret, irq_sync, irq_err;
-+      const struct ipu_devtype *devtype;
-+
-+      devtype = of_device_get_match_data(&pdev->dev);
-+      if (!devtype)
-+              return -EINVAL;
-+
-+      irq_sync = platform_get_irq(pdev, 0);
-+      irq_err = platform_get_irq(pdev, 1);
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+      dev_dbg(&pdev->dev, "irq_sync: %d irq_err: %d\n",
-+                      irq_sync, irq_err);
-+
-+      if (!res || irq_sync < 0 || irq_err < 0)
-+              return -ENODEV;
-+
-+      ipu_base = res->start;
-+
-+      ipu = devm_kzalloc(&pdev->dev, sizeof(*ipu), GFP_KERNEL);
-+      if (!ipu)
-+              return -ENODEV;
-+
-+      ipu->id = of_alias_get_id(np, "ipu");
-+      if (ipu->id < 0)
-+              ipu->id = 0;
-+
-+      if (of_device_is_compatible(np, "fsl,imx6qp-ipu") &&
-+          IS_ENABLED(CONFIG_DRM)) {
-+              ipu->prg_priv = ipu_prg_lookup_by_phandle(&pdev->dev,
-+                                                        "fsl,prg", ipu->id);
-+              if (!ipu->prg_priv)
-+                      return -EPROBE_DEFER;
-+      }
-+
-+      ipu->devtype = devtype;
-+      ipu->ipu_type = devtype->type;
-+
-+      spin_lock_init(&ipu->lock);
-+      mutex_init(&ipu->channel_lock);
-+      INIT_LIST_HEAD(&ipu->channels);
-+
-+      dev_dbg(&pdev->dev, "cm_reg:   0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs);
-+      dev_dbg(&pdev->dev, "idmac:    0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
-+      dev_dbg(&pdev->dev, "cpmem:    0x%08lx\n",
-+                      ipu_base + devtype->cpmem_ofs);
-+      dev_dbg(&pdev->dev, "csi0:    0x%08lx\n",
-+                      ipu_base + devtype->csi0_ofs);
-+      dev_dbg(&pdev->dev, "csi1:    0x%08lx\n",
-+                      ipu_base + devtype->csi1_ofs);
-+      dev_dbg(&pdev->dev, "ic:      0x%08lx\n",
-+                      ipu_base + devtype->ic_ofs);
-+      dev_dbg(&pdev->dev, "disp0:    0x%08lx\n",
-+                      ipu_base + devtype->disp0_ofs);
-+      dev_dbg(&pdev->dev, "disp1:    0x%08lx\n",
-+                      ipu_base + devtype->disp1_ofs);
-+      dev_dbg(&pdev->dev, "srm:      0x%08lx\n",
-+                      ipu_base + devtype->srm_ofs);
-+      dev_dbg(&pdev->dev, "tpm:      0x%08lx\n",
-+                      ipu_base + devtype->tpm_ofs);
-+      dev_dbg(&pdev->dev, "dc:       0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
-+      dev_dbg(&pdev->dev, "ic:       0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
-+      dev_dbg(&pdev->dev, "dmfc:     0x%08lx\n",
-+                      ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
-+      dev_dbg(&pdev->dev, "vdi:      0x%08lx\n",
-+                      ipu_base + devtype->vdi_ofs);
-+
-+      ipu->cm_reg = devm_ioremap(&pdev->dev,
-+                      ipu_base + devtype->cm_ofs, PAGE_SIZE);
-+      ipu->idmac_reg = devm_ioremap(&pdev->dev,
-+                      ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS,
-+                      PAGE_SIZE);
-+
-+      if (!ipu->cm_reg || !ipu->idmac_reg)
-+              return -ENOMEM;
-+
-+      ipu->clk = devm_clk_get(&pdev->dev, "bus");
-+      if (IS_ERR(ipu->clk)) {
-+              ret = PTR_ERR(ipu->clk);
-+              dev_err(&pdev->dev, "clk_get failed with %d", ret);
-+              return ret;
-+      }
-+
-+      platform_set_drvdata(pdev, ipu);
-+
-+      ret = clk_prepare_enable(ipu->clk);
-+      if (ret) {
-+              dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ipu->dev = &pdev->dev;
-+      ipu->irq_sync = irq_sync;
-+      ipu->irq_err = irq_err;
-+
-+      ret = device_reset(&pdev->dev);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to reset: %d\n", ret);
-+              goto out_failed_reset;
-+      }
-+      ret = ipu_memory_reset(ipu);
-+      if (ret)
-+              goto out_failed_reset;
-+
-+      ret = ipu_irq_init(ipu);
-+      if (ret)
-+              goto out_failed_irq;
-+
-+      /* Set MCU_T to divide MCU access window into 2 */
-+      ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
-+                      IPU_DISP_GEN);
-+
-+      ret = ipu_submodules_init(ipu, pdev, ipu_base, ipu->clk);
-+      if (ret)
-+              goto failed_submodules_init;
-+
-+      ret = ipu_add_client_devices(ipu, ipu_base);
-+      if (ret) {
-+              dev_err(&pdev->dev, "adding client devices failed with %d\n",
-+                              ret);
-+              goto failed_add_clients;
-+      }
-+
-+      dev_info(&pdev->dev, "%s probed\n", devtype->name);
-+
-+      return 0;
-+
-+failed_add_clients:
-+      ipu_submodules_exit(ipu);
-+failed_submodules_init:
-+      ipu_irq_exit(ipu);
-+out_failed_irq:
-+out_failed_reset:
-+      clk_disable_unprepare(ipu->clk);
-+      return ret;
-+}
-+
-+static int ipu_remove(struct platform_device *pdev)
-+{
-+      struct ipu_soc *ipu = platform_get_drvdata(pdev);
-+
-+      platform_device_unregister_children(pdev);
-+      ipu_submodules_exit(ipu);
-+      ipu_irq_exit(ipu);
-+
-+      clk_disable_unprepare(ipu->clk);
-+
-+      return 0;
-+}
-+
-+static struct platform_driver imx_ipu_driver = {
-+      .driver = {
-+              .name = "imx-ipuv3",
-+              .of_match_table = imx_ipu_dt_ids,
-+      },
-+      .probe = ipu_probe,
-+      .remove = ipu_remove,
-+};
-+
-+static struct platform_driver * const drivers[] = {
-+#if IS_ENABLED(CONFIG_DRM)
-+      &ipu_pre_drv,
-+      &ipu_prg_drv,
-+#endif
-+      &imx_ipu_driver,
-+};
-+
-+static int __init imx_ipu_init(void)
-+{
-+      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_init(imx_ipu_init);
-+
-+static void __exit imx_ipu_exit(void)
-+{
-+      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_exit(imx_ipu_exit);
-+
-+MODULE_ALIAS("platform:imx-ipuv3");
-+MODULE_DESCRIPTION("i.MX IPU v3 driver");
-+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
-@@ -0,0 +1,976 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012 Mentor Graphics Inc.
-+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+#include <linux/types.h>
-+#include <linux/bitrev.h>
-+#include <linux/io.h>
-+#include <linux/sizes.h>
-+#include <drm/drm_fourcc.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_cpmem_word {
-+      u32 data[5];
-+      u32 res[3];
-+};
-+
-+struct ipu_ch_param {
-+      struct ipu_cpmem_word word[2];
-+};
-+
-+struct ipu_cpmem {
-+      struct ipu_ch_param __iomem *base;
-+      u32 module;
-+      spinlock_t lock;
-+      int use_count;
-+      struct ipu_soc *ipu;
-+};
-+
-+#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
-+
-+#define IPU_FIELD_UBO         IPU_CPMEM_WORD(0, 46, 22)
-+#define IPU_FIELD_VBO         IPU_CPMEM_WORD(0, 68, 22)
-+#define IPU_FIELD_IOX         IPU_CPMEM_WORD(0, 90, 4)
-+#define IPU_FIELD_RDRW                IPU_CPMEM_WORD(0, 94, 1)
-+#define IPU_FIELD_SO          IPU_CPMEM_WORD(0, 113, 1)
-+#define IPU_FIELD_SLY         IPU_CPMEM_WORD(1, 102, 14)
-+#define IPU_FIELD_SLUV                IPU_CPMEM_WORD(1, 128, 14)
-+
-+#define IPU_FIELD_XV          IPU_CPMEM_WORD(0, 0, 10)
-+#define IPU_FIELD_YV          IPU_CPMEM_WORD(0, 10, 9)
-+#define IPU_FIELD_XB          IPU_CPMEM_WORD(0, 19, 13)
-+#define IPU_FIELD_YB          IPU_CPMEM_WORD(0, 32, 12)
-+#define IPU_FIELD_NSB_B               IPU_CPMEM_WORD(0, 44, 1)
-+#define IPU_FIELD_CF          IPU_CPMEM_WORD(0, 45, 1)
-+#define IPU_FIELD_SX          IPU_CPMEM_WORD(0, 46, 12)
-+#define IPU_FIELD_SY          IPU_CPMEM_WORD(0, 58, 11)
-+#define IPU_FIELD_NS          IPU_CPMEM_WORD(0, 69, 10)
-+#define IPU_FIELD_SDX         IPU_CPMEM_WORD(0, 79, 7)
-+#define IPU_FIELD_SM          IPU_CPMEM_WORD(0, 86, 10)
-+#define IPU_FIELD_SCC         IPU_CPMEM_WORD(0, 96, 1)
-+#define IPU_FIELD_SCE         IPU_CPMEM_WORD(0, 97, 1)
-+#define IPU_FIELD_SDY         IPU_CPMEM_WORD(0, 98, 7)
-+#define IPU_FIELD_SDRX                IPU_CPMEM_WORD(0, 105, 1)
-+#define IPU_FIELD_SDRY                IPU_CPMEM_WORD(0, 106, 1)
-+#define IPU_FIELD_BPP         IPU_CPMEM_WORD(0, 107, 3)
-+#define IPU_FIELD_DEC_SEL     IPU_CPMEM_WORD(0, 110, 2)
-+#define IPU_FIELD_DIM         IPU_CPMEM_WORD(0, 112, 1)
-+#define IPU_FIELD_BNDM                IPU_CPMEM_WORD(0, 114, 3)
-+#define IPU_FIELD_BM          IPU_CPMEM_WORD(0, 117, 2)
-+#define IPU_FIELD_ROT         IPU_CPMEM_WORD(0, 119, 1)
-+#define IPU_FIELD_ROT_HF_VF   IPU_CPMEM_WORD(0, 119, 3)
-+#define IPU_FIELD_HF          IPU_CPMEM_WORD(0, 120, 1)
-+#define IPU_FIELD_VF          IPU_CPMEM_WORD(0, 121, 1)
-+#define IPU_FIELD_THE         IPU_CPMEM_WORD(0, 122, 1)
-+#define IPU_FIELD_CAP         IPU_CPMEM_WORD(0, 123, 1)
-+#define IPU_FIELD_CAE         IPU_CPMEM_WORD(0, 124, 1)
-+#define IPU_FIELD_FW          IPU_CPMEM_WORD(0, 125, 13)
-+#define IPU_FIELD_FH          IPU_CPMEM_WORD(0, 138, 12)
-+#define IPU_FIELD_EBA0                IPU_CPMEM_WORD(1, 0, 29)
-+#define IPU_FIELD_EBA1                IPU_CPMEM_WORD(1, 29, 29)
-+#define IPU_FIELD_ILO         IPU_CPMEM_WORD(1, 58, 20)
-+#define IPU_FIELD_NPB         IPU_CPMEM_WORD(1, 78, 7)
-+#define IPU_FIELD_PFS         IPU_CPMEM_WORD(1, 85, 4)
-+#define IPU_FIELD_ALU         IPU_CPMEM_WORD(1, 89, 1)
-+#define IPU_FIELD_ALBM                IPU_CPMEM_WORD(1, 90, 3)
-+#define IPU_FIELD_ID          IPU_CPMEM_WORD(1, 93, 2)
-+#define IPU_FIELD_TH          IPU_CPMEM_WORD(1, 95, 7)
-+#define IPU_FIELD_SL          IPU_CPMEM_WORD(1, 102, 14)
-+#define IPU_FIELD_WID0                IPU_CPMEM_WORD(1, 116, 3)
-+#define IPU_FIELD_WID1                IPU_CPMEM_WORD(1, 119, 3)
-+#define IPU_FIELD_WID2                IPU_CPMEM_WORD(1, 122, 3)
-+#define IPU_FIELD_WID3                IPU_CPMEM_WORD(1, 125, 3)
-+#define IPU_FIELD_OFS0                IPU_CPMEM_WORD(1, 128, 5)
-+#define IPU_FIELD_OFS1                IPU_CPMEM_WORD(1, 133, 5)
-+#define IPU_FIELD_OFS2                IPU_CPMEM_WORD(1, 138, 5)
-+#define IPU_FIELD_OFS3                IPU_CPMEM_WORD(1, 143, 5)
-+#define IPU_FIELD_SXYS                IPU_CPMEM_WORD(1, 148, 1)
-+#define IPU_FIELD_CRE         IPU_CPMEM_WORD(1, 149, 1)
-+#define IPU_FIELD_DEC_SEL2    IPU_CPMEM_WORD(1, 150, 1)
-+
-+static inline struct ipu_ch_param __iomem *
-+ipu_get_cpmem(struct ipuv3_channel *ch)
-+{
-+      struct ipu_cpmem *cpmem = ch->ipu->cpmem_priv;
-+
-+      return cpmem->base + ch->num;
-+}
-+
-+static void ipu_ch_param_write_field(struct ipuv3_channel *ch, u32 wbs, u32 v)
-+{
-+      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
-+      u32 bit = (wbs >> 8) % 160;
-+      u32 size = wbs & 0xff;
-+      u32 word = (wbs >> 8) / 160;
-+      u32 i = bit / 32;
-+      u32 ofs = bit % 32;
-+      u32 mask = (1 << size) - 1;
-+      u32 val;
-+
-+      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-+
-+      val = readl(&base->word[word].data[i]);
-+      val &= ~(mask << ofs);
-+      val |= v << ofs;
-+      writel(val, &base->word[word].data[i]);
-+
-+      if ((bit + size - 1) / 32 > i) {
-+              val = readl(&base->word[word].data[i + 1]);
-+              val &= ~(mask >> (ofs ? (32 - ofs) : 0));
-+              val |= v >> (ofs ? (32 - ofs) : 0);
-+              writel(val, &base->word[word].data[i + 1]);
-+      }
-+}
-+
-+static u32 ipu_ch_param_read_field(struct ipuv3_channel *ch, u32 wbs)
-+{
-+      struct ipu_ch_param __iomem *base = ipu_get_cpmem(ch);
-+      u32 bit = (wbs >> 8) % 160;
-+      u32 size = wbs & 0xff;
-+      u32 word = (wbs >> 8) / 160;
-+      u32 i = bit / 32;
-+      u32 ofs = bit % 32;
-+      u32 mask = (1 << size) - 1;
-+      u32 val = 0;
-+
-+      pr_debug("%s %d %d %d\n", __func__, word, bit , size);
-+
-+      val = (readl(&base->word[word].data[i]) >> ofs) & mask;
-+
-+      if ((bit + size - 1) / 32 > i) {
-+              u32 tmp;
-+
-+              tmp = readl(&base->word[word].data[i + 1]);
-+              tmp &= mask >> (ofs ? (32 - ofs) : 0);
-+              val |= tmp << (ofs ? (32 - ofs) : 0);
-+      }
-+
-+      return val;
-+}
-+
-+/*
-+ * The V4L2 spec defines packed RGB formats in memory byte order, which from
-+ * point of view of the IPU corresponds to little-endian words with the first
-+ * component in the least significant bits.
-+ * The DRM pixel formats and IPU internal representation are ordered the other
-+ * way around, with the first named component ordered at the most significant
-+ * bits. Further, V4L2 formats are not well defined:
-+ *     https://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
-+ * We choose the interpretation which matches GStreamer behavior.
-+ */
-+static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
-+{
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_RGB565:
-+              /*
-+               * Here we choose the 'corrected' interpretation of RGBP, a
-+               * little-endian 16-bit word with the red component at the most
-+               * significant bits:
-+               * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
-+               */
-+              return DRM_FORMAT_RGB565;
-+      case V4L2_PIX_FMT_BGR24:
-+              /* B G R <=> [24:0] R:G:B */
-+              return DRM_FORMAT_RGB888;
-+      case V4L2_PIX_FMT_RGB24:
-+              /* R G B <=> [24:0] B:G:R */
-+              return DRM_FORMAT_BGR888;
-+      case V4L2_PIX_FMT_BGR32:
-+              /* B G R A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_XRGB8888;
-+      case V4L2_PIX_FMT_RGB32:
-+              /* R G B A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_XBGR8888;
-+      case V4L2_PIX_FMT_ABGR32:
-+              /* B G R A <=> [32:0] A:R:G:B */
-+              return DRM_FORMAT_ARGB8888;
-+      case V4L2_PIX_FMT_XBGR32:
-+              /* B G R X <=> [32:0] X:R:G:B */
-+              return DRM_FORMAT_XRGB8888;
-+      case V4L2_PIX_FMT_BGRA32:
-+              /* A B G R <=> [32:0] R:G:B:A */
-+              return DRM_FORMAT_RGBA8888;
-+      case V4L2_PIX_FMT_BGRX32:
-+              /* X B G R <=> [32:0] R:G:B:X */
-+              return DRM_FORMAT_RGBX8888;
-+      case V4L2_PIX_FMT_RGBA32:
-+              /* R G B A <=> [32:0] A:B:G:R */
-+              return DRM_FORMAT_ABGR8888;
-+      case V4L2_PIX_FMT_RGBX32:
-+              /* R G B X <=> [32:0] X:B:G:R */
-+              return DRM_FORMAT_XBGR8888;
-+      case V4L2_PIX_FMT_ARGB32:
-+              /* A R G B <=> [32:0] B:G:R:A */
-+              return DRM_FORMAT_BGRA8888;
-+      case V4L2_PIX_FMT_XRGB32:
-+              /* X R G B <=> [32:0] B:G:R:X */
-+              return DRM_FORMAT_BGRX8888;
-+      case V4L2_PIX_FMT_UYVY:
-+              return DRM_FORMAT_UYVY;
-+      case V4L2_PIX_FMT_YUYV:
-+              return DRM_FORMAT_YUYV;
-+      case V4L2_PIX_FMT_YUV420:
-+              return DRM_FORMAT_YUV420;
-+      case V4L2_PIX_FMT_YUV422P:
-+              return DRM_FORMAT_YUV422;
-+      case V4L2_PIX_FMT_YVU420:
-+              return DRM_FORMAT_YVU420;
-+      case V4L2_PIX_FMT_NV12:
-+              return DRM_FORMAT_NV12;
-+      case V4L2_PIX_FMT_NV16:
-+              return DRM_FORMAT_NV16;
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+void ipu_cpmem_zero(struct ipuv3_channel *ch)
-+{
-+      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
-+      void __iomem *base = p;
-+      int i;
-+
-+      for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
-+              writel(0, base + i * sizeof(u32));
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_zero);
-+
-+void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int xres, int yres)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_FW, xres - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_FH, yres - 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_resolution);
-+
-+void ipu_cpmem_skip_odd_chroma_rows(struct ipuv3_channel *ch)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_RDRW, 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_skip_odd_chroma_rows);
-+
-+void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, stride - 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_stride);
-+
-+void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch)
-+{
-+      struct ipu_soc *ipu = ch->ipu;
-+      u32 val;
-+
-+      if (ipu->ipu_type == IPUV3EX)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_ID, 1);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(ch->num));
-+      val |= 1 << (ch->num % 32);
-+      ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(ch->num));
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
-+
-+void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t buf)
-+{
-+      WARN_ON_ONCE(buf & 0x7);
-+
-+      if (bufnum)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_EBA1, buf >> 3);
-+      else
-+              ipu_ch_param_write_field(ch, IPU_FIELD_EBA0, buf >> 3);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);
-+
-+void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
-+{
-+      WARN_ON_ONCE((u_off & 0x7) || (v_off & 0x7));
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
-+
-+void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride,
-+                             u32 pixelformat)
-+{
-+      u32 ilo, sly, sluv;
-+
-+      if (stride < 0) {
-+              stride = -stride;
-+              ilo = 0x100000 - (stride / 8);
-+      } else {
-+              ilo = stride / 8;
-+      }
-+
-+      sly = (stride * 2) - 1;
-+
-+      switch (pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+      case V4L2_PIX_FMT_YVU420:
-+              sluv = stride / 2 - 1;
-+              break;
-+      case V4L2_PIX_FMT_NV12:
-+              sluv = stride - 1;
-+              break;
-+      case V4L2_PIX_FMT_YUV422P:
-+              sluv = stride - 1;
-+              break;
-+      case V4L2_PIX_FMT_NV16:
-+              sluv = stride * 2 - 1;
-+              break;
-+      default:
-+              sluv = 0;
-+              break;
-+      }
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ILO, ilo);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLY, sly);
-+      if (sluv)
-+              ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, sluv);
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_interlaced_scan);
-+
-+void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
-+{
-+      id &= 0x3;
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ID, id);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);
-+
-+int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
-+{
-+      return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
-+
-+void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
-+};
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_burstsize);
-+
-+void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch)
-+{
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BM, 1);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_block_mode);
-+
-+void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
-+                          enum ipu_rotate_mode rot)
-+{
-+      u32 temp_rot = bitrev8(rot) >> 5;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ROT_HF_VF, temp_rot);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_rotation);
-+
-+int ipu_cpmem_set_format_rgb(struct ipuv3_channel *ch,
-+                           const struct ipu_rgb *rgb)
-+{
-+      int bpp = 0, npb = 0, ro, go, bo, to;
-+
-+      ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
-+      go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
-+      bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
-+      to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID0, rgb->red.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS0, ro);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID1, rgb->green.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS1, go);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_WID2, rgb->blue.length - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_OFS2, bo);
-+
-+      if (rgb->transp.length) {
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3,
-+                              rgb->transp.length - 1);
-+              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3, to);
-+      } else {
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
-+              ipu_ch_param_write_field(ch, IPU_FIELD_OFS3,
-+                              rgb->bits_per_pixel);
-+      }
-+
-+      switch (rgb->bits_per_pixel) {
-+      case 32:
-+              bpp = 0;
-+              npb = 15;
-+              break;
-+      case 24:
-+              bpp = 1;
-+              npb = 19;
-+              break;
-+      case 16:
-+              bpp = 3;
-+              npb = 31;
-+              break;
-+      case 8:
-+              bpp = 5;
-+              npb = 63;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 7); /* rgb mode */
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
-+
-+int ipu_cpmem_set_format_passthrough(struct ipuv3_channel *ch, int width)
-+{
-+      int bpp = 0, npb = 0;
-+
-+      switch (width) {
-+      case 32:
-+              bpp = 0;
-+              npb = 15;
-+              break;
-+      case 24:
-+              bpp = 1;
-+              npb = 19;
-+              break;
-+      case 16:
-+              bpp = 3;
-+              npb = 31;
-+              break;
-+      case 8:
-+              bpp = 5;
-+              npb = 63;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_BPP, bpp);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_NPB, npb);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 6); /* raw mode */
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);
-+
-+void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
-+{
-+      switch (pixel_format) {
-+      case V4L2_PIX_FMT_UYVY:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
-+              break;
-+      case V4L2_PIX_FMT_YUYV:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
-+              break;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);
-+
-+void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
-+                                 unsigned int uv_stride,
-+                                 unsigned int u_offset, unsigned int v_offset)
-+{
-+      WARN_ON_ONCE((u_offset & 0x7) || (v_offset & 0x7));
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, uv_stride - 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
-+
-+static const struct ipu_rgb def_xrgb_32 = {
-+      .red    = { .offset = 16, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset =  0, .length = 8, },
-+      .transp = { .offset = 24, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_xbgr_32 = {
-+      .red    = { .offset =  0, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset = 16, .length = 8, },
-+      .transp = { .offset = 24, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_rgbx_32 = {
-+      .red    = { .offset = 24, .length = 8, },
-+      .green  = { .offset = 16, .length = 8, },
-+      .blue   = { .offset =  8, .length = 8, },
-+      .transp = { .offset =  0, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_bgrx_32 = {
-+      .red    = { .offset =  8, .length = 8, },
-+      .green  = { .offset = 16, .length = 8, },
-+      .blue   = { .offset = 24, .length = 8, },
-+      .transp = { .offset =  0, .length = 8, },
-+      .bits_per_pixel = 32,
-+};
-+
-+static const struct ipu_rgb def_rgb_24 = {
-+      .red    = { .offset = 16, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset =  0, .length = 8, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 24,
-+};
-+
-+static const struct ipu_rgb def_bgr_24 = {
-+      .red    = { .offset =  0, .length = 8, },
-+      .green  = { .offset =  8, .length = 8, },
-+      .blue   = { .offset = 16, .length = 8, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 24,
-+};
-+
-+static const struct ipu_rgb def_rgb_16 = {
-+      .red    = { .offset = 11, .length = 5, },
-+      .green  = { .offset =  5, .length = 6, },
-+      .blue   = { .offset =  0, .length = 5, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_bgr_16 = {
-+      .red    = { .offset =  0, .length = 5, },
-+      .green  = { .offset =  5, .length = 6, },
-+      .blue   = { .offset = 11, .length = 5, },
-+      .transp = { .offset =  0, .length = 0, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_argb_16 = {
-+      .red    = { .offset = 10, .length = 5, },
-+      .green  = { .offset =  5, .length = 5, },
-+      .blue   = { .offset =  0, .length = 5, },
-+      .transp = { .offset = 15, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_argb_16_4444 = {
-+      .red    = { .offset =  8, .length = 4, },
-+      .green  = { .offset =  4, .length = 4, },
-+      .blue   = { .offset =  0, .length = 4, },
-+      .transp = { .offset = 12, .length = 4, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_abgr_16 = {
-+      .red    = { .offset =  0, .length = 5, },
-+      .green  = { .offset =  5, .length = 5, },
-+      .blue   = { .offset = 10, .length = 5, },
-+      .transp = { .offset = 15, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_rgba_16 = {
-+      .red    = { .offset = 11, .length = 5, },
-+      .green  = { .offset =  6, .length = 5, },
-+      .blue   = { .offset =  1, .length = 5, },
-+      .transp = { .offset =  0, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+static const struct ipu_rgb def_bgra_16 = {
-+      .red    = { .offset =  1, .length = 5, },
-+      .green  = { .offset =  6, .length = 5, },
-+      .blue   = { .offset = 11, .length = 5, },
-+      .transp = { .offset =  0, .length = 1, },
-+      .bits_per_pixel = 16,
-+};
-+
-+#define Y_OFFSET(pix, x, y)   ((x) + pix->width * (y))
-+#define U_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-+                               (pix->width * ((y) / 2) / 2) + (x) / 2)
-+#define V_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-+                               (pix->width * pix->height / 4) +       \
-+                               (pix->width * ((y) / 2) / 2) + (x) / 2)
-+#define U2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
-+                               (pix->width * (y) / 2) + (x) / 2)
-+#define V2_OFFSET(pix, x, y)  ((pix->width * pix->height) +           \
-+                               (pix->width * pix->height / 2) +       \
-+                               (pix->width * (y) / 2) + (x) / 2)
-+#define UV_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
-+                               (pix->width * ((y) / 2)) + (x))
-+#define UV2_OFFSET(pix, x, y) ((pix->width * pix->height) +   \
-+                               (pix->width * y) + (x))
-+
-+#define NUM_ALPHA_CHANNELS    7
-+
-+/* See Table 37-12. Alpha channels mapping. */
-+static int ipu_channel_albm(int ch_num)
-+{
-+      switch (ch_num) {
-+      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:     return 0;
-+      case IPUV3_CHANNEL_G_MEM_IC_PP:         return 1;
-+      case IPUV3_CHANNEL_MEM_FG_SYNC:         return 2;
-+      case IPUV3_CHANNEL_MEM_FG_ASYNC:        return 3;
-+      case IPUV3_CHANNEL_MEM_BG_SYNC:         return 4;
-+      case IPUV3_CHANNEL_MEM_BG_ASYNC:        return 5;
-+      case IPUV3_CHANNEL_MEM_VDI_PLANE1_COMB: return 6;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static void ipu_cpmem_set_separate_alpha(struct ipuv3_channel *ch)
-+{
-+      struct ipu_soc *ipu = ch->ipu;
-+      int albm;
-+      u32 val;
-+
-+      albm = ipu_channel_albm(ch->num);
-+      if (albm < 0)
-+              return;
-+
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ALU, 1);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_ALBM, albm);
-+      ipu_ch_param_write_field(ch, IPU_FIELD_CRE, 1);
-+
-+      val = ipu_idmac_read(ipu, IDMAC_SEP_ALPHA);
-+      val |= BIT(ch->num);
-+      ipu_idmac_write(ipu, val, IDMAC_SEP_ALPHA);
-+}
-+
-+int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc)
-+{
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_YUV420:
-+      case DRM_FORMAT_YVU420:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 2);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUV422:
-+      case DRM_FORMAT_YVU422:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUV444:
-+      case DRM_FORMAT_YVU444:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_NV12:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_NV16:
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_UYVY:
-+              /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_YUYV:
-+              /* bits/pixel */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3);
-+              /* pix format */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);
-+              /* burst size */
-+              ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
-+              break;
-+      case DRM_FORMAT_ABGR8888:
-+      case DRM_FORMAT_XBGR8888:
-+              ipu_cpmem_set_format_rgb(ch, &def_xbgr_32);
-+              break;
-+      case DRM_FORMAT_ARGB8888:
-+      case DRM_FORMAT_XRGB8888:
-+              ipu_cpmem_set_format_rgb(ch, &def_xrgb_32);
-+              break;
-+      case DRM_FORMAT_RGBA8888:
-+      case DRM_FORMAT_RGBX8888:
-+      case DRM_FORMAT_RGBX8888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgbx_32);
-+              break;
-+      case DRM_FORMAT_BGRA8888:
-+      case DRM_FORMAT_BGRX8888:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgrx_32);
-+              break;
-+      case DRM_FORMAT_BGR888:
-+      case DRM_FORMAT_BGR888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgr_24);
-+              break;
-+      case DRM_FORMAT_RGB888:
-+      case DRM_FORMAT_RGB888_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgb_24);
-+              break;
-+      case DRM_FORMAT_RGB565:
-+      case DRM_FORMAT_RGB565_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgb_16);
-+              break;
-+      case DRM_FORMAT_BGR565:
-+      case DRM_FORMAT_BGR565_A8:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgr_16);
-+              break;
-+      case DRM_FORMAT_ARGB1555:
-+              ipu_cpmem_set_format_rgb(ch, &def_argb_16);
-+              break;
-+      case DRM_FORMAT_ABGR1555:
-+              ipu_cpmem_set_format_rgb(ch, &def_abgr_16);
-+              break;
-+      case DRM_FORMAT_RGBA5551:
-+              ipu_cpmem_set_format_rgb(ch, &def_rgba_16);
-+              break;
-+      case DRM_FORMAT_BGRA5551:
-+              ipu_cpmem_set_format_rgb(ch, &def_bgra_16);
-+              break;
-+      case DRM_FORMAT_ARGB4444:
-+              ipu_cpmem_set_format_rgb(ch, &def_argb_16_4444);
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      switch (drm_fourcc) {
-+      case DRM_FORMAT_RGB565_A8:
-+      case DRM_FORMAT_BGR565_A8:
-+      case DRM_FORMAT_RGB888_A8:
-+      case DRM_FORMAT_BGR888_A8:
-+      case DRM_FORMAT_RGBX8888_A8:
-+      case DRM_FORMAT_BGRX8888_A8:
-+              ipu_ch_param_write_field(ch, IPU_FIELD_WID3, 7);
-+              ipu_cpmem_set_separate_alpha(ch);
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
-+
-+int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image)
-+{
-+      struct v4l2_pix_format *pix = &image->pix;
-+      int offset, u_offset, v_offset;
-+      int ret = 0;
-+
-+      pr_debug("%s: resolution: %dx%d stride: %d\n",
-+               __func__, pix->width, pix->height,
-+               pix->bytesperline);
-+
-+      ipu_cpmem_set_resolution(ch, image->rect.width, image->rect.height);
-+      ipu_cpmem_set_stride(ch, pix->bytesperline);
-+
-+      ipu_cpmem_set_fmt(ch, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
-+
-+      switch (pix->pixelformat) {
-+      case V4L2_PIX_FMT_YUV420:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : U_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : V_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_YVU420:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : V_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : U_OFFSET(pix, image->rect.left,
-+                                                 image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_YUV422P:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : U2_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+              v_offset = image->v_offset ?
-+                      image->v_offset : V2_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline / 2,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_NV12:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : UV_OFFSET(pix, image->rect.left,
-+                                                  image->rect.top) - offset;
-+              v_offset = image->v_offset ? image->v_offset : 0;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_NV16:
-+              offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
-+              u_offset = image->u_offset ?
-+                      image->u_offset : UV2_OFFSET(pix, image->rect.left,
-+                                                   image->rect.top) - offset;
-+              v_offset = image->v_offset ? image->v_offset : 0;
-+
-+              ipu_cpmem_set_yuv_planar_full(ch, pix->bytesperline,
-+                                            u_offset, v_offset);
-+              break;
-+      case V4L2_PIX_FMT_UYVY:
-+      case V4L2_PIX_FMT_YUYV:
-+      case V4L2_PIX_FMT_RGB565:
-+              offset = image->rect.left * 2 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_RGB32:
-+      case V4L2_PIX_FMT_BGR32:
-+      case V4L2_PIX_FMT_ABGR32:
-+      case V4L2_PIX_FMT_XBGR32:
-+      case V4L2_PIX_FMT_BGRA32:
-+      case V4L2_PIX_FMT_BGRX32:
-+      case V4L2_PIX_FMT_RGBA32:
-+      case V4L2_PIX_FMT_RGBX32:
-+      case V4L2_PIX_FMT_ARGB32:
-+      case V4L2_PIX_FMT_XRGB32:
-+              offset = image->rect.left * 4 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_RGB24:
-+      case V4L2_PIX_FMT_BGR24:
-+              offset = image->rect.left * 3 +
-+                      image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_SBGGR8:
-+      case V4L2_PIX_FMT_SGBRG8:
-+      case V4L2_PIX_FMT_SGRBG8:
-+      case V4L2_PIX_FMT_SRGGB8:
-+      case V4L2_PIX_FMT_GREY:
-+              offset = image->rect.left + image->rect.top * pix->bytesperline;
-+              break;
-+      case V4L2_PIX_FMT_SBGGR16:
-+      case V4L2_PIX_FMT_SGBRG16:
-+      case V4L2_PIX_FMT_SGRBG16:
-+      case V4L2_PIX_FMT_SRGGB16:
-+      case V4L2_PIX_FMT_Y16:
-+              offset = image->rect.left * 2 +
-+                       image->rect.top * pix->bytesperline;
-+              break;
-+      default:
-+              /* This should not happen */
-+              WARN_ON(1);
-+              offset = 0;
-+              ret = -EINVAL;
-+      }
-+
-+      ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset);
-+      ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_set_image);
-+
-+void ipu_cpmem_dump(struct ipuv3_channel *ch)
-+{
-+      struct ipu_ch_param __iomem *p = ipu_get_cpmem(ch);
-+      struct ipu_soc *ipu = ch->ipu;
-+      int chno = ch->num;
-+
-+      dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", chno,
-+              readl(&p->word[0].data[0]),
-+              readl(&p->word[0].data[1]),
-+              readl(&p->word[0].data[2]),
-+              readl(&p->word[0].data[3]),
-+              readl(&p->word[0].data[4]));
-+      dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", chno,
-+              readl(&p->word[1].data[0]),
-+              readl(&p->word[1].data[1]),
-+              readl(&p->word[1].data[2]),
-+              readl(&p->word[1].data[3]),
-+              readl(&p->word[1].data[4]));
-+      dev_dbg(ipu->dev, "PFS 0x%x, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_PFS));
-+      dev_dbg(ipu->dev, "BPP 0x%x, ",
-+              ipu_ch_param_read_field(ch, IPU_FIELD_BPP));
-+      dev_dbg(ipu->dev, "NPB 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_NPB));
-+
-+      dev_dbg(ipu->dev, "FW %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_FW));
-+      dev_dbg(ipu->dev, "FH %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_FH));
-+      dev_dbg(ipu->dev, "EBA0 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_EBA0) << 3);
-+      dev_dbg(ipu->dev, "EBA1 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_EBA1) << 3);
-+      dev_dbg(ipu->dev, "Stride %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SL));
-+      dev_dbg(ipu->dev, "scan_order %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SO));
-+      dev_dbg(ipu->dev, "uv_stride %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_SLUV));
-+      dev_dbg(ipu->dev, "u_offset 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_UBO) << 3);
-+      dev_dbg(ipu->dev, "v_offset 0x%x\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_VBO) << 3);
-+
-+      dev_dbg(ipu->dev, "Width0 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID0));
-+      dev_dbg(ipu->dev, "Width1 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID1));
-+      dev_dbg(ipu->dev, "Width2 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID2));
-+      dev_dbg(ipu->dev, "Width3 %d+1, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_WID3));
-+      dev_dbg(ipu->dev, "Offset0 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS0));
-+      dev_dbg(ipu->dev, "Offset1 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS1));
-+      dev_dbg(ipu->dev, "Offset2 %d, ",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS2));
-+      dev_dbg(ipu->dev, "Offset3 %d\n",
-+               ipu_ch_param_read_field(ch, IPU_FIELD_OFS3));
-+}
-+EXPORT_SYMBOL_GPL(ipu_cpmem_dump);
-+
-+int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
-+{
-+      struct ipu_cpmem *cpmem;
-+
-+      cpmem = devm_kzalloc(dev, sizeof(*cpmem), GFP_KERNEL);
-+      if (!cpmem)
-+              return -ENOMEM;
-+
-+      ipu->cpmem_priv = cpmem;
-+
-+      spin_lock_init(&cpmem->lock);
-+      cpmem->base = devm_ioremap(dev, base, SZ_128K);
-+      if (!cpmem->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "CPMEM base: 0x%08lx remapped to %p\n",
-+              base, cpmem->base);
-+      cpmem->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_cpmem_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-csi.c
-@@ -0,0 +1,821 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2014 Mentor Graphics Inc.
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/platform_device.h>
-+#include <linux/videodev2.h>
-+#include <uapi/linux/v4l2-mediabus.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+
-+#include "ipu-prv.h"
-+
-+struct ipu_csi {
-+      void __iomem *base;
-+      int id;
-+      u32 module;
-+      struct clk *clk_ipu;    /* IPU bus clock */
-+      spinlock_t lock;
-+      bool inuse;
-+      struct ipu_soc *ipu;
-+};
-+
-+/* CSI Register Offsets */
-+#define CSI_SENS_CONF         0x0000
-+#define CSI_SENS_FRM_SIZE     0x0004
-+#define CSI_ACT_FRM_SIZE      0x0008
-+#define CSI_OUT_FRM_CTRL      0x000c
-+#define CSI_TST_CTRL          0x0010
-+#define CSI_CCIR_CODE_1               0x0014
-+#define CSI_CCIR_CODE_2               0x0018
-+#define CSI_CCIR_CODE_3               0x001c
-+#define CSI_MIPI_DI           0x0020
-+#define CSI_SKIP              0x0024
-+#define CSI_CPD_CTRL          0x0028
-+#define CSI_CPD_RC(n)         (0x002c + ((n)*4))
-+#define CSI_CPD_RS(n)         (0x004c + ((n)*4))
-+#define CSI_CPD_GRC(n)                (0x005c + ((n)*4))
-+#define CSI_CPD_GRS(n)                (0x007c + ((n)*4))
-+#define CSI_CPD_GBC(n)                (0x008c + ((n)*4))
-+#define CSI_CPD_GBS(n)                (0x00Ac + ((n)*4))
-+#define CSI_CPD_BC(n)         (0x00Bc + ((n)*4))
-+#define CSI_CPD_BS(n)         (0x00Dc + ((n)*4))
-+#define CSI_CPD_OFFSET1               0x00ec
-+#define CSI_CPD_OFFSET2               0x00f0
-+
-+/* CSI Register Fields */
-+#define CSI_SENS_CONF_DATA_FMT_SHIFT          8
-+#define CSI_SENS_CONF_DATA_FMT_MASK           0x00000700
-+#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444     0L
-+#define CSI_SENS_CONF_DATA_FMT_YUV422_YUYV    1L
-+#define CSI_SENS_CONF_DATA_FMT_YUV422_UYVY    2L
-+#define CSI_SENS_CONF_DATA_FMT_BAYER          3L
-+#define CSI_SENS_CONF_DATA_FMT_RGB565         4L
-+#define CSI_SENS_CONF_DATA_FMT_RGB555         5L
-+#define CSI_SENS_CONF_DATA_FMT_RGB444         6L
-+#define CSI_SENS_CONF_DATA_FMT_JPEG           7L
-+
-+#define CSI_SENS_CONF_VSYNC_POL_SHIFT         0
-+#define CSI_SENS_CONF_HSYNC_POL_SHIFT         1
-+#define CSI_SENS_CONF_DATA_POL_SHIFT          2
-+#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT               3
-+#define CSI_SENS_CONF_SENS_PRTCL_MASK         0x00000070
-+#define CSI_SENS_CONF_SENS_PRTCL_SHIFT                4
-+#define CSI_SENS_CONF_PACK_TIGHT_SHIFT                7
-+#define CSI_SENS_CONF_DATA_WIDTH_SHIFT                11
-+#define CSI_SENS_CONF_EXT_VSYNC_SHIFT         15
-+#define CSI_SENS_CONF_DIVRATIO_SHIFT          16
-+
-+#define CSI_SENS_CONF_DIVRATIO_MASK           0x00ff0000
-+#define CSI_SENS_CONF_DATA_DEST_SHIFT         24
-+#define CSI_SENS_CONF_DATA_DEST_MASK          0x07000000
-+#define CSI_SENS_CONF_JPEG8_EN_SHIFT          27
-+#define CSI_SENS_CONF_JPEG_EN_SHIFT           28
-+#define CSI_SENS_CONF_FORCE_EOF_SHIFT         29
-+#define CSI_SENS_CONF_DATA_EN_POL_SHIFT               31
-+
-+#define CSI_DATA_DEST_IC                      2
-+#define CSI_DATA_DEST_IDMAC                   4
-+
-+#define CSI_CCIR_ERR_DET_EN                   0x01000000
-+#define CSI_HORI_DOWNSIZE_EN                  0x80000000
-+#define CSI_VERT_DOWNSIZE_EN                  0x40000000
-+#define CSI_TEST_GEN_MODE_EN                  0x01000000
-+
-+#define CSI_HSC_MASK                          0x1fff0000
-+#define CSI_HSC_SHIFT                         16
-+#define CSI_VSC_MASK                          0x00000fff
-+#define CSI_VSC_SHIFT                         0
-+
-+#define CSI_TEST_GEN_R_MASK                   0x000000ff
-+#define CSI_TEST_GEN_R_SHIFT                  0
-+#define CSI_TEST_GEN_G_MASK                   0x0000ff00
-+#define CSI_TEST_GEN_G_SHIFT                  8
-+#define CSI_TEST_GEN_B_MASK                   0x00ff0000
-+#define CSI_TEST_GEN_B_SHIFT                  16
-+
-+#define CSI_MAX_RATIO_SKIP_SMFC_MASK          0x00000007
-+#define CSI_MAX_RATIO_SKIP_SMFC_SHIFT         0
-+#define CSI_SKIP_SMFC_MASK                    0x000000f8
-+#define CSI_SKIP_SMFC_SHIFT                   3
-+#define CSI_ID_2_SKIP_MASK                    0x00000300
-+#define CSI_ID_2_SKIP_SHIFT                   8
-+
-+#define CSI_COLOR_FIRST_ROW_MASK              0x00000002
-+#define CSI_COLOR_FIRST_COMP_MASK             0x00000001
-+
-+/* MIPI CSI-2 data types */
-+#define MIPI_DT_YUV420                0x18 /* YYY.../UYVY.... */
-+#define MIPI_DT_YUV420_LEGACY 0x1a /* UYY.../VYY...   */
-+#define MIPI_DT_YUV422                0x1e /* UYVY...         */
-+#define MIPI_DT_RGB444                0x20
-+#define MIPI_DT_RGB555                0x21
-+#define MIPI_DT_RGB565                0x22
-+#define MIPI_DT_RGB666                0x23
-+#define MIPI_DT_RGB888                0x24
-+#define MIPI_DT_RAW6          0x28
-+#define MIPI_DT_RAW7          0x29
-+#define MIPI_DT_RAW8          0x2a
-+#define MIPI_DT_RAW10         0x2b
-+#define MIPI_DT_RAW12         0x2c
-+#define MIPI_DT_RAW14         0x2d
-+
-+/*
-+ * Bitfield of CSI bus signal polarities and modes.
-+ */
-+struct ipu_csi_bus_config {
-+      unsigned data_width:4;
-+      unsigned clk_mode:3;
-+      unsigned ext_vsync:1;
-+      unsigned vsync_pol:1;
-+      unsigned hsync_pol:1;
-+      unsigned pixclk_pol:1;
-+      unsigned data_pol:1;
-+      unsigned sens_clksrc:1;
-+      unsigned pack_tight:1;
-+      unsigned force_eof:1;
-+      unsigned data_en_pol:1;
-+
-+      unsigned data_fmt;
-+      unsigned mipi_dt;
-+};
-+
-+/*
-+ * Enumeration of CSI data bus widths.
-+ */
-+enum ipu_csi_data_width {
-+      IPU_CSI_DATA_WIDTH_4   = 0,
-+      IPU_CSI_DATA_WIDTH_8   = 1,
-+      IPU_CSI_DATA_WIDTH_10  = 3,
-+      IPU_CSI_DATA_WIDTH_12  = 5,
-+      IPU_CSI_DATA_WIDTH_16  = 9,
-+};
-+
-+/*
-+ * Enumeration of CSI clock modes.
-+ */
-+enum ipu_csi_clk_mode {
-+      IPU_CSI_CLK_MODE_GATED_CLK,
-+      IPU_CSI_CLK_MODE_NONGATED_CLK,
-+      IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
-+      IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
-+      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
-+      IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
-+};
-+
-+static inline u32 ipu_csi_read(struct ipu_csi *csi, unsigned offset)
-+{
-+      return readl(csi->base + offset);
-+}
-+
-+static inline void ipu_csi_write(struct ipu_csi *csi, u32 value,
-+                               unsigned offset)
-+{
-+      writel(value, csi->base + offset);
-+}
-+
-+/*
-+ * Set mclk division ratio for generating test mode mclk. Only used
-+ * for test generator.
-+ */
-+static int ipu_csi_set_testgen_mclk(struct ipu_csi *csi, u32 pixel_clk,
-+                                      u32 ipu_clk)
-+{
-+      u32 temp;
-+      int div_ratio;
-+
-+      div_ratio = (ipu_clk / pixel_clk) - 1;
-+
-+      if (div_ratio > 0xFF || div_ratio < 0) {
-+              dev_err(csi->ipu->dev,
-+                      "value of pixel_clk extends normal range\n");
-+              return -EINVAL;
-+      }
-+
-+      temp = ipu_csi_read(csi, CSI_SENS_CONF);
-+      temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
-+      ipu_csi_write(csi, temp | (div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
-+                        CSI_SENS_CONF);
-+
-+      return 0;
-+}
-+
-+/*
-+ * Find the CSI data format and data width for the given V4L2 media
-+ * bus pixel format code.
-+ */
-+static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code,
-+                              enum v4l2_mbus_type mbus_type)
-+{
-+      switch (mbus_code) {
-+      case MEDIA_BUS_FMT_BGR565_2X8_BE:
-+      case MEDIA_BUS_FMT_BGR565_2X8_LE:
-+      case MEDIA_BUS_FMT_RGB565_2X8_BE:
-+      case MEDIA_BUS_FMT_RGB565_2X8_LE:
-+              if (mbus_type == V4L2_MBUS_CSI2_DPHY)
-+                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
-+              else
-+                      cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RGB565;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB444;
-+              cfg->mipi_dt = MIPI_DT_RGB444;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
-+              cfg->mipi_dt = MIPI_DT_RGB555;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_RGB888_1X24:
-+      case MEDIA_BUS_FMT_BGR888_1X24:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
-+              cfg->mipi_dt = MIPI_DT_RGB888;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_UYVY8_2X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_YUYV8_2X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_UYVY8_1X16:
-+      case MEDIA_BUS_FMT_YUYV8_1X16:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_YUV422;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_16;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG8_1X8:
-+      case MEDIA_BUS_FMT_SRGGB8_1X8:
-+      case MEDIA_BUS_FMT_Y8_1X8:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW8;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
-+      case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW10;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR10_1X10:
-+      case MEDIA_BUS_FMT_SGBRG10_1X10:
-+      case MEDIA_BUS_FMT_SGRBG10_1X10:
-+      case MEDIA_BUS_FMT_SRGGB10_1X10:
-+      case MEDIA_BUS_FMT_Y10_1X10:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW10;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_10;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR12_1X12:
-+      case MEDIA_BUS_FMT_SGBRG12_1X12:
-+      case MEDIA_BUS_FMT_SGRBG12_1X12:
-+      case MEDIA_BUS_FMT_SRGGB12_1X12:
-+      case MEDIA_BUS_FMT_Y12_1X12:
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
-+              cfg->mipi_dt = MIPI_DT_RAW12;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_12;
-+              break;
-+      case MEDIA_BUS_FMT_JPEG_1X8:
-+              /* TODO */
-+              cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_JPEG;
-+              cfg->mipi_dt = MIPI_DT_RAW8;
-+              cfg->data_width = IPU_CSI_DATA_WIDTH_8;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+/* translate alternate field mode based on given standard */
-+static inline enum v4l2_field
-+ipu_csi_translate_field(enum v4l2_field field, v4l2_std_id std)
-+{
-+      return (field != V4L2_FIELD_ALTERNATE) ? field :
-+              ((std & V4L2_STD_525_60) ?
-+               V4L2_FIELD_SEQ_BT : V4L2_FIELD_SEQ_TB);
-+}
-+
-+/*
-+ * Fill a CSI bus config struct from mbus_config and mbus_framefmt.
-+ */
-+static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
-+                          const struct v4l2_mbus_config *mbus_cfg,
-+                          const struct v4l2_mbus_framefmt *mbus_fmt)
-+{
-+      int ret;
-+
-+      memset(csicfg, 0, sizeof(*csicfg));
-+
-+      ret = mbus_code_to_bus_cfg(csicfg, mbus_fmt->code, mbus_cfg->type);
-+      if (ret < 0)
-+              return ret;
-+
-+      switch (mbus_cfg->type) {
-+      case V4L2_MBUS_PARALLEL:
-+              csicfg->ext_vsync = 1;
-+              csicfg->vsync_pol = (mbus_cfg->flags &
-+                                   V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
-+              csicfg->hsync_pol = (mbus_cfg->flags &
-+                                   V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
-+              csicfg->pixclk_pol = (mbus_cfg->flags &
-+                                    V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
-+              csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
-+              break;
-+      case V4L2_MBUS_BT656:
-+              csicfg->ext_vsync = 0;
-+              if (V4L2_FIELD_HAS_BOTH(mbus_fmt->field) ||
-+                  mbus_fmt->field == V4L2_FIELD_ALTERNATE)
-+                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED;
-+              else
-+                      csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE;
-+              break;
-+      case V4L2_MBUS_CSI2_DPHY:
-+              /*
-+               * MIPI CSI-2 requires non gated clock mode, all other
-+               * parameters are not applicable for MIPI CSI-2 bus.
-+               */
-+              csicfg->clk_mode = IPU_CSI_CLK_MODE_NONGATED_CLK;
-+              break;
-+      default:
-+              /* will never get here, keep compiler quiet */
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int
-+ipu_csi_set_bt_interlaced_codes(struct ipu_csi *csi,
-+                              const struct v4l2_mbus_framefmt *infmt,
-+                              const struct v4l2_mbus_framefmt *outfmt,
-+                              v4l2_std_id std)
-+{
-+      enum v4l2_field infield, outfield;
-+      bool swap_fields;
-+
-+      /* get translated field type of input and output */
-+      infield = ipu_csi_translate_field(infmt->field, std);
-+      outfield = ipu_csi_translate_field(outfmt->field, std);
-+
-+      /*
-+       * Write the H-V-F codes the CSI will match against the
-+       * incoming data for start/end of active and blanking
-+       * field intervals. If input and output field types are
-+       * sequential but not the same (one is SEQ_BT and the other
-+       * is SEQ_TB), swap the F-bit so that the CSI will capture
-+       * field 1 lines before field 0 lines.
-+       */
-+      swap_fields = (V4L2_FIELD_IS_SEQUENTIAL(infield) &&
-+                     V4L2_FIELD_IS_SEQUENTIAL(outfield) &&
-+                     infield != outfield);
-+
-+      if (!swap_fields) {
-+              /*
-+               * Field0BlankEnd  = 110, Field0BlankStart  = 010
-+               * Field0ActiveEnd = 100, Field0ActiveStart = 000
-+               * Field1BlankEnd  = 111, Field1BlankStart  = 011
-+               * Field1ActiveEnd = 101, Field1ActiveStart = 001
-+               */
-+              ipu_csi_write(csi, 0x40596 | CSI_CCIR_ERR_DET_EN,
-+                            CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xD07DF, CSI_CCIR_CODE_2);
-+      } else {
-+              dev_dbg(csi->ipu->dev, "capture field swap\n");
-+
-+              /* same as above but with F-bit inverted */
-+              ipu_csi_write(csi, 0xD07DF | CSI_CCIR_ERR_DET_EN,
-+                            CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0x40596, CSI_CCIR_CODE_2);
-+      }
-+
-+      ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+
-+      return 0;
-+}
-+
-+
-+int ipu_csi_init_interface(struct ipu_csi *csi,
-+                         const struct v4l2_mbus_config *mbus_cfg,
-+                         const struct v4l2_mbus_framefmt *infmt,
-+                         const struct v4l2_mbus_framefmt *outfmt)
-+{
-+      struct ipu_csi_bus_config cfg;
-+      unsigned long flags;
-+      u32 width, height, data = 0;
-+      v4l2_std_id std;
-+      int ret;
-+
-+      ret = fill_csi_bus_cfg(&cfg, mbus_cfg, infmt);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* set default sensor frame width and height */
-+      width = infmt->width;
-+      height = infmt->height;
-+      if (infmt->field == V4L2_FIELD_ALTERNATE)
-+              height *= 2;
-+
-+      /* Set the CSI_SENS_CONF register remaining fields */
-+      data |= cfg.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
-+              cfg.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
-+              cfg.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
-+              cfg.vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
-+              cfg.hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
-+              cfg.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
-+              cfg.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
-+              cfg.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
-+              cfg.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
-+              cfg.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
-+              cfg.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      ipu_csi_write(csi, data, CSI_SENS_CONF);
-+
-+      /* Set CCIR registers */
-+
-+      switch (cfg.clk_mode) {
-+      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
-+              ipu_csi_write(csi, 0x40030, CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+              break;
-+      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
-+              if (width == 720 && height == 480) {
-+                      std = V4L2_STD_NTSC;
-+                      height = 525;
-+              } else if (width == 720 && height == 576) {
-+                      std = V4L2_STD_PAL;
-+                      height = 625;
-+              } else {
-+                      dev_err(csi->ipu->dev,
-+                              "Unsupported interlaced video mode\n");
-+                      ret = -EINVAL;
-+                      goto out_unlock;
-+              }
-+
-+              ret = ipu_csi_set_bt_interlaced_codes(csi, infmt, outfmt, std);
-+              if (ret)
-+                      goto out_unlock;
-+              break;
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
-+              ipu_csi_write(csi, 0x40030 | CSI_CCIR_ERR_DET_EN,
-+                                 CSI_CCIR_CODE_1);
-+              ipu_csi_write(csi, 0xFF0000, CSI_CCIR_CODE_3);
-+              break;
-+      case IPU_CSI_CLK_MODE_GATED_CLK:
-+      case IPU_CSI_CLK_MODE_NONGATED_CLK:
-+              ipu_csi_write(csi, 0, CSI_CCIR_CODE_1);
-+              break;
-+      }
-+
-+      /* Setup sensor frame size */
-+      ipu_csi_write(csi, (width - 1) | ((height - 1) << 16),
-+                    CSI_SENS_FRM_SIZE);
-+
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
-+              ipu_csi_read(csi, CSI_SENS_CONF));
-+      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
-+              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
-+
-+out_unlock:
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_init_interface);
-+
-+bool ipu_csi_is_interlaced(struct ipu_csi *csi)
-+{
-+      unsigned long flags;
-+      u32 sensor_protocol;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+      sensor_protocol =
-+              (ipu_csi_read(csi, CSI_SENS_CONF) &
-+               CSI_SENS_CONF_SENS_PRTCL_MASK) >>
-+              CSI_SENS_CONF_SENS_PRTCL_SHIFT;
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      switch (sensor_protocol) {
-+      case IPU_CSI_CLK_MODE_GATED_CLK:
-+      case IPU_CSI_CLK_MODE_NONGATED_CLK:
-+      case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR:
-+              return false;
-+      case IPU_CSI_CLK_MODE_CCIR656_INTERLACED:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR:
-+      case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR:
-+              return true;
-+      default:
-+              dev_err(csi->ipu->dev,
-+                      "CSI %d sensor protocol unsupported\n", csi->id);
-+              return false;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_is_interlaced);
-+
-+void ipu_csi_get_window(struct ipu_csi *csi, struct v4l2_rect *w)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      reg = ipu_csi_read(csi, CSI_ACT_FRM_SIZE);
-+      w->width = (reg & 0xFFFF) + 1;
-+      w->height = (reg >> 16 & 0xFFFF) + 1;
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      w->left = (reg & CSI_HSC_MASK) >> CSI_HSC_SHIFT;
-+      w->top = (reg & CSI_VSC_MASK) >> CSI_VSC_SHIFT;
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_get_window);
-+
-+void ipu_csi_set_window(struct ipu_csi *csi, struct v4l2_rect *w)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      ipu_csi_write(csi, (w->width - 1) | ((w->height - 1) << 16),
-+                        CSI_ACT_FRM_SIZE);
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      reg &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
-+      reg |= ((w->top << CSI_VSC_SHIFT) | (w->left << CSI_HSC_SHIFT));
-+      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_window);
-+
-+void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
-+      reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
-+      reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
-+             (vert ? CSI_VERT_DOWNSIZE_EN : 0);
-+      ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_downsize);
-+
-+void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
-+                              u32 r_value, u32 g_value, u32 b_value,
-+                              u32 pix_clk)
-+{
-+      unsigned long flags;
-+      u32 ipu_clk = clk_get_rate(csi->clk_ipu);
-+      u32 temp;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_TST_CTRL);
-+
-+      if (!active) {
-+              temp &= ~CSI_TEST_GEN_MODE_EN;
-+              ipu_csi_write(csi, temp, CSI_TST_CTRL);
-+      } else {
-+              /* Set sensb_mclk div_ratio */
-+              ipu_csi_set_testgen_mclk(csi, pix_clk, ipu_clk);
-+
-+              temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
-+                        CSI_TEST_GEN_B_MASK);
-+              temp |= CSI_TEST_GEN_MODE_EN;
-+              temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
-+                      (g_value << CSI_TEST_GEN_G_SHIFT) |
-+                      (b_value << CSI_TEST_GEN_B_SHIFT);
-+              ipu_csi_write(csi, temp, CSI_TST_CTRL);
-+      }
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_test_generator);
-+
-+int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc,
-+                            struct v4l2_mbus_framefmt *mbus_fmt)
-+{
-+      struct ipu_csi_bus_config cfg;
-+      unsigned long flags;
-+      u32 temp;
-+      int ret;
-+
-+      if (vc > 3)
-+              return -EINVAL;
-+
-+      ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY);
-+      if (ret < 0)
-+              return ret;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_MIPI_DI);
-+      temp &= ~(0xff << (vc * 8));
-+      temp |= (cfg.mipi_dt << (vc * 8));
-+      ipu_csi_write(csi, temp, CSI_MIPI_DI);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_mipi_datatype);
-+
-+int ipu_csi_set_skip_smfc(struct ipu_csi *csi, u32 skip,
-+                        u32 max_ratio, u32 id)
-+{
-+      unsigned long flags;
-+      u32 temp;
-+
-+      if (max_ratio > 5 || id > 3)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      temp = ipu_csi_read(csi, CSI_SKIP);
-+      temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
-+                CSI_SKIP_SMFC_MASK);
-+      temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
-+              (id << CSI_ID_2_SKIP_SHIFT) |
-+              (skip << CSI_SKIP_SMFC_SHIFT);
-+      ipu_csi_write(csi, temp, CSI_SKIP);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_skip_smfc);
-+
-+int ipu_csi_set_dest(struct ipu_csi *csi, enum ipu_csi_dest csi_dest)
-+{
-+      unsigned long flags;
-+      u32 csi_sens_conf, dest;
-+
-+      if (csi_dest == IPU_CSI_DEST_IDMAC)
-+              dest = CSI_DATA_DEST_IDMAC;
-+      else
-+              dest = CSI_DATA_DEST_IC; /* IC or VDIC */
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      csi_sens_conf = ipu_csi_read(csi, CSI_SENS_CONF);
-+      csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
-+      csi_sens_conf |= (dest << CSI_SENS_CONF_DATA_DEST_SHIFT);
-+      ipu_csi_write(csi, csi_sens_conf, CSI_SENS_CONF);
-+
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_set_dest);
-+
-+int ipu_csi_enable(struct ipu_csi *csi)
-+{
-+      ipu_module_enable(csi->ipu, csi->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_enable);
-+
-+int ipu_csi_disable(struct ipu_csi *csi)
-+{
-+      ipu_module_disable(csi->ipu, csi->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_disable);
-+
-+struct ipu_csi *ipu_csi_get(struct ipu_soc *ipu, int id)
-+{
-+      unsigned long flags;
-+      struct ipu_csi *csi, *ret;
-+
-+      if (id > 1)
-+              return ERR_PTR(-EINVAL);
-+
-+      csi = ipu->csi_priv[id];
-+      ret = csi;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+
-+      if (csi->inuse) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      csi->inuse = true;
-+unlock:
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_get);
-+
-+void ipu_csi_put(struct ipu_csi *csi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&csi->lock, flags);
-+      csi->inuse = false;
-+      spin_unlock_irqrestore(&csi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_put);
-+
-+int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
-+               unsigned long base, u32 module, struct clk *clk_ipu)
-+{
-+      struct ipu_csi *csi;
-+
-+      if (id > 1)
-+              return -ENODEV;
-+
-+      csi = devm_kzalloc(dev, sizeof(*csi), GFP_KERNEL);
-+      if (!csi)
-+              return -ENOMEM;
-+
-+      ipu->csi_priv[id] = csi;
-+
-+      spin_lock_init(&csi->lock);
-+      csi->module = module;
-+      csi->id = id;
-+      csi->clk_ipu = clk_ipu;
-+      csi->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!csi->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "CSI%d base: 0x%08lx remapped to %p\n",
-+              id, base, csi->base);
-+      csi->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_csi_exit(struct ipu_soc *ipu, int id)
-+{
-+}
-+
-+void ipu_csi_dump(struct ipu_csi *csi)
-+{
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_CONF:     %08x\n",
-+              ipu_csi_read(csi, CSI_SENS_CONF));
-+      dev_dbg(csi->ipu->dev, "CSI_SENS_FRM_SIZE: %08x\n",
-+              ipu_csi_read(csi, CSI_SENS_FRM_SIZE));
-+      dev_dbg(csi->ipu->dev, "CSI_ACT_FRM_SIZE:  %08x\n",
-+              ipu_csi_read(csi, CSI_ACT_FRM_SIZE));
-+      dev_dbg(csi->ipu->dev, "CSI_OUT_FRM_CTRL:  %08x\n",
-+              ipu_csi_read(csi, CSI_OUT_FRM_CTRL));
-+      dev_dbg(csi->ipu->dev, "CSI_TST_CTRL:      %08x\n",
-+              ipu_csi_read(csi, CSI_TST_CTRL));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_1:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_1));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_2:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_2));
-+      dev_dbg(csi->ipu->dev, "CSI_CCIR_CODE_3:   %08x\n",
-+              ipu_csi_read(csi, CSI_CCIR_CODE_3));
-+      dev_dbg(csi->ipu->dev, "CSI_MIPI_DI:       %08x\n",
-+              ipu_csi_read(csi, CSI_MIPI_DI));
-+      dev_dbg(csi->ipu->dev, "CSI_SKIP:          %08x\n",
-+              ipu_csi_read(csi, CSI_SKIP));
-+}
-+EXPORT_SYMBOL_GPL(ipu_csi_dump);
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-dc.c
-@@ -0,0 +1,420 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DC_MAP_CONF_PTR(n)    (0x108 + ((n) & ~0x1) * 2)
-+#define DC_MAP_CONF_VAL(n)    (0x144 + ((n) & ~0x1) * 2)
-+
-+#define DC_EVT_NF             0
-+#define DC_EVT_NL             1
-+#define DC_EVT_EOF            2
-+#define DC_EVT_NFIELD         3
-+#define DC_EVT_EOL            4
-+#define DC_EVT_EOFIELD                5
-+#define DC_EVT_NEW_ADDR               6
-+#define DC_EVT_NEW_CHAN               7
-+#define DC_EVT_NEW_DATA               8
-+
-+#define DC_EVT_NEW_ADDR_W_0   0
-+#define DC_EVT_NEW_ADDR_W_1   1
-+#define DC_EVT_NEW_CHAN_W_0   2
-+#define DC_EVT_NEW_CHAN_W_1   3
-+#define DC_EVT_NEW_DATA_W_0   4
-+#define DC_EVT_NEW_DATA_W_1   5
-+#define DC_EVT_NEW_ADDR_R_0   6
-+#define DC_EVT_NEW_ADDR_R_1   7
-+#define DC_EVT_NEW_CHAN_R_0   8
-+#define DC_EVT_NEW_CHAN_R_1   9
-+#define DC_EVT_NEW_DATA_R_0   10
-+#define DC_EVT_NEW_DATA_R_1   11
-+
-+#define DC_WR_CH_CONF         0x0
-+#define DC_WR_CH_ADDR         0x4
-+#define DC_RL_CH(evt)         (8 + ((evt) & ~0x1) * 2)
-+
-+#define DC_GEN                        0xd4
-+#define DC_DISP_CONF1(disp)   (0xd8 + (disp) * 4)
-+#define DC_DISP_CONF2(disp)   (0xe8 + (disp) * 4)
-+#define DC_STAT                       0x1c8
-+
-+#define WROD(lf)              (0x18 | ((lf) << 1))
-+#define WRG                   0x01
-+#define WCLK                  0xc9
-+
-+#define SYNC_WAVE 0
-+#define NULL_WAVE (-1)
-+
-+#define DC_GEN_SYNC_1_6_SYNC  (2 << 1)
-+#define DC_GEN_SYNC_PRIORITY_1        (1 << 7)
-+
-+#define DC_WR_CH_CONF_WORD_SIZE_8             (0 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_16            (1 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_24            (2 << 0)
-+#define DC_WR_CH_CONF_WORD_SIZE_32            (3 << 0)
-+#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i)     (((i) & 0x1) << 3)
-+#define DC_WR_CH_CONF_DISP_ID_SERIAL          (2 << 3)
-+#define DC_WR_CH_CONF_DISP_ID_ASYNC           (3 << 4)
-+#define DC_WR_CH_CONF_FIELD_MODE              (1 << 9)
-+#define DC_WR_CH_CONF_PROG_TYPE_NORMAL                (4 << 5)
-+#define DC_WR_CH_CONF_PROG_TYPE_MASK          (7 << 5)
-+#define DC_WR_CH_CONF_PROG_DI_ID              (1 << 2)
-+#define DC_WR_CH_CONF_PROG_DISP_ID(i)         (((i) & 0x1) << 3)
-+
-+#define IPU_DC_NUM_CHANNELS   10
-+
-+struct ipu_dc_priv;
-+
-+enum ipu_dc_map {
-+      IPU_DC_MAP_RGB24,
-+      IPU_DC_MAP_RGB565,
-+      IPU_DC_MAP_GBR24, /* TVEv2 */
-+      IPU_DC_MAP_BGR666,
-+      IPU_DC_MAP_LVDS666,
-+      IPU_DC_MAP_BGR24,
-+};
-+
-+struct ipu_dc {
-+      /* The display interface number assigned to this dc channel */
-+      unsigned int            di;
-+      void __iomem            *base;
-+      struct ipu_dc_priv      *priv;
-+      int                     chno;
-+      bool                    in_use;
-+};
-+
-+struct ipu_dc_priv {
-+      void __iomem            *dc_reg;
-+      void __iomem            *dc_tmpl_reg;
-+      struct ipu_soc          *ipu;
-+      struct device           *dev;
-+      struct ipu_dc           channels[IPU_DC_NUM_CHANNELS];
-+      struct mutex            mutex;
-+      struct completion       comp;
-+      int                     use_count;
-+};
-+
-+static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
-+{
-+      u32 reg;
-+
-+      reg = readl(dc->base + DC_RL_CH(event));
-+      reg &= ~(0xffff << (16 * (event & 0x1)));
-+      reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
-+      writel(reg, dc->base + DC_RL_CH(event));
-+}
-+
-+static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
-+              int map, int wave, int glue, int sync, int stop)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+      u32 reg1, reg2;
-+
-+      if (opcode == WCLK) {
-+              reg1 = (operand << 20) & 0xfff00000;
-+              reg2 = operand >> 12 | opcode << 1 | stop << 9;
-+      } else if (opcode == WRG) {
-+              reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
-+              reg2 = operand >> 17 | opcode << 7 | stop << 9;
-+      } else {
-+              reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
-+              reg2 = operand >> 12 | opcode << 4 | stop << 9;
-+      }
-+      writel(reg1, priv->dc_tmpl_reg + word * 8);
-+      writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
-+}
-+
-+static int ipu_bus_format_to_map(u32 fmt)
-+{
-+      switch (fmt) {
-+      default:
-+              WARN_ON(1);
-+              /* fall-through */
-+      case MEDIA_BUS_FMT_RGB888_1X24:
-+              return IPU_DC_MAP_RGB24;
-+      case MEDIA_BUS_FMT_RGB565_1X16:
-+              return IPU_DC_MAP_RGB565;
-+      case MEDIA_BUS_FMT_GBR888_1X24:
-+              return IPU_DC_MAP_GBR24;
-+      case MEDIA_BUS_FMT_RGB666_1X18:
-+              return IPU_DC_MAP_BGR666;
-+      case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
-+              return IPU_DC_MAP_LVDS666;
-+      case MEDIA_BUS_FMT_BGR888_1X24:
-+              return IPU_DC_MAP_BGR24;
-+      }
-+}
-+
-+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
-+              u32 bus_format, u32 width)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+      int addr, sync;
-+      u32 reg = 0;
-+      int map;
-+
-+      dc->di = ipu_di_get_num(di);
-+
-+      map = ipu_bus_format_to_map(bus_format);
-+
-+      /*
-+       * In interlaced mode we need more counters to create the asymmetric
-+       * per-field VSYNC signals. The pixel active signal synchronising DC
-+       * to DI moves to signal generator #6 (see ipu-di.c). In progressive
-+       * mode counter #5 is used.
-+       */
-+      sync = interlaced ? 6 : 5;
-+
-+      /* Reserve 5 microcode template words for each DI */
-+      if (dc->di)
-+              addr = 5;
-+      else
-+              addr = 0;
-+
-+      if (interlaced) {
-+              dc_link_event(dc, DC_EVT_NL, addr, 3);
-+              dc_link_event(dc, DC_EVT_EOL, addr, 2);
-+              dc_link_event(dc, DC_EVT_NEW_DATA, addr, 1);
-+
-+              /* Init template microcode */
-+              dc_write_tmpl(dc, addr, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
-+      } else {
-+              dc_link_event(dc, DC_EVT_NL, addr + 2, 3);
-+              dc_link_event(dc, DC_EVT_EOL, addr + 3, 2);
-+              dc_link_event(dc, DC_EVT_NEW_DATA, addr + 1, 1);
-+
-+              /* Init template microcode */
-+              dc_write_tmpl(dc, addr + 2, WROD(0), 0, map, SYNC_WAVE, 8, sync, 1);
-+              dc_write_tmpl(dc, addr + 3, WROD(0), 0, map, SYNC_WAVE, 4, sync, 0);
-+              dc_write_tmpl(dc, addr + 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
-+              dc_write_tmpl(dc, addr + 1, WROD(0), 0, map, SYNC_WAVE, 0, sync, 1);
-+      }
-+
-+      dc_link_event(dc, DC_EVT_NF, 0, 0);
-+      dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
-+      dc_link_event(dc, DC_EVT_EOF, 0, 0);
-+      dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
-+      dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
-+      dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
-+
-+      reg = readl(dc->base + DC_WR_CH_CONF);
-+      if (interlaced)
-+              reg |= DC_WR_CH_CONF_FIELD_MODE;
-+      else
-+              reg &= ~DC_WR_CH_CONF_FIELD_MODE;
-+      writel(reg, dc->base + DC_WR_CH_CONF);
-+
-+      writel(0x0, dc->base + DC_WR_CH_ADDR);
-+      writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
-+
-+void ipu_dc_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_enable);
-+
-+void ipu_dc_enable_channel(struct ipu_dc *dc)
-+{
-+      u32 reg;
-+
-+      reg = readl(dc->base + DC_WR_CH_CONF);
-+      reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
-+      writel(reg, dc->base + DC_WR_CH_CONF);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
-+
-+void ipu_dc_disable_channel(struct ipu_dc *dc)
-+{
-+      u32 val;
-+
-+      val = readl(dc->base + DC_WR_CH_CONF);
-+      val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-+      writel(val, dc->base + DC_WR_CH_CONF);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
-+
-+void ipu_dc_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_disable);
-+
-+static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
-+              int byte_num, int offset, int mask)
-+{
-+      int ptr = map * 3 + byte_num;
-+      u32 reg;
-+
-+      reg = readl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-+      reg &= ~(0xffff << (16 * (ptr & 0x1)));
-+      reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
-+      writel(reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
-+
-+      reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-+      reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
-+      reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
-+      writel(reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
-+}
-+
-+static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
-+{
-+      u32 reg = readl(priv->dc_reg + DC_MAP_CONF_PTR(map));
-+
-+      writel(reg & ~(0xffff << (16 * (map & 0x1))),
-+                   priv->dc_reg + DC_MAP_CONF_PTR(map));
-+}
-+
-+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
-+{
-+      struct ipu_dc_priv *priv = ipu->dc_priv;
-+      struct ipu_dc *dc;
-+
-+      if (channel >= IPU_DC_NUM_CHANNELS)
-+              return ERR_PTR(-ENODEV);
-+
-+      dc = &priv->channels[channel];
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (dc->in_use) {
-+              mutex_unlock(&priv->mutex);
-+              return ERR_PTR(-EBUSY);
-+      }
-+
-+      dc->in_use = true;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return dc;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_get);
-+
-+void ipu_dc_put(struct ipu_dc *dc)
-+{
-+      struct ipu_dc_priv *priv = dc->priv;
-+
-+      mutex_lock(&priv->mutex);
-+      dc->in_use = false;
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_put);
-+
-+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long template_base)
-+{
-+      struct ipu_dc_priv *priv;
-+      static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
-+              0x78, 0, 0x94, 0xb4};
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      mutex_init(&priv->mutex);
-+
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+      priv->dc_reg = devm_ioremap(dev, base, PAGE_SIZE);
-+      priv->dc_tmpl_reg = devm_ioremap(dev, template_base, PAGE_SIZE);
-+      if (!priv->dc_reg || !priv->dc_tmpl_reg)
-+              return -ENOMEM;
-+
-+      for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
-+              priv->channels[i].chno = i;
-+              priv->channels[i].priv = priv;
-+              priv->channels[i].base = priv->dc_reg + channel_offsets[i];
-+      }
-+
-+      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
-+                      DC_WR_CH_CONF_PROG_DI_ID,
-+                      priv->channels[1].base + DC_WR_CH_CONF);
-+      writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
-+                      priv->channels[5].base + DC_WR_CH_CONF);
-+
-+      writel(DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1,
-+              priv->dc_reg + DC_GEN);
-+
-+      ipu->dc_priv = priv;
-+
-+      dev_dbg(dev, "DC base: 0x%08lx template base: 0x%08lx\n",
-+                      base, template_base);
-+
-+      /* rgb24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
-+
-+      /* rgb565 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
-+
-+      /* gbr24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
-+
-+      /* bgr666 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
-+
-+      /* lvds666 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_LVDS666);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 0, 5, 0xfc); /* blue */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 1, 13, 0xfc); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_LVDS666, 2, 21, 0xfc); /* red */
-+
-+      /* bgr24 */
-+      ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
-+      ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
-+
-+      return 0;
-+}
-+
-+void ipu_dc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-di.c
-@@ -0,0 +1,745 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/platform_device.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_di {
-+      void __iomem *base;
-+      int id;
-+      u32 module;
-+      struct clk *clk_di;     /* display input clock */
-+      struct clk *clk_ipu;    /* IPU bus clock */
-+      struct clk *clk_di_pixel; /* resulting pixel clock */
-+      bool inuse;
-+      struct ipu_soc *ipu;
-+};
-+
-+static DEFINE_MUTEX(di_mutex);
-+
-+struct di_sync_config {
-+      int run_count;
-+      int run_src;
-+      int offset_count;
-+      int offset_src;
-+      int repeat_count;
-+      int cnt_clr_src;
-+      int cnt_polarity_gen_en;
-+      int cnt_polarity_clr_src;
-+      int cnt_polarity_trigger_src;
-+      int cnt_up;
-+      int cnt_down;
-+};
-+
-+enum di_pins {
-+      DI_PIN11 = 0,
-+      DI_PIN12 = 1,
-+      DI_PIN13 = 2,
-+      DI_PIN14 = 3,
-+      DI_PIN15 = 4,
-+      DI_PIN16 = 5,
-+      DI_PIN17 = 6,
-+      DI_PIN_CS = 7,
-+
-+      DI_PIN_SER_CLK = 0,
-+      DI_PIN_SER_RS = 1,
-+};
-+
-+enum di_sync_wave {
-+      DI_SYNC_NONE = 0,
-+      DI_SYNC_CLK = 1,
-+      DI_SYNC_INT_HSYNC = 2,
-+      DI_SYNC_HSYNC = 3,
-+      DI_SYNC_VSYNC = 4,
-+      DI_SYNC_DE = 6,
-+
-+      DI_SYNC_CNT1 = 2,       /* counter >= 2 only */
-+      DI_SYNC_CNT4 = 5,       /* counter >= 5 only */
-+      DI_SYNC_CNT5 = 6,       /* counter >= 6 only */
-+};
-+
-+#define SYNC_WAVE 0
-+
-+#define DI_GENERAL            0x0000
-+#define DI_BS_CLKGEN0         0x0004
-+#define DI_BS_CLKGEN1         0x0008
-+#define DI_SW_GEN0(gen)               (0x000c + 4 * ((gen) - 1))
-+#define DI_SW_GEN1(gen)               (0x0030 + 4 * ((gen) - 1))
-+#define DI_STP_REP(gen)               (0x0148 + 4 * (((gen) - 1)/2))
-+#define DI_SYNC_AS_GEN                0x0054
-+#define DI_DW_GEN(gen)                (0x0058 + 4 * (gen))
-+#define DI_DW_SET(gen, set)   (0x0088 + 4 * ((gen) + 0xc * (set)))
-+#define DI_SER_CONF           0x015c
-+#define DI_SSC                        0x0160
-+#define DI_POL                        0x0164
-+#define DI_AW0                        0x0168
-+#define DI_AW1                        0x016c
-+#define DI_SCR_CONF           0x0170
-+#define DI_STAT                       0x0174
-+
-+#define DI_SW_GEN0_RUN_COUNT(x)                       ((x) << 19)
-+#define DI_SW_GEN0_RUN_SRC(x)                 ((x) << 16)
-+#define DI_SW_GEN0_OFFSET_COUNT(x)            ((x) << 3)
-+#define DI_SW_GEN0_OFFSET_SRC(x)              ((x) << 0)
-+
-+#define DI_SW_GEN1_CNT_POL_GEN_EN(x)          ((x) << 29)
-+#define DI_SW_GEN1_CNT_CLR_SRC(x)             ((x) << 25)
-+#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x)     ((x) << 12)
-+#define DI_SW_GEN1_CNT_POL_CLR_SRC(x)         ((x) << 9)
-+#define DI_SW_GEN1_CNT_DOWN(x)                        ((x) << 16)
-+#define DI_SW_GEN1_CNT_UP(x)                  (x)
-+#define DI_SW_GEN1_AUTO_RELOAD                        (0x10000000)
-+
-+#define DI_DW_GEN_ACCESS_SIZE_OFFSET          24
-+#define DI_DW_GEN_COMPONENT_SIZE_OFFSET               16
-+
-+#define DI_GEN_POLARITY_1                     (1 << 0)
-+#define DI_GEN_POLARITY_2                     (1 << 1)
-+#define DI_GEN_POLARITY_3                     (1 << 2)
-+#define DI_GEN_POLARITY_4                     (1 << 3)
-+#define DI_GEN_POLARITY_5                     (1 << 4)
-+#define DI_GEN_POLARITY_6                     (1 << 5)
-+#define DI_GEN_POLARITY_7                     (1 << 6)
-+#define DI_GEN_POLARITY_8                     (1 << 7)
-+#define DI_GEN_POLARITY_DISP_CLK              (1 << 17)
-+#define DI_GEN_DI_CLK_EXT                     (1 << 20)
-+#define DI_GEN_DI_VSYNC_EXT                   (1 << 21)
-+
-+#define DI_POL_DRDY_DATA_POLARITY             (1 << 7)
-+#define DI_POL_DRDY_POLARITY_15                       (1 << 4)
-+
-+#define DI_VSYNC_SEL_OFFSET                   13
-+
-+static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
-+{
-+      return readl(di->base + offset);
-+}
-+
-+static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
-+{
-+      writel(value, di->base + offset);
-+}
-+
-+static void ipu_di_data_wave_config(struct ipu_di *di,
-+                                   int wave_gen,
-+                                   int access_size, int component_size)
-+{
-+      u32 reg;
-+      reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
-+          (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
-+      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-+}
-+
-+static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
-+              int set, int up, int down)
-+{
-+      u32 reg;
-+
-+      reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
-+      reg &= ~(0x3 << (di_pin * 2));
-+      reg |= set << (di_pin * 2);
-+      ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
-+
-+      ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
-+}
-+
-+static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
-+              int start, int count)
-+{
-+      u32 reg;
-+      int i;
-+
-+      for (i = 0; i < count; i++) {
-+              struct di_sync_config *c = &config[i];
-+              int wave_gen = start + i + 1;
-+
-+              if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
-+                              (c->repeat_count >= 0x1000) ||
-+                              (c->cnt_up >= 0x400) ||
-+                              (c->cnt_down >= 0x400)) {
-+                      dev_err(di->ipu->dev, "DI%d counters out of range.\n",
-+                                      di->id);
-+                      return;
-+              }
-+
-+              reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
-+                      DI_SW_GEN0_RUN_SRC(c->run_src) |
-+                      DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
-+                      DI_SW_GEN0_OFFSET_SRC(c->offset_src);
-+              ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
-+
-+              reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
-+                      DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
-+                      DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
-+                                      c->cnt_polarity_trigger_src) |
-+                      DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
-+                      DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
-+                      DI_SW_GEN1_CNT_UP(c->cnt_up);
-+
-+              /* Enable auto reload */
-+              if (c->repeat_count == 0)
-+                      reg |= DI_SW_GEN1_AUTO_RELOAD;
-+
-+              ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
-+
-+              reg = ipu_di_read(di, DI_STP_REP(wave_gen));
-+              reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
-+              reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
-+              ipu_di_write(di, reg, DI_STP_REP(wave_gen));
-+      }
-+}
-+
-+static void ipu_di_sync_config_interlaced(struct ipu_di *di,
-+              struct ipu_di_signal_cfg *sig)
-+{
-+      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
-+              sig->mode.hback_porch + sig->mode.hfront_porch;
-+      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
-+              sig->mode.vback_porch + sig->mode.vfront_porch;
-+      struct di_sync_config cfg[] = {
-+              {
-+                      /* 1: internal VSYNC for each frame */
-+                      .run_count = v_total * 2 - 1,
-+                      .run_src = 3,                   /* == counter 7 */
-+              }, {
-+                      /* PIN2: HSYNC waveform */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              }, {
-+                      /* PIN3: VSYNC waveform */
-+                      .run_count = v_total - 1,
-+                      .run_src = 4,                   /* == counter 7 */
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = 4,  /* == counter 7 */
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+                      .cnt_clr_src = DI_SYNC_CNT1,
-+              }, {
-+                      /* 4: Field */
-+                      .run_count = v_total / 2,
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = h_total / 2,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = 2,
-+                      .cnt_clr_src = DI_SYNC_CNT1,
-+              }, {
-+                      /* 5: Active lines */
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = (sig->mode.vsync_len +
-+                                       sig->mode.vback_porch) / 2,
-+                      .offset_src = DI_SYNC_HSYNC,
-+                      .repeat_count = sig->mode.vactive / 2,
-+                      .cnt_clr_src = DI_SYNC_CNT4,
-+              }, {
-+                      /* 6: Active pixel, referenced by DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = DI_SYNC_CNT5,
-+              }, {
-+                      /* 7: Half line HSYNC */
-+                      .run_count = h_total / 2 - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              }
-+      };
-+
-+      ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-+
-+      ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
-+}
-+
-+static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
-+              struct ipu_di_signal_cfg *sig, int div)
-+{
-+      u32 h_total = sig->mode.hactive + sig->mode.hsync_len +
-+              sig->mode.hback_porch + sig->mode.hfront_porch;
-+      u32 v_total = sig->mode.vactive + sig->mode.vsync_len +
-+              sig->mode.vback_porch + sig->mode.vfront_porch;
-+      struct di_sync_config cfg[] = {
-+              {
-+                      /* 1: INT_HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              } , {
-+                      /* PIN2: HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* PIN3: VSYNC */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* 4: Line Active */
-+                      .run_src = DI_SYNC_HSYNC,
-+                      .offset_count = sig->mode.vsync_len +
-+                                      sig->mode.vback_porch,
-+                      .offset_src = DI_SYNC_HSYNC,
-+                      .repeat_count = sig->mode.vactive,
-+                      .cnt_clr_src = DI_SYNC_VSYNC,
-+              } , {
-+                      /* 5: Pixel Active, referenced by DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = 5, /* Line Active */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              } , {
-+                      /* unused */
-+              },
-+      };
-+      /* can't use #7 and #8 for line active and pixel active counters */
-+      struct di_sync_config cfg_vga[] = {
-+              {
-+                      /* 1: INT_HSYNC */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+              } , {
-+                      /* 2: VSYNC */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+              } , {
-+                      /* 3: Line Active */
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = sig->mode.vsync_len +
-+                                      sig->mode.vback_porch,
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .repeat_count = sig->mode.vactive,
-+                      .cnt_clr_src = 3 /* VSYNC */,
-+              } , {
-+                      /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* 5: Pixel Active signal to DC */
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = sig->mode.hsync_len +
-+                                      sig->mode.hback_porch,
-+                      .offset_src = DI_SYNC_CLK,
-+                      .repeat_count = sig->mode.hactive,
-+                      .cnt_clr_src = 4, /* Line Active */
-+              } , {
-+                      /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = 1, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
-+                      .run_count = h_total - 1,
-+                      .run_src = DI_SYNC_CLK,
-+                      .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_CLK,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_CLK,
-+                      .cnt_down = sig->mode.hsync_len * 2,
-+              } , {
-+                      /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
-+                      .run_count = v_total - 1,
-+                      .run_src = DI_SYNC_INT_HSYNC,
-+                      .offset_count = 1, /* magic value from Freescale TVE driver */
-+                      .offset_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_polarity_gen_en = 1,
-+                      .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-+                      .cnt_down = sig->mode.vsync_len * 2,
-+              } , {
-+                      /* unused */
-+              },
-+      };
-+
-+      ipu_di_write(di, v_total - 1, DI_SCR_CONF);
-+      if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
-+              ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
-+      else
-+              ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
-+}
-+
-+static void ipu_di_config_clock(struct ipu_di *di,
-+      const struct ipu_di_signal_cfg *sig)
-+{
-+      struct clk *clk;
-+      unsigned clkgen0;
-+      uint32_t val;
-+
-+      if (sig->clkflags & IPU_DI_CLKMODE_EXT) {
-+              /*
-+               * CLKMODE_EXT means we must use the DI clock: this is
-+               * needed for things like LVDS which needs to feed the
-+               * DI and LDB with the same pixel clock.
-+               */
-+              clk = di->clk_di;
-+
-+              if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
-+                      /*
-+                       * CLKMODE_SYNC means that we want the DI to be
-+                       * clocked at the same rate as the parent clock.
-+                       * This is needed (eg) for LDB which needs to be
-+                       * fed with the same pixel clock.  We assume that
-+                       * the LDB clock has already been set correctly.
-+                       */
-+                      clkgen0 = 1 << 4;
-+              } else {
-+                      /*
-+                       * We can use the divider.  We should really have
-+                       * a flag here indicating whether the bridge can
-+                       * cope with a fractional divider or not.  For the
-+                       * time being, let's go for simplicitly and
-+                       * reliability.
-+                       */
-+                      unsigned long in_rate;
-+                      unsigned div;
-+
-+                      clk_set_rate(clk, sig->mode.pixelclock);
-+
-+                      in_rate = clk_get_rate(clk);
-+                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
-+                      div = clamp(div, 1U, 255U);
-+
-+                      clkgen0 = div << 4;
-+              }
-+      } else {
-+              /*
-+               * For other interfaces, we can arbitarily select between
-+               * the DI specific clock and the internal IPU clock.  See
-+               * DI_GENERAL bit 20.  We select the IPU clock if it can
-+               * give us a clock rate within 1% of the requested frequency,
-+               * otherwise we use the DI clock.
-+               */
-+              unsigned long rate, clkrate;
-+              unsigned div, error;
-+
-+              clkrate = clk_get_rate(di->clk_ipu);
-+              div = DIV_ROUND_CLOSEST(clkrate, sig->mode.pixelclock);
-+              div = clamp(div, 1U, 255U);
-+              rate = clkrate / div;
-+
-+              error = rate / (sig->mode.pixelclock / 1000);
-+
-+              dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
-+                      rate, div, (signed)(error - 1000) / 10, error % 10);
-+
-+              /* Allow a 1% error */
-+              if (error < 1010 && error >= 990) {
-+                      clk = di->clk_ipu;
-+
-+                      clkgen0 = div << 4;
-+              } else {
-+                      unsigned long in_rate;
-+                      unsigned div;
-+
-+                      clk = di->clk_di;
-+
-+                      clk_set_rate(clk, sig->mode.pixelclock);
-+
-+                      in_rate = clk_get_rate(clk);
-+                      div = DIV_ROUND_CLOSEST(in_rate, sig->mode.pixelclock);
-+                      div = clamp(div, 1U, 255U);
-+
-+                      clkgen0 = div << 4;
-+              }
-+      }
-+
-+      di->clk_di_pixel = clk;
-+
-+      /* Set the divider */
-+      ipu_di_write(di, clkgen0, DI_BS_CLKGEN0);
-+
-+      /*
-+       * Set the high/low periods.  Bits 24:16 give us the falling edge,
-+       * and bits 8:0 give the rising edge.  LSB is fraction, and is
-+       * based on the divider above.  We want a 50% duty cycle, so set
-+       * the falling edge to be half the divider.
-+       */
-+      ipu_di_write(di, (clkgen0 >> 4) << 16, DI_BS_CLKGEN1);
-+
-+      /* Finally select the input clock */
-+      val = ipu_di_read(di, DI_GENERAL) & ~DI_GEN_DI_CLK_EXT;
-+      if (clk == di->clk_di)
-+              val |= DI_GEN_DI_CLK_EXT;
-+      ipu_di_write(di, val, DI_GENERAL);
-+
-+      dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
-+              sig->mode.pixelclock,
-+              clk_get_rate(di->clk_ipu),
-+              clk_get_rate(di->clk_di),
-+              clk == di->clk_di ? "DI" : "IPU",
-+              clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
-+}
-+
-+/*
-+ * This function is called to adjust a video mode to IPU restrictions.
-+ * It is meant to be called from drm crtc mode_fixup() methods.
-+ */
-+int ipu_di_adjust_videomode(struct ipu_di *di, struct videomode *mode)
-+{
-+      u32 diff;
-+
-+      if (mode->vfront_porch >= 2)
-+              return 0;
-+
-+      diff = 2 - mode->vfront_porch;
-+
-+      if (mode->vback_porch >= diff) {
-+              mode->vfront_porch = 2;
-+              mode->vback_porch -= diff;
-+      } else if (mode->vsync_len > diff) {
-+              mode->vfront_porch = 2;
-+              mode->vsync_len = mode->vsync_len - diff;
-+      } else {
-+              dev_warn(di->ipu->dev, "failed to adjust videomode\n");
-+              return -EINVAL;
-+      }
-+
-+      dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
-+
-+static u32 ipu_di_gen_polarity(int pin)
-+{
-+      switch (pin) {
-+      case 1:
-+              return DI_GEN_POLARITY_1;
-+      case 2:
-+              return DI_GEN_POLARITY_2;
-+      case 3:
-+              return DI_GEN_POLARITY_3;
-+      case 4:
-+              return DI_GEN_POLARITY_4;
-+      case 5:
-+              return DI_GEN_POLARITY_5;
-+      case 6:
-+              return DI_GEN_POLARITY_6;
-+      case 7:
-+              return DI_GEN_POLARITY_7;
-+      case 8:
-+              return DI_GEN_POLARITY_8;
-+      }
-+      return 0;
-+}
-+
-+int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
-+{
-+      u32 reg;
-+      u32 di_gen, vsync_cnt;
-+      u32 div;
-+
-+      dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
-+              di->id, sig->mode.hactive, sig->mode.vactive);
-+
-+      dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
-+              clk_get_rate(di->clk_ipu),
-+              clk_get_rate(di->clk_di),
-+              sig->mode.pixelclock);
-+
-+      mutex_lock(&di_mutex);
-+
-+      ipu_di_config_clock(di, sig);
-+
-+      div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
-+      div = div / 16;         /* Now divider is integer portion */
-+
-+      /* Setup pixel clock timing */
-+      /* Down time is half of period */
-+      ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
-+
-+      ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
-+      ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
-+
-+      di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
-+      di_gen |= DI_GEN_DI_VSYNC_EXT;
-+
-+      if (sig->mode.flags & DISPLAY_FLAGS_INTERLACED) {
-+              ipu_di_sync_config_interlaced(di, sig);
-+
-+              /* set y_sel = 1 */
-+              di_gen |= 0x10000000;
-+
-+              vsync_cnt = 3;
-+      } else {
-+              ipu_di_sync_config_noninterlaced(di, sig, div);
-+
-+              vsync_cnt = 3;
-+              if (di->id == 1)
-+                      /*
-+                       * TODO: change only for TVEv2, parallel display
-+                       * uses pin 2 / 3
-+                       */
-+                      if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
-+                              vsync_cnt = 6;
-+      }
-+
-+      if (sig->mode.flags & DISPLAY_FLAGS_HSYNC_HIGH)
-+              di_gen |= ipu_di_gen_polarity(sig->hsync_pin);
-+      if (sig->mode.flags & DISPLAY_FLAGS_VSYNC_HIGH)
-+              di_gen |= ipu_di_gen_polarity(sig->vsync_pin);
-+
-+      if (sig->clk_pol)
-+              di_gen |= DI_GEN_POLARITY_DISP_CLK;
-+
-+      ipu_di_write(di, di_gen, DI_GENERAL);
-+
-+      ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
-+                   DI_SYNC_AS_GEN);
-+
-+      reg = ipu_di_read(di, DI_POL);
-+      reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
-+
-+      if (sig->enable_pol)
-+              reg |= DI_POL_DRDY_POLARITY_15;
-+      if (sig->data_pol)
-+              reg |= DI_POL_DRDY_DATA_POLARITY;
-+
-+      ipu_di_write(di, reg, DI_POL);
-+
-+      mutex_unlock(&di_mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
-+
-+int ipu_di_enable(struct ipu_di *di)
-+{
-+      int ret;
-+
-+      WARN_ON(IS_ERR(di->clk_di_pixel));
-+
-+      ret = clk_prepare_enable(di->clk_di_pixel);
-+      if (ret)
-+              return ret;
-+
-+      ipu_module_enable(di->ipu, di->module);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_enable);
-+
-+int ipu_di_disable(struct ipu_di *di)
-+{
-+      WARN_ON(IS_ERR(di->clk_di_pixel));
-+
-+      ipu_module_disable(di->ipu, di->module);
-+
-+      clk_disable_unprepare(di->clk_di_pixel);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_disable);
-+
-+int ipu_di_get_num(struct ipu_di *di)
-+{
-+      return di->id;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_get_num);
-+
-+static DEFINE_MUTEX(ipu_di_lock);
-+
-+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
-+{
-+      struct ipu_di *di;
-+
-+      if (disp > 1)
-+              return ERR_PTR(-EINVAL);
-+
-+      di = ipu->di_priv[disp];
-+
-+      mutex_lock(&ipu_di_lock);
-+
-+      if (di->inuse) {
-+              di = ERR_PTR(-EBUSY);
-+              goto out;
-+      }
-+
-+      di->inuse = true;
-+out:
-+      mutex_unlock(&ipu_di_lock);
-+
-+      return di;
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_get);
-+
-+void ipu_di_put(struct ipu_di *di)
-+{
-+      mutex_lock(&ipu_di_lock);
-+
-+      di->inuse = false;
-+
-+      mutex_unlock(&ipu_di_lock);
-+}
-+EXPORT_SYMBOL_GPL(ipu_di_put);
-+
-+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-+              unsigned long base,
-+              u32 module, struct clk *clk_ipu)
-+{
-+      struct ipu_di *di;
-+
-+      if (id > 1)
-+              return -ENODEV;
-+
-+      di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
-+      if (!di)
-+              return -ENOMEM;
-+
-+      ipu->di_priv[id] = di;
-+
-+      di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
-+      if (IS_ERR(di->clk_di))
-+              return PTR_ERR(di->clk_di);
-+
-+      di->module = module;
-+      di->id = id;
-+      di->clk_ipu = clk_ipu;
-+      di->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!di->base)
-+              return -ENOMEM;
-+
-+      ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
-+
-+      dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
-+                      id, base, di->base);
-+      di->inuse = false;
-+      di->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_di_exit(struct ipu_soc *ipu, int id)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
-@@ -0,0 +1,214 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DMFC_RD_CHAN          0x0000
-+#define DMFC_WR_CHAN          0x0004
-+#define DMFC_WR_CHAN_DEF      0x0008
-+#define DMFC_DP_CHAN          0x000c
-+#define DMFC_DP_CHAN_DEF      0x0010
-+#define DMFC_GENERAL1         0x0014
-+#define DMFC_GENERAL2         0x0018
-+#define DMFC_IC_CTRL          0x001c
-+#define DMFC_WR_CHAN_ALT      0x0020
-+#define DMFC_WR_CHAN_DEF_ALT  0x0024
-+#define DMFC_DP_CHAN_ALT      0x0028
-+#define DMFC_DP_CHAN_DEF_ALT  0x002c
-+#define DMFC_GENERAL1_ALT     0x0030
-+#define DMFC_STAT             0x0034
-+
-+#define DMFC_WR_CHAN_1_28             0
-+#define DMFC_WR_CHAN_2_41             8
-+#define DMFC_WR_CHAN_1C_42            16
-+#define DMFC_WR_CHAN_2C_43            24
-+
-+#define DMFC_DP_CHAN_5B_23            0
-+#define DMFC_DP_CHAN_5F_27            8
-+#define DMFC_DP_CHAN_6B_24            16
-+#define DMFC_DP_CHAN_6F_29            24
-+
-+struct dmfc_channel_data {
-+      int             ipu_channel;
-+      unsigned long   channel_reg;
-+      unsigned long   shift;
-+      unsigned        eot_shift;
-+      unsigned        max_fifo_lines;
-+};
-+
-+static const struct dmfc_channel_data dmfcdata[] = {
-+      {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_BG_SYNC,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_5B_23,
-+              .eot_shift      = 20,
-+              .max_fifo_lines = 3,
-+      }, {
-+              .ipu_channel    = 24,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_6B_24,
-+              .eot_shift      = 22,
-+              .max_fifo_lines = 1,
-+      }, {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_FG_SYNC,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_5F_27,
-+              .eot_shift      = 21,
-+              .max_fifo_lines = 2,
-+      }, {
-+              .ipu_channel    = IPUV3_CHANNEL_MEM_DC_SYNC,
-+              .channel_reg    = DMFC_WR_CHAN,
-+              .shift          = DMFC_WR_CHAN_1_28,
-+              .eot_shift      = 16,
-+              .max_fifo_lines = 2,
-+      }, {
-+              .ipu_channel    = 29,
-+              .channel_reg    = DMFC_DP_CHAN,
-+              .shift          = DMFC_DP_CHAN_6F_29,
-+              .eot_shift      = 23,
-+              .max_fifo_lines = 1,
-+      },
-+};
-+
-+#define DMFC_NUM_CHANNELS     ARRAY_SIZE(dmfcdata)
-+
-+struct ipu_dmfc_priv;
-+
-+struct dmfc_channel {
-+      unsigned                        slots;
-+      struct ipu_soc                  *ipu;
-+      struct ipu_dmfc_priv            *priv;
-+      const struct dmfc_channel_data  *data;
-+};
-+
-+struct ipu_dmfc_priv {
-+      struct ipu_soc *ipu;
-+      struct device *dev;
-+      struct dmfc_channel channels[DMFC_NUM_CHANNELS];
-+      struct mutex mutex;
-+      void __iomem *base;
-+      int use_count;
-+};
-+
-+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
-+
-+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
-+
-+void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
-+{
-+      struct ipu_dmfc_priv *priv = dmfc->priv;
-+      u32 dmfc_gen1;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
-+
-+      if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
-+              dmfc_gen1 |= 1 << dmfc->data->eot_shift;
-+      else
-+              dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
-+
-+      writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
-+
-+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
-+{
-+      struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
-+      int i;
-+
-+      for (i = 0; i < DMFC_NUM_CHANNELS; i++)
-+              if (dmfcdata[i].ipu_channel == ipu_channel)
-+                      return &priv->channels[i];
-+      return ERR_PTR(-ENODEV);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_get);
-+
-+void ipu_dmfc_put(struct dmfc_channel *dmfc)
-+{
-+}
-+EXPORT_SYMBOL_GPL(ipu_dmfc_put);
-+
-+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              struct clk *ipu_clk)
-+{
-+      struct ipu_dmfc_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+      mutex_init(&priv->mutex);
-+
-+      ipu->dmfc_priv = priv;
-+
-+      for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
-+              priv->channels[i].priv = priv;
-+              priv->channels[i].ipu = ipu;
-+              priv->channels[i].data = &dmfcdata[i];
-+
-+              if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
-+                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
-+                  dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
-+                      priv->channels[i].slots = 2;
-+      }
-+
-+      writel(0x00000050, priv->base + DMFC_WR_CHAN);
-+      writel(0x00005654, priv->base + DMFC_DP_CHAN);
-+      writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
-+      writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
-+      writel(0x00000003, priv->base + DMFC_GENERAL1);
-+
-+      return 0;
-+}
-+
-+void ipu_dmfc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-dp.c
-@@ -0,0 +1,357 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/errno.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+
-+#include <video/imx-ipu-v3.h>
-+#include "ipu-prv.h"
-+
-+#define DP_SYNC 0
-+#define DP_ASYNC0 0x60
-+#define DP_ASYNC1 0xBC
-+
-+#define DP_COM_CONF           0x0
-+#define DP_GRAPH_WIND_CTRL    0x0004
-+#define DP_FG_POS             0x0008
-+#define DP_CSC_A_0            0x0044
-+#define DP_CSC_A_1            0x0048
-+#define DP_CSC_A_2            0x004C
-+#define DP_CSC_A_3            0x0050
-+#define DP_CSC_0              0x0054
-+#define DP_CSC_1              0x0058
-+
-+#define DP_COM_CONF_FG_EN             (1 << 0)
-+#define DP_COM_CONF_GWSEL             (1 << 1)
-+#define DP_COM_CONF_GWAM              (1 << 2)
-+#define DP_COM_CONF_GWCKE             (1 << 3)
-+#define DP_COM_CONF_CSC_DEF_MASK      (3 << 8)
-+#define DP_COM_CONF_CSC_DEF_OFFSET    8
-+#define DP_COM_CONF_CSC_DEF_FG                (3 << 8)
-+#define DP_COM_CONF_CSC_DEF_BG                (2 << 8)
-+#define DP_COM_CONF_CSC_DEF_BOTH      (1 << 8)
-+
-+#define IPUV3_NUM_FLOWS               3
-+
-+struct ipu_dp_priv;
-+
-+struct ipu_dp {
-+      u32 flow;
-+      bool in_use;
-+      bool foreground;
-+      enum ipu_color_space in_cs;
-+};
-+
-+struct ipu_flow {
-+      struct ipu_dp foreground;
-+      struct ipu_dp background;
-+      enum ipu_color_space out_cs;
-+      void __iomem *base;
-+      struct ipu_dp_priv *priv;
-+};
-+
-+struct ipu_dp_priv {
-+      struct ipu_soc *ipu;
-+      struct device *dev;
-+      void __iomem *base;
-+      struct ipu_flow flow[IPUV3_NUM_FLOWS];
-+      struct mutex mutex;
-+      int use_count;
-+};
-+
-+static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
-+
-+static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
-+{
-+      if (dp->foreground)
-+              return container_of(dp, struct ipu_flow, foreground);
-+      else
-+              return container_of(dp, struct ipu_flow, background);
-+}
-+
-+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
-+              u8 alpha, bool bg_chan)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      if (bg_chan)
-+              reg &= ~DP_COM_CONF_GWSEL;
-+      else
-+              reg |= DP_COM_CONF_GWSEL;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      if (enable) {
-+              reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
-+              writel(reg | ((u32) alpha << 24),
-+                           flow->base + DP_GRAPH_WIND_CTRL);
-+
-+              reg = readl(flow->base + DP_COM_CONF);
-+              writel(reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-+      } else {
-+              reg = readl(flow->base + DP_COM_CONF);
-+              writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
-+      }
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
-+
-+int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+
-+      writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS);
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
-+
-+static void ipu_dp_csc_init(struct ipu_flow *flow,
-+              enum ipu_color_space in,
-+              enum ipu_color_space out,
-+              u32 place)
-+{
-+      u32 reg;
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-+
-+      if (in == out) {
-+              writel(reg, flow->base + DP_COM_CONF);
-+              return;
-+      }
-+
-+      if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
-+              writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
-+              writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
-+              writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
-+              writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
-+              writel(0x3d6 | (0x0000 << 16) | (2 << 30),
-+                              flow->base + DP_CSC_0);
-+              writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
-+                              flow->base + DP_CSC_1);
-+      } else {
-+              writel(0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
-+              writel(0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
-+              writel(0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
-+              writel(0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
-+              writel(0x000 | (0x3e42 << 16) | (1 << 30),
-+                              flow->base + DP_CSC_0);
-+              writel(0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
-+                              flow->base + DP_CSC_1);
-+      }
-+
-+      reg |= place;
-+
-+      writel(reg, flow->base + DP_COM_CONF);
-+}
-+
-+int ipu_dp_setup_channel(struct ipu_dp *dp,
-+              enum ipu_color_space in,
-+              enum ipu_color_space out)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      dp->in_cs = in;
-+
-+      if (!dp->foreground)
-+              flow->out_cs = out;
-+
-+      if (flow->foreground.in_cs == flow->background.in_cs) {
-+              /*
-+               * foreground and background are of same colorspace, put
-+               * colorspace converter after combining unit.
-+               */
-+              ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
-+                              DP_COM_CONF_CSC_DEF_BOTH);
-+      } else {
-+              if (flow->foreground.in_cs == IPUV3_COLORSPACE_UNKNOWN ||
-+                  flow->foreground.in_cs == flow->out_cs)
-+                      /*
-+                       * foreground identical to output, apply color
-+                       * conversion on background
-+                       */
-+                      ipu_dp_csc_init(flow, flow->background.in_cs,
-+                                      flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
-+              else
-+                      ipu_dp_csc_init(flow, flow->foreground.in_cs,
-+                                      flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
-+      }
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
-+
-+int ipu_dp_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
-+
-+      priv->use_count++;
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_enable);
-+
-+int ipu_dp_enable_channel(struct ipu_dp *dp)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg;
-+
-+      if (!dp->foreground)
-+              return 0;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      reg |= DP_COM_CONF_FG_EN;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      ipu_srm_dp_update(priv->ipu, true);
-+
-+      mutex_unlock(&priv->mutex);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
-+
-+void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync)
-+{
-+      struct ipu_flow *flow = to_flow(dp);
-+      struct ipu_dp_priv *priv = flow->priv;
-+      u32 reg, csc;
-+
-+      dp->in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+
-+      if (!dp->foreground)
-+              return;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      reg = readl(flow->base + DP_COM_CONF);
-+      csc = reg & DP_COM_CONF_CSC_DEF_MASK;
-+      reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-+      if (csc == DP_COM_CONF_CSC_DEF_BOTH || csc == DP_COM_CONF_CSC_DEF_BG)
-+              reg |= DP_COM_CONF_CSC_DEF_BG;
-+
-+      reg &= ~DP_COM_CONF_FG_EN;
-+      writel(reg, flow->base + DP_COM_CONF);
-+
-+      writel(0, flow->base + DP_FG_POS);
-+      ipu_srm_dp_update(priv->ipu, sync);
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
-+
-+void ipu_dp_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+
-+      mutex_lock(&priv->mutex);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_disable);
-+
-+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
-+{
-+      struct ipu_dp_priv *priv = ipu->dp_priv;
-+      struct ipu_dp *dp;
-+
-+      if ((flow >> 1) >= IPUV3_NUM_FLOWS)
-+              return ERR_PTR(-EINVAL);
-+
-+      if (flow & 1)
-+              dp = &priv->flow[flow >> 1].foreground;
-+      else
-+              dp = &priv->flow[flow >> 1].background;
-+
-+      if (dp->in_use)
-+              return ERR_PTR(-EBUSY);
-+
-+      dp->in_use = true;
-+
-+      return dp;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_get);
-+
-+void ipu_dp_put(struct ipu_dp *dp)
-+{
-+      dp->in_use = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_put);
-+
-+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base)
-+{
-+      struct ipu_dp_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+      priv->dev = dev;
-+      priv->ipu = ipu;
-+
-+      ipu->dp_priv = priv;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      mutex_init(&priv->mutex);
-+
-+      for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
-+              priv->flow[i].background.in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+              priv->flow[i].foreground.in_cs = IPUV3_COLORSPACE_UNKNOWN;
-+              priv->flow[i].foreground.foreground = true;
-+              priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
-+              priv->flow[i].priv = priv;
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_dp_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-ic.c
-@@ -0,0 +1,761 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2014 Mentor Graphics Inc.
-+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/spinlock.h>
-+#include <linux/bitrev.h>
-+#include <linux/io.h>
-+#include <linux/err.h>
-+#include <linux/sizes.h>
-+#include "ipu-prv.h"
-+
-+/* IC Register Offsets */
-+#define IC_CONF                 0x0000
-+#define IC_PRP_ENC_RSC          0x0004
-+#define IC_PRP_VF_RSC           0x0008
-+#define IC_PP_RSC               0x000C
-+#define IC_CMBP_1               0x0010
-+#define IC_CMBP_2               0x0014
-+#define IC_IDMAC_1              0x0018
-+#define IC_IDMAC_2              0x001C
-+#define IC_IDMAC_3              0x0020
-+#define IC_IDMAC_4              0x0024
-+
-+/* IC Register Fields */
-+#define IC_CONF_PRPENC_EN       (1 << 0)
-+#define IC_CONF_PRPENC_CSC1     (1 << 1)
-+#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
-+#define IC_CONF_PRPVF_EN        (1 << 8)
-+#define IC_CONF_PRPVF_CSC1      (1 << 9)
-+#define IC_CONF_PRPVF_CSC2      (1 << 10)
-+#define IC_CONF_PRPVF_CMB       (1 << 11)
-+#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
-+#define IC_CONF_PP_EN           (1 << 16)
-+#define IC_CONF_PP_CSC1         (1 << 17)
-+#define IC_CONF_PP_CSC2         (1 << 18)
-+#define IC_CONF_PP_CMB          (1 << 19)
-+#define IC_CONF_PP_ROT_EN       (1 << 20)
-+#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
-+#define IC_CONF_KEY_COLOR_EN    (1 << 29)
-+#define IC_CONF_RWS_EN          (1 << 30)
-+#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
-+
-+#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
-+#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
-+#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
-+#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
-+#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
-+#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
-+#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
-+#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
-+#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
-+#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
-+#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
-+#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
-+#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
-+#define IC_IDMAC_1_PP_ROT_OFFSET        17
-+#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
-+#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
-+#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
-+
-+#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
-+#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
-+#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
-+#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
-+#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
-+#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
-+
-+#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
-+#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
-+#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
-+#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
-+#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
-+#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
-+
-+struct ic_task_regoffs {
-+      u32 rsc;
-+      u32 tpmem_csc[2];
-+};
-+
-+struct ic_task_bitfields {
-+      u32 ic_conf_en;
-+      u32 ic_conf_rot_en;
-+      u32 ic_conf_cmb_en;
-+      u32 ic_conf_csc1_en;
-+      u32 ic_conf_csc2_en;
-+      u32 ic_cmb_galpha_bit;
-+};
-+
-+static const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
-+      [IC_TASK_ENCODER] = {
-+              .rsc = IC_PRP_ENC_RSC,
-+              .tpmem_csc = {0x2008, 0},
-+      },
-+      [IC_TASK_VIEWFINDER] = {
-+              .rsc = IC_PRP_VF_RSC,
-+              .tpmem_csc = {0x4028, 0x4040},
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .rsc = IC_PP_RSC,
-+              .tpmem_csc = {0x6060, 0x6078},
-+      },
-+};
-+
-+static const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
-+      [IC_TASK_ENCODER] = {
-+              .ic_conf_en = IC_CONF_PRPENC_EN,
-+              .ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
-+              .ic_conf_cmb_en = 0,    /* NA */
-+              .ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
-+              .ic_conf_csc2_en = 0,   /* NA */
-+              .ic_cmb_galpha_bit = 0, /* NA */
-+      },
-+      [IC_TASK_VIEWFINDER] = {
-+              .ic_conf_en = IC_CONF_PRPVF_EN,
-+              .ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
-+              .ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
-+              .ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
-+              .ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
-+              .ic_cmb_galpha_bit = 0,
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .ic_conf_en = IC_CONF_PP_EN,
-+              .ic_conf_rot_en = IC_CONF_PP_ROT_EN,
-+              .ic_conf_cmb_en = IC_CONF_PP_CMB,
-+              .ic_conf_csc1_en = IC_CONF_PP_CSC1,
-+              .ic_conf_csc2_en = IC_CONF_PP_CSC2,
-+              .ic_cmb_galpha_bit = 8,
-+      },
-+};
-+
-+struct ipu_ic_priv;
-+
-+struct ipu_ic {
-+      enum ipu_ic_task task;
-+      const struct ic_task_regoffs *reg;
-+      const struct ic_task_bitfields *bit;
-+
-+      struct ipu_ic_colorspace in_cs;
-+      struct ipu_ic_colorspace g_in_cs;
-+      struct ipu_ic_colorspace out_cs;
-+
-+      bool graphics;
-+      bool rotation;
-+      bool in_use;
-+
-+      struct ipu_ic_priv *priv;
-+};
-+
-+struct ipu_ic_priv {
-+      void __iomem *base;
-+      void __iomem *tpmem_base;
-+      spinlock_t lock;
-+      struct ipu_soc *ipu;
-+      int use_count;
-+      int irt_use_count;
-+      struct ipu_ic task[IC_NUM_TASKS];
-+};
-+
-+static inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
-+{
-+      return readl(ic->priv->base + offset);
-+}
-+
-+static inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
-+{
-+      writel(value, ic->priv->base + offset);
-+}
-+
-+static int init_csc(struct ipu_ic *ic,
-+                  const struct ipu_ic_csc *csc,
-+                  int csc_index)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      u32 __iomem *base;
-+      const u16 (*c)[3];
-+      const u16 *a;
-+      u32 param;
-+
-+      base = (u32 __iomem *)
-+              (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
-+
-+      /* Cast to unsigned */
-+      c = (const u16 (*)[3])csc->params.coeff;
-+      a = (const u16 *)csc->params.offset;
-+
-+      param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
-+              ((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
-+              (csc->params.sat << 10);
-+      writel(param, base++);
-+
-+      param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
-+              ((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[1] & 0x1fe0) >> 5);
-+      writel(param, base++);
-+
-+      param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
-+              ((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
-+      writel(param, base++);
-+
-+      param = ((a[2] & 0x1fe0) >> 5);
-+      writel(param, base++);
-+
-+      return 0;
-+}
-+
-+static int calc_resize_coeffs(struct ipu_ic *ic,
-+                            u32 in_size, u32 out_size,
-+                            u32 *resize_coeff,
-+                            u32 *downsize_coeff)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+      u32 temp_size, temp_downsize;
-+
-+      /*
-+       * Input size cannot be more than 4096, and output size cannot
-+       * be more than 1024
-+       */
-+      if (in_size > 4096) {
-+              dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
-+              return -EINVAL;
-+      }
-+      if (out_size > 1024) {
-+              dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Cannot downsize more than 4:1 */
-+      if ((out_size << 2) < in_size) {
-+              dev_err(ipu->dev, "Unsupported downsize\n");
-+              return -EINVAL;
-+      }
-+
-+      /* Compute downsizing coefficient */
-+      temp_downsize = 0;
-+      temp_size = in_size;
-+      while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
-+             (temp_downsize < 2)) {
-+              temp_size >>= 1;
-+              temp_downsize++;
-+      }
-+      *downsize_coeff = temp_downsize;
-+
-+      /*
-+       * compute resizing coefficient using the following equation:
-+       * resize_coeff = M * (SI - 1) / (SO - 1)
-+       * where M = 2^13, SI = input size, SO = output size
-+       */
-+      *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
-+      if (*resize_coeff >= 16384L) {
-+              dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
-+              *resize_coeff = 0x3FFF;
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_ic_task_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+      u32 ic_conf;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      ic_conf |= ic->bit->ic_conf_en;
-+
-+      if (ic->rotation)
-+              ic_conf |= ic->bit->ic_conf_rot_en;
-+
-+      if (ic->in_cs.cs != ic->out_cs.cs)
-+              ic_conf |= ic->bit->ic_conf_csc1_en;
-+
-+      if (ic->graphics) {
-+              ic_conf |= ic->bit->ic_conf_cmb_en;
-+              ic_conf |= ic->bit->ic_conf_csc1_en;
-+
-+              if (ic->g_in_cs.cs != ic->out_cs.cs)
-+                      ic_conf |= ic->bit->ic_conf_csc2_en;
-+      }
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_enable);
-+
-+void ipu_ic_task_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+      u32 ic_conf;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      ic_conf &= ~(ic->bit->ic_conf_en |
-+                   ic->bit->ic_conf_csc1_en |
-+                   ic->bit->ic_conf_rot_en);
-+      if (ic->bit->ic_conf_csc2_en)
-+              ic_conf &= ~ic->bit->ic_conf_csc2_en;
-+      if (ic->bit->ic_conf_cmb_en)
-+              ic_conf &= ~ic->bit->ic_conf_cmb_en;
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_disable);
-+
-+int ipu_ic_task_graphics_init(struct ipu_ic *ic,
-+                            const struct ipu_ic_colorspace *g_in_cs,
-+                            bool galpha_en, u32 galpha,
-+                            bool colorkey_en, u32 colorkey)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_ic_csc csc2;
-+      unsigned long flags;
-+      u32 reg, ic_conf;
-+      int ret = 0;
-+
-+      if (ic->task == IC_TASK_ENCODER)
-+              return -EINVAL;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_conf = ipu_ic_read(ic, IC_CONF);
-+
-+      if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
-+              struct ipu_ic_csc csc1;
-+
-+              ret = ipu_ic_calc_csc(&csc1,
-+                                    V4L2_YCBCR_ENC_601,
-+                                    V4L2_QUANTIZATION_FULL_RANGE,
-+                                    IPUV3_COLORSPACE_RGB,
-+                                    V4L2_YCBCR_ENC_601,
-+                                    V4L2_QUANTIZATION_FULL_RANGE,
-+                                    IPUV3_COLORSPACE_RGB);
-+              if (ret)
-+                      goto unlock;
-+
-+              /* need transparent CSC1 conversion */
-+              ret = init_csc(ic, &csc1, 0);
-+              if (ret)
-+                      goto unlock;
-+      }
-+
-+      ic->g_in_cs = *g_in_cs;
-+      csc2.in_cs = ic->g_in_cs;
-+      csc2.out_cs = ic->out_cs;
-+
-+      ret = __ipu_ic_calc_csc(&csc2);
-+      if (ret)
-+              goto unlock;
-+
-+      ret = init_csc(ic, &csc2, 1);
-+      if (ret)
-+              goto unlock;
-+
-+      if (galpha_en) {
-+              ic_conf |= IC_CONF_IC_GLB_LOC_A;
-+              reg = ipu_ic_read(ic, IC_CMBP_1);
-+              reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
-+              reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
-+              ipu_ic_write(ic, reg, IC_CMBP_1);
-+      } else
-+              ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
-+
-+      if (colorkey_en) {
-+              ic_conf |= IC_CONF_KEY_COLOR_EN;
-+              ipu_ic_write(ic, colorkey, IC_CMBP_2);
-+      } else
-+              ic_conf &= ~IC_CONF_KEY_COLOR_EN;
-+
-+      ipu_ic_write(ic, ic_conf, IC_CONF);
-+
-+      ic->graphics = true;
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
-+
-+int ipu_ic_task_init_rsc(struct ipu_ic *ic,
-+                       const struct ipu_ic_csc *csc,
-+                       int in_width, int in_height,
-+                       int out_width, int out_height,
-+                       u32 rsc)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      u32 downsize_coeff, resize_coeff;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if (!rsc) {
-+              /* Setup vertical resizing */
-+
-+              ret = calc_resize_coeffs(ic, in_height, out_height,
-+                                       &resize_coeff, &downsize_coeff);
-+              if (ret)
-+                      return ret;
-+
-+              rsc = (downsize_coeff << 30) | (resize_coeff << 16);
-+
-+              /* Setup horizontal resizing */
-+              ret = calc_resize_coeffs(ic, in_width, out_width,
-+                                       &resize_coeff, &downsize_coeff);
-+              if (ret)
-+                      return ret;
-+
-+              rsc |= (downsize_coeff << 14) | resize_coeff;
-+      }
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ipu_ic_write(ic, rsc, ic->reg->rsc);
-+
-+      /* Setup color space conversion */
-+      ic->in_cs = csc->in_cs;
-+      ic->out_cs = csc->out_cs;
-+
-+      ret = init_csc(ic, csc, 0);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+
-+int ipu_ic_task_init(struct ipu_ic *ic,
-+                   const struct ipu_ic_csc *csc,
-+                   int in_width, int in_height,
-+                   int out_width, int out_height)
-+{
-+      return ipu_ic_task_init_rsc(ic, csc,
-+                                  in_width, in_height,
-+                                  out_width, out_height, 0);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_init);
-+
-+int ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
-+                        u32 width, u32 height, int burst_size,
-+                        enum ipu_rotate_mode rot)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+      u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
-+      u32 temp_rot = bitrev8(rot) >> 5;
-+      bool need_hor_flip = false;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if ((burst_size != 8) && (burst_size != 16)) {
-+              dev_err(ipu->dev, "Illegal burst length for IC\n");
-+              return -EINVAL;
-+      }
-+
-+      width--;
-+      height--;
-+
-+      if (temp_rot & 0x2)     /* Need horizontal flip */
-+              need_hor_flip = true;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
-+      ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
-+      ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
-+
-+      switch (channel->num) {
-+      case IPUV3_CHANNEL_IC_PP_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_IC_PP:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_PP:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_IC_PRP_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_ENC:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_IC_PRP_VF_MEM:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
-+
-+              if (need_hor_flip)
-+                      ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
-+
-+              ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
-+              ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
-+
-+              ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
-+              ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_MEM_ROT_VF:
-+              ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
-+              ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
-+              break;
-+      case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_G_MEM_IC_PP:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
-+              break;
-+      case IPUV3_CHANNEL_VDI_MEM_IC_VF:
-+              if (burst_size == 16)
-+                      ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
-+              else
-+                      ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
-+              break;
-+      default:
-+              goto unlock;
-+      }
-+
-+      ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
-+      ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
-+      ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
-+
-+      if (ipu_rot_mode_is_irt(rot))
-+              ic->rotation = true;
-+
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
-+
-+static void ipu_irt_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+
-+      if (!priv->irt_use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
-+
-+      priv->irt_use_count++;
-+}
-+
-+static void ipu_irt_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+
-+      if (priv->irt_use_count) {
-+              if (!--priv->irt_use_count)
-+                      ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
-+      }
-+}
-+
-+int ipu_ic_enable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
-+
-+      priv->use_count++;
-+
-+      if (ic->rotation)
-+              ipu_irt_enable(ic);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_enable);
-+
-+int ipu_ic_disable(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      if (ic->rotation)
-+              ipu_irt_disable(ic);
-+
-+      ic->rotation = ic->graphics = false;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_disable);
-+
-+struct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
-+{
-+      struct ipu_ic_priv *priv = ipu->ic_priv;
-+      unsigned long flags;
-+      struct ipu_ic *ic, *ret;
-+
-+      if (task >= IC_NUM_TASKS)
-+              return ERR_PTR(-EINVAL);
-+
-+      ic = &priv->task[task];
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (ic->in_use) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      ic->in_use = true;
-+      ret = ic;
-+
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_get);
-+
-+void ipu_ic_put(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+      ic->in_use = false;
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_put);
-+
-+int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long tpmem_base)
-+{
-+      struct ipu_ic_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->ic_priv = priv;
-+
-+      spin_lock_init(&priv->lock);
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+      priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
-+      if (!priv->tpmem_base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
-+
-+      priv->ipu = ipu;
-+
-+      for (i = 0; i < IC_NUM_TASKS; i++) {
-+              priv->task[i].task = i;
-+              priv->task[i].priv = priv;
-+              priv->task[i].reg = &ic_task_reg[i];
-+              priv->task[i].bit = &ic_task_bit[i];
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_ic_exit(struct ipu_soc *ipu)
-+{
-+}
-+
-+void ipu_ic_dump(struct ipu_ic *ic)
-+{
-+      struct ipu_ic_priv *priv = ic->priv;
-+      struct ipu_soc *ipu = priv->ipu;
-+
-+      dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CONF));
-+      dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PRP_ENC_RSC));
-+      dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PRP_VF_RSC));
-+      dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_PP_RSC));
-+      dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CMBP_1));
-+      dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_CMBP_2));
-+      dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_1));
-+      dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_2));
-+      dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_3));
-+      dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
-+              ipu_ic_read(ic, IC_IDMAC_4));
-+}
-+EXPORT_SYMBOL_GPL(ipu_ic_dump);
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
-@@ -0,0 +1,2475 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2016 Mentor Graphics Inc.
-+ *
-+ * Queued image conversion support, with tiling and rotation.
-+ */
-+
-+#include <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <video/imx-ipu-image-convert.h>
-+#include "ipu-prv.h"
-+
-+/*
-+ * The IC Resizer has a restriction that the output frame from the
-+ * resizer must be 1024 or less in both width (pixels) and height
-+ * (lines).
-+ *
-+ * The image converter attempts to split up a conversion when
-+ * the desired output (converted) frame resolution exceeds the
-+ * IC resizer limit of 1024 in either dimension.
-+ *
-+ * If either dimension of the output frame exceeds the limit, the
-+ * dimension is split into 1, 2, or 4 equal stripes, for a maximum
-+ * of 4*4 or 16 tiles. A conversion is then carried out for each
-+ * tile (but taking care to pass the full frame stride length to
-+ * the DMA channel's parameter memory!). IDMA double-buffering is used
-+ * to convert each tile back-to-back when possible (see note below
-+ * when double_buffering boolean is set).
-+ *
-+ * Note that the input frame must be split up into the same number
-+ * of tiles as the output frame:
-+ *
-+ *                       +---------+-----+
-+ *   +-----+---+         |  A      | B   |
-+ *   | A   | B |         |         |     |
-+ *   +-----+---+   -->   +---------+-----+
-+ *   | C   | D |         |  C      | D   |
-+ *   +-----+---+         |         |     |
-+ *                       +---------+-----+
-+ *
-+ * Clockwise 90° rotations are handled by first rescaling into a
-+ * reusable temporary tile buffer and then rotating with the 8x8
-+ * block rotator, writing to the correct destination:
-+ *
-+ *                                         +-----+-----+
-+ *                                         |     |     |
-+ *   +-----+---+         +---------+       | C   | A   |
-+ *   | A   | B |         | A,B, |  |       |     |     |
-+ *   +-----+---+   -->   | C,D  |  |  -->  |     |     |
-+ *   | C   | D |         +---------+       +-----+-----+
-+ *   +-----+---+                           | D   | B   |
-+ *                                         |     |     |
-+ *                                         +-----+-----+
-+ *
-+ * If the 8x8 block rotator is used, horizontal or vertical flipping
-+ * is done during the rotation step, otherwise flipping is done
-+ * during the scaling step.
-+ * With rotation or flipping, tile order changes between input and
-+ * output image. Tiles are numbered row major from top left to bottom
-+ * right for both input and output image.
-+ */
-+
-+#define MAX_STRIPES_W    4
-+#define MAX_STRIPES_H    4
-+#define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
-+
-+#define MIN_W     16
-+#define MIN_H     8
-+#define MAX_W     4096
-+#define MAX_H     4096
-+
-+enum ipu_image_convert_type {
-+      IMAGE_CONVERT_IN = 0,
-+      IMAGE_CONVERT_OUT,
-+};
-+
-+struct ipu_image_convert_dma_buf {
-+      void          *virt;
-+      dma_addr_t    phys;
-+      unsigned long len;
-+};
-+
-+struct ipu_image_convert_dma_chan {
-+      int in;
-+      int out;
-+      int rot_in;
-+      int rot_out;
-+      int vdi_in_p;
-+      int vdi_in;
-+      int vdi_in_n;
-+};
-+
-+/* dimensions of one tile */
-+struct ipu_image_tile {
-+      u32 width;
-+      u32 height;
-+      u32 left;
-+      u32 top;
-+      /* size and strides are in bytes */
-+      u32 size;
-+      u32 stride;
-+      u32 rot_stride;
-+      /* start Y or packed offset of this tile */
-+      u32 offset;
-+      /* offset from start to tile in U plane, for planar formats */
-+      u32 u_off;
-+      /* offset from start to tile in V plane, for planar formats */
-+      u32 v_off;
-+};
-+
-+struct ipu_image_convert_image {
-+      struct ipu_image base;
-+      enum ipu_image_convert_type type;
-+
-+      const struct ipu_image_pixfmt *fmt;
-+      unsigned int stride;
-+
-+      /* # of rows (horizontal stripes) if dest height is > 1024 */
-+      unsigned int num_rows;
-+      /* # of columns (vertical stripes) if dest width is > 1024 */
-+      unsigned int num_cols;
-+
-+      struct ipu_image_tile tile[MAX_TILES];
-+};
-+
-+struct ipu_image_pixfmt {
-+      u32     fourcc;        /* V4L2 fourcc */
-+      int     bpp;           /* total bpp */
-+      int     uv_width_dec;  /* decimation in width for U/V planes */
-+      int     uv_height_dec; /* decimation in height for U/V planes */
-+      bool    planar;        /* planar format */
-+      bool    uv_swapped;    /* U and V planes are swapped */
-+      bool    uv_packed;     /* partial planar (U and V in same plane) */
-+};
-+
-+struct ipu_image_convert_ctx;
-+struct ipu_image_convert_chan;
-+struct ipu_image_convert_priv;
-+
-+struct ipu_image_convert_ctx {
-+      struct ipu_image_convert_chan *chan;
-+
-+      ipu_image_convert_cb_t complete;
-+      void *complete_context;
-+
-+      /* Source/destination image data and rotation mode */
-+      struct ipu_image_convert_image in;
-+      struct ipu_image_convert_image out;
-+      struct ipu_ic_csc csc;
-+      enum ipu_rotate_mode rot_mode;
-+      u32 downsize_coeff_h;
-+      u32 downsize_coeff_v;
-+      u32 image_resize_coeff_h;
-+      u32 image_resize_coeff_v;
-+      u32 resize_coeffs_h[MAX_STRIPES_W];
-+      u32 resize_coeffs_v[MAX_STRIPES_H];
-+
-+      /* intermediate buffer for rotation */
-+      struct ipu_image_convert_dma_buf rot_intermediate[2];
-+
-+      /* current buffer number for double buffering */
-+      int cur_buf_num;
-+
-+      bool aborting;
-+      struct completion aborted;
-+
-+      /* can we use double-buffering for this conversion operation? */
-+      bool double_buffering;
-+      /* num_rows * num_cols */
-+      unsigned int num_tiles;
-+      /* next tile to process */
-+      unsigned int next_tile;
-+      /* where to place converted tile in dest image */
-+      unsigned int out_tile_map[MAX_TILES];
-+
-+      struct list_head list;
-+};
-+
-+struct ipu_image_convert_chan {
-+      struct ipu_image_convert_priv *priv;
-+
-+      enum ipu_ic_task ic_task;
-+      const struct ipu_image_convert_dma_chan *dma_ch;
-+
-+      struct ipu_ic *ic;
-+      struct ipuv3_channel *in_chan;
-+      struct ipuv3_channel *out_chan;
-+      struct ipuv3_channel *rotation_in_chan;
-+      struct ipuv3_channel *rotation_out_chan;
-+
-+      /* the IPU end-of-frame irqs */
-+      int out_eof_irq;
-+      int rot_out_eof_irq;
-+
-+      spinlock_t irqlock;
-+
-+      /* list of convert contexts */
-+      struct list_head ctx_list;
-+      /* queue of conversion runs */
-+      struct list_head pending_q;
-+      /* queue of completed runs */
-+      struct list_head done_q;
-+
-+      /* the current conversion run */
-+      struct ipu_image_convert_run *current_run;
-+};
-+
-+struct ipu_image_convert_priv {
-+      struct ipu_image_convert_chan chan[IC_NUM_TASKS];
-+      struct ipu_soc *ipu;
-+};
-+
-+static const struct ipu_image_convert_dma_chan
-+image_convert_dma_chan[IC_NUM_TASKS] = {
-+      [IC_TASK_VIEWFINDER] = {
-+              .in = IPUV3_CHANNEL_MEM_IC_PRP_VF,
-+              .out = IPUV3_CHANNEL_IC_PRP_VF_MEM,
-+              .rot_in = IPUV3_CHANNEL_MEM_ROT_VF,
-+              .rot_out = IPUV3_CHANNEL_ROT_VF_MEM,
-+              .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV,
-+              .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR,
-+              .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT,
-+      },
-+      [IC_TASK_POST_PROCESSOR] = {
-+              .in = IPUV3_CHANNEL_MEM_IC_PP,
-+              .out = IPUV3_CHANNEL_IC_PP_MEM,
-+              .rot_in = IPUV3_CHANNEL_MEM_ROT_PP,
-+              .rot_out = IPUV3_CHANNEL_ROT_PP_MEM,
-+      },
-+};
-+
-+static const struct ipu_image_pixfmt image_convert_formats[] = {
-+      {
-+              .fourcc = V4L2_PIX_FMT_RGB565,
-+              .bpp    = 16,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGB24,
-+              .bpp    = 24,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGR24,
-+              .bpp    = 24,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGB32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGR32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_XRGB32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_XBGR32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_BGRX32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_RGBX32,
-+              .bpp    = 32,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUYV,
-+              .bpp    = 16,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_UYVY,
-+              .bpp    = 16,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUV420,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YVU420,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+              .uv_swapped = true,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_NV12,
-+              .bpp    = 12,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 2,
-+              .uv_packed = true,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_YUV422P,
-+              .bpp    = 16,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+      }, {
-+              .fourcc = V4L2_PIX_FMT_NV16,
-+              .bpp    = 16,
-+              .planar = true,
-+              .uv_width_dec = 2,
-+              .uv_height_dec = 1,
-+              .uv_packed = true,
-+      },
-+};
-+
-+static const struct ipu_image_pixfmt *get_format(u32 fourcc)
-+{
-+      const struct ipu_image_pixfmt *ret = NULL;
-+      unsigned int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) {
-+              if (image_convert_formats[i].fourcc == fourcc) {
-+                      ret = &image_convert_formats[i];
-+                      break;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static void dump_format(struct ipu_image_convert_ctx *ctx,
-+                      struct ipu_image_convert_image *ic_image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev,
-+              "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
-+              chan->ic_task, ctx,
-+              ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input",
-+              ic_image->base.pix.width, ic_image->base.pix.height,
-+              ic_image->num_cols, ic_image->num_rows,
-+              ic_image->fmt->fourcc & 0xff,
-+              (ic_image->fmt->fourcc >> 8) & 0xff,
-+              (ic_image->fmt->fourcc >> 16) & 0xff,
-+              (ic_image->fmt->fourcc >> 24) & 0xff);
-+}
-+
-+int ipu_image_convert_enum_format(int index, u32 *fourcc)
-+{
-+      const struct ipu_image_pixfmt *fmt;
-+
-+      if (index >= (int)ARRAY_SIZE(image_convert_formats))
-+              return -EINVAL;
-+
-+      /* Format found */
-+      fmt = &image_convert_formats[index];
-+      *fourcc = fmt->fourcc;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format);
-+
-+static void free_dma_buf(struct ipu_image_convert_priv *priv,
-+                       struct ipu_image_convert_dma_buf *buf)
-+{
-+      if (buf->virt)
-+              dma_free_coherent(priv->ipu->dev,
-+                                buf->len, buf->virt, buf->phys);
-+      buf->virt = NULL;
-+      buf->phys = 0;
-+}
-+
-+static int alloc_dma_buf(struct ipu_image_convert_priv *priv,
-+                       struct ipu_image_convert_dma_buf *buf,
-+                       int size)
-+{
-+      buf->len = PAGE_ALIGN(size);
-+      buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys,
-+                                     GFP_DMA | GFP_KERNEL);
-+      if (!buf->virt) {
-+              dev_err(priv->ipu->dev, "failed to alloc dma buffer\n");
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static inline int num_stripes(int dim)
-+{
-+      return (dim - 1) / 1024 + 1;
-+}
-+
-+/*
-+ * Calculate downsizing coefficients, which are the same for all tiles,
-+ * and initial bilinear resizing coefficients, which are used to find the
-+ * best seam positions.
-+ * Also determine the number of tiles necessary to guarantee that no tile
-+ * is larger than 1024 pixels in either dimension at the output and between
-+ * IC downsizing and main processing sections.
-+ */
-+static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
-+                                        struct ipu_image *in,
-+                                        struct ipu_image *out)
-+{
-+      u32 downsized_width = in->rect.width;
-+      u32 downsized_height = in->rect.height;
-+      u32 downsize_coeff_v = 0;
-+      u32 downsize_coeff_h = 0;
-+      u32 resized_width = out->rect.width;
-+      u32 resized_height = out->rect.height;
-+      u32 resize_coeff_h;
-+      u32 resize_coeff_v;
-+      u32 cols;
-+      u32 rows;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              resized_width = out->rect.height;
-+              resized_height = out->rect.width;
-+      }
-+
-+      /* Do not let invalid input lead to an endless loop below */
-+      if (WARN_ON(resized_width == 0 || resized_height == 0))
-+              return -EINVAL;
-+
-+      while (downsized_width >= resized_width * 2) {
-+              downsized_width >>= 1;
-+              downsize_coeff_h++;
-+      }
-+
-+      while (downsized_height >= resized_height * 2) {
-+              downsized_height >>= 1;
-+              downsize_coeff_v++;
-+      }
-+
-+      /*
-+       * Calculate the bilinear resizing coefficients that could be used if
-+       * we were converting with a single tile. The bottom right output pixel
-+       * should sample as close as possible to the bottom right input pixel
-+       * out of the decimator, but not overshoot it:
-+       */
-+      resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
-+      resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
-+
-+      /*
-+       * Both the output of the IC downsizing section before being passed to
-+       * the IC main processing section and the final output of the IC main
-+       * processing section must be <= 1024 pixels in both dimensions.
-+       */
-+      cols = num_stripes(max_t(u32, downsized_width, resized_width));
-+      rows = num_stripes(max_t(u32, downsized_height, resized_height));
-+
-+      dev_dbg(ctx->chan->priv->ipu->dev,
-+              "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
-+              __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
-+              resize_coeff_v, cols, rows);
-+
-+      if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
-+          resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
-+              return -EINVAL;
-+
-+      ctx->downsize_coeff_h = downsize_coeff_h;
-+      ctx->downsize_coeff_v = downsize_coeff_v;
-+      ctx->image_resize_coeff_h = resize_coeff_h;
-+      ctx->image_resize_coeff_v = resize_coeff_v;
-+      ctx->in.num_cols = cols;
-+      ctx->in.num_rows = rows;
-+
-+      return 0;
-+}
-+
-+#define round_closest(x, y) round_down((x) + (y)/2, (y))
-+
-+/*
-+ * Find the best aligned seam position for the given column / row index.
-+ * Rotation and image offsets are out of scope.
-+ *
-+ * @index: column / row index, used to calculate valid interval
-+ * @in_edge: input right / bottom edge
-+ * @out_edge: output right / bottom edge
-+ * @in_align: input alignment, either horizontal 8-byte line start address
-+ *            alignment, or pixel alignment due to image format
-+ * @out_align: output alignment, either horizontal 8-byte line start address
-+ *             alignment, or pixel alignment due to image format or rotator
-+ *             block size
-+ * @in_burst: horizontal input burst size in case of horizontal flip
-+ * @out_burst: horizontal output burst size or rotator block size
-+ * @downsize_coeff: downsizing section coefficient
-+ * @resize_coeff: main processing section resizing coefficient
-+ * @_in_seam: aligned input seam position return value
-+ * @_out_seam: aligned output seam position return value
-+ */
-+static void find_best_seam(struct ipu_image_convert_ctx *ctx,
-+                         unsigned int index,
-+                         unsigned int in_edge,
-+                         unsigned int out_edge,
-+                         unsigned int in_align,
-+                         unsigned int out_align,
-+                         unsigned int in_burst,
-+                         unsigned int out_burst,
-+                         unsigned int downsize_coeff,
-+                         unsigned int resize_coeff,
-+                         u32 *_in_seam,
-+                         u32 *_out_seam)
-+{
-+      struct device *dev = ctx->chan->priv->ipu->dev;
-+      unsigned int out_pos;
-+      /* Input / output seam position candidates */
-+      unsigned int out_seam = 0;
-+      unsigned int in_seam = 0;
-+      unsigned int min_diff = UINT_MAX;
-+      unsigned int out_start;
-+      unsigned int out_end;
-+      unsigned int in_start;
-+      unsigned int in_end;
-+
-+      /* Start within 1024 pixels of the right / bottom edge */
-+      out_start = max_t(int, index * out_align, out_edge - 1024);
-+      /* End before having to add more columns to the left / rows above */
-+      out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
-+
-+      /*
-+       * Limit input seam position to make sure that the downsized input tile
-+       * to the right or bottom does not exceed 1024 pixels.
-+       */
-+      in_start = max_t(int, index * in_align,
-+                       in_edge - (1024 << downsize_coeff));
-+      in_end = min_t(unsigned int, in_edge,
-+                     index * (1024 << downsize_coeff) + 1);
-+
-+      /*
-+       * Output tiles must start at a multiple of 8 bytes horizontally and
-+       * possibly at an even line horizontally depending on the pixel format.
-+       * Only consider output aligned positions for the seam.
-+       */
-+      out_start = round_up(out_start, out_align);
-+      for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
-+              unsigned int in_pos;
-+              unsigned int in_pos_aligned;
-+              unsigned int in_pos_rounded;
-+              unsigned int abs_diff;
-+
-+              /*
-+               * Tiles in the right row / bottom column may not be allowed to
-+               * overshoot horizontally / vertically. out_burst may be the
-+               * actual DMA burst size, or the rotator block size.
-+               */
-+              if ((out_burst > 1) && (out_edge - out_pos) % out_burst)
-+                      continue;
-+
-+              /*
-+               * Input sample position, corresponding to out_pos, 19.13 fixed
-+               * point.
-+               */
-+              in_pos = (out_pos * resize_coeff) << downsize_coeff;
-+              /*
-+               * The closest input sample position that we could actually
-+               * start the input tile at, 19.13 fixed point.
-+               */
-+              in_pos_aligned = round_closest(in_pos, 8192U * in_align);
-+              /* Convert 19.13 fixed point to integer */
-+              in_pos_rounded = in_pos_aligned / 8192U;
-+
-+              if (in_pos_rounded < in_start)
-+                      continue;
-+              if (in_pos_rounded >= in_end)
-+                      break;
-+
-+              if ((in_burst > 1) &&
-+                  (in_edge - in_pos_rounded) % in_burst)
-+                      continue;
-+
-+              if (in_pos < in_pos_aligned)
-+                      abs_diff = in_pos_aligned - in_pos;
-+              else
-+                      abs_diff = in_pos - in_pos_aligned;
-+
-+              if (abs_diff < min_diff) {
-+                      in_seam = in_pos_rounded;
-+                      out_seam = out_pos;
-+                      min_diff = abs_diff;
-+              }
-+      }
-+
-+      *_out_seam = out_seam;
-+      *_in_seam = in_seam;
-+
-+      dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
-+              __func__, out_seam, out_align, out_start, out_end,
-+              in_seam, in_align, in_start, in_end, min_diff / 8192,
-+              DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
-+}
-+
-+/*
-+ * Tile left edges are required to be aligned to multiples of 8 bytes
-+ * by the IDMAC.
-+ */
-+static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt)
-+{
-+      if (fmt->planar)
-+              return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec;
-+      else
-+              return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8;
-+}
-+
-+/*
-+ * Tile top edge alignment is only limited by chroma subsampling.
-+ */
-+static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt)
-+{
-+      return fmt->uv_height_dec > 1 ? 2 : 1;
-+}
-+
-+static inline u32 tile_width_align(enum ipu_image_convert_type type,
-+                                 const struct ipu_image_pixfmt *fmt,
-+                                 enum ipu_rotate_mode rot_mode)
-+{
-+      if (type == IMAGE_CONVERT_IN) {
-+              /*
-+               * The IC burst reads 8 pixels at a time. Reading beyond the
-+               * end of the line is usually acceptable. Those pixels are
-+               * ignored, unless the IC has to write the scaled line in
-+               * reverse.
-+               */
-+              return (!ipu_rot_mode_is_irt(rot_mode) &&
-+                      (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2;
-+      }
-+
-+      /*
-+       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
-+       * formats to guarantee 8-byte aligned line start addresses in the
-+       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
-+       * for all other formats.
-+       */
-+      return (ipu_rot_mode_is_irt(rot_mode) &&
-+              fmt->planar && !fmt->uv_packed) ?
-+              8 * fmt->uv_width_dec : 8;
-+}
-+
-+static inline u32 tile_height_align(enum ipu_image_convert_type type,
-+                                  const struct ipu_image_pixfmt *fmt,
-+                                  enum ipu_rotate_mode rot_mode)
-+{
-+      if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode))
-+              return 2;
-+
-+      /*
-+       * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
-+       * formats to guarantee 8-byte aligned line start addresses in the
-+       * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
-+       * for all other formats.
-+       */
-+      return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8;
-+}
-+
-+/*
-+ * Fill in left position and width and for all tiles in an input column, and
-+ * for all corresponding output tiles. If the 90° rotator is used, the output
-+ * tiles are in a row, and output tile top position and height are set.
-+ */
-+static void fill_tile_column(struct ipu_image_convert_ctx *ctx,
-+                           unsigned int col,
-+                           struct ipu_image_convert_image *in,
-+                           unsigned int in_left, unsigned int in_width,
-+                           struct ipu_image_convert_image *out,
-+                           unsigned int out_left, unsigned int out_width)
-+{
-+      unsigned int row, tile_idx;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+
-+      for (row = 0; row < in->num_rows; row++) {
-+              tile_idx = in->num_cols * row + col;
-+              in_tile = &in->tile[tile_idx];
-+              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
-+
-+              in_tile->left = in_left;
-+              in_tile->width = in_width;
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+                      out_tile->top = out_left;
-+                      out_tile->height = out_width;
-+              } else {
-+                      out_tile->left = out_left;
-+                      out_tile->width = out_width;
-+              }
-+      }
-+}
-+
-+/*
-+ * Fill in top position and height and for all tiles in an input row, and
-+ * for all corresponding output tiles. If the 90° rotator is used, the output
-+ * tiles are in a column, and output tile left position and width are set.
-+ */
-+static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row,
-+                        struct ipu_image_convert_image *in,
-+                        unsigned int in_top, unsigned int in_height,
-+                        struct ipu_image_convert_image *out,
-+                        unsigned int out_top, unsigned int out_height)
-+{
-+      unsigned int col, tile_idx;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+
-+      for (col = 0; col < in->num_cols; col++) {
-+              tile_idx = in->num_cols * row + col;
-+              in_tile = &in->tile[tile_idx];
-+              out_tile = &out->tile[ctx->out_tile_map[tile_idx]];
-+
-+              in_tile->top = in_top;
-+              in_tile->height = in_height;
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+                      out_tile->left = out_top;
-+                      out_tile->width = out_height;
-+              } else {
-+                      out_tile->top = out_top;
-+                      out_tile->height = out_height;
-+              }
-+      }
-+}
-+
-+/*
-+ * Find the best horizontal and vertical seam positions to split into tiles.
-+ * Minimize the fractional part of the input sampling position for the
-+ * top / left pixels of each tile.
-+ */
-+static void find_seams(struct ipu_image_convert_ctx *ctx,
-+                     struct ipu_image_convert_image *in,
-+                     struct ipu_image_convert_image *out)
-+{
-+      struct device *dev = ctx->chan->priv->ipu->dev;
-+      unsigned int resized_width = out->base.rect.width;
-+      unsigned int resized_height = out->base.rect.height;
-+      unsigned int col;
-+      unsigned int row;
-+      unsigned int in_left_align = tile_left_align(in->fmt);
-+      unsigned int in_top_align = tile_top_align(in->fmt);
-+      unsigned int out_left_align = tile_left_align(out->fmt);
-+      unsigned int out_top_align = tile_top_align(out->fmt);
-+      unsigned int out_width_align = tile_width_align(out->type, out->fmt,
-+                                                      ctx->rot_mode);
-+      unsigned int out_height_align = tile_height_align(out->type, out->fmt,
-+                                                        ctx->rot_mode);
-+      unsigned int in_right = in->base.rect.width;
-+      unsigned int in_bottom = in->base.rect.height;
-+      unsigned int out_right = out->base.rect.width;
-+      unsigned int out_bottom = out->base.rect.height;
-+      unsigned int flipped_out_left;
-+      unsigned int flipped_out_top;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* Switch width/height and align top left to IRT block size */
-+              resized_width = out->base.rect.height;
-+              resized_height = out->base.rect.width;
-+              out_left_align = out_height_align;
-+              out_top_align = out_width_align;
-+              out_width_align = out_left_align;
-+              out_height_align = out_top_align;
-+              out_right = out->base.rect.height;
-+              out_bottom = out->base.rect.width;
-+      }
-+
-+      for (col = in->num_cols - 1; col > 0; col--) {
-+              bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) ||
-+                                        !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              bool allow_out_overshoot = (col < in->num_cols - 1) &&
-+                                         !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              unsigned int in_left;
-+              unsigned int out_left;
-+
-+              /*
-+               * Align input width to burst length if the scaling step flips
-+               * horizontally.
-+               */
-+
-+              find_best_seam(ctx, col,
-+                             in_right, out_right,
-+                             in_left_align, out_left_align,
-+                             allow_in_overshoot ? 1 : 8 /* burst length */,
-+                             allow_out_overshoot ? 1 : out_width_align,
-+                             ctx->downsize_coeff_h, ctx->image_resize_coeff_h,
-+                             &in_left, &out_left);
-+
-+              if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
-+                      flipped_out_left = resized_width - out_right;
-+              else
-+                      flipped_out_left = out_left;
-+
-+              fill_tile_column(ctx, col, in, in_left, in_right - in_left,
-+                               out, flipped_out_left, out_right - out_left);
-+
-+              dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col,
-+                      in_left, in_right - in_left,
-+                      flipped_out_left, out_right - out_left);
-+
-+              in_right = in_left;
-+              out_right = out_left;
-+      }
-+
-+      flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ?
-+                         resized_width - out_right : 0;
-+
-+      fill_tile_column(ctx, 0, in, 0, in_right,
-+                       out, flipped_out_left, out_right);
-+
-+      dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__,
-+              in_right, flipped_out_left, out_right);
-+
-+      for (row = in->num_rows - 1; row > 0; row--) {
-+              bool allow_overshoot = row < in->num_rows - 1;
-+              unsigned int in_top;
-+              unsigned int out_top;
-+
-+              find_best_seam(ctx, row,
-+                             in_bottom, out_bottom,
-+                             in_top_align, out_top_align,
-+                             1, allow_overshoot ? 1 : out_height_align,
-+                             ctx->downsize_coeff_v, ctx->image_resize_coeff_v,
-+                             &in_top, &out_top);
-+
-+              if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
-+                  ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      flipped_out_top = resized_height - out_bottom;
-+              else
-+                      flipped_out_top = out_top;
-+
-+              fill_tile_row(ctx, row, in, in_top, in_bottom - in_top,
-+                            out, flipped_out_top, out_bottom - out_top);
-+
-+              dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row,
-+                      in_top, in_bottom - in_top,
-+                      flipped_out_top, out_bottom - out_top);
-+
-+              in_bottom = in_top;
-+              out_bottom = out_top;
-+      }
-+
-+      if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^
-+          ipu_rot_mode_is_irt(ctx->rot_mode))
-+              flipped_out_top = resized_height - out_bottom;
-+      else
-+              flipped_out_top = 0;
-+
-+      fill_tile_row(ctx, 0, in, 0, in_bottom,
-+                    out, flipped_out_top, out_bottom);
-+
-+      dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__,
-+              in_bottom, flipped_out_top, out_bottom);
-+}
-+
-+static int calc_tile_dimensions(struct ipu_image_convert_ctx *ctx,
-+                              struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      unsigned int max_width = 1024;
-+      unsigned int max_height = 1024;
-+      unsigned int i;
-+
-+      if (image->type == IMAGE_CONVERT_IN) {
-+              /* Up to 4096x4096 input tile size */
-+              max_width <<= ctx->downsize_coeff_h;
-+              max_height <<= ctx->downsize_coeff_v;
-+      }
-+
-+      for (i = 0; i < ctx->num_tiles; i++) {
-+              struct ipu_image_tile *tile;
-+              const unsigned int row = i / image->num_cols;
-+              const unsigned int col = i % image->num_cols;
-+
-+              if (image->type == IMAGE_CONVERT_OUT)
-+                      tile = &image->tile[ctx->out_tile_map[i]];
-+              else
-+                      tile = &image->tile[i];
-+
-+              tile->size = ((tile->height * image->fmt->bpp) >> 3) *
-+                      tile->width;
-+
-+              if (image->fmt->planar) {
-+                      tile->stride = tile->width;
-+                      tile->rot_stride = tile->height;
-+              } else {
-+                      tile->stride =
-+                              (image->fmt->bpp * tile->width) >> 3;
-+                      tile->rot_stride =
-+                              (image->fmt->bpp * tile->height) >> 3;
-+              }
-+
-+              dev_dbg(priv->ipu->dev,
-+                      "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
-+                      chan->ic_task, ctx,
-+                      image->type == IMAGE_CONVERT_IN ? "Input" : "Output",
-+                      row, col,
-+                      tile->width, tile->height, tile->left, tile->top);
-+
-+              if (!tile->width || tile->width > max_width ||
-+                  !tile->height || tile->height > max_height) {
-+                      dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n",
-+                              image->type == IMAGE_CONVERT_IN ? "input" :
-+                              "output", tile->width, tile->height);
-+                      return -EINVAL;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * Use the rotation transformation to find the tile coordinates
-+ * (row, col) of a tile in the destination frame that corresponds
-+ * to the given tile coordinates of a source frame. The destination
-+ * coordinate is then converted to a tile index.
-+ */
-+static int transform_tile_index(struct ipu_image_convert_ctx *ctx,
-+                              int src_row, int src_col)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      int dst_row, dst_col;
-+
-+      /* with no rotation it's a 1:1 mapping */
-+      if (ctx->rot_mode == IPU_ROTATE_NONE)
-+              return src_row * s_image->num_cols + src_col;
-+
-+      /*
-+       * before doing the transform, first we have to translate
-+       * source row,col for an origin in the center of s_image
-+       */
-+      src_row = src_row * 2 - (s_image->num_rows - 1);
-+      src_col = src_col * 2 - (s_image->num_cols - 1);
-+
-+      /* do the rotation transform */
-+      if (ctx->rot_mode & IPU_ROT_BIT_90) {
-+              dst_col = -src_row;
-+              dst_row = src_col;
-+      } else {
-+              dst_col = src_col;
-+              dst_row = src_row;
-+      }
-+
-+      /* apply flip */
-+      if (ctx->rot_mode & IPU_ROT_BIT_HFLIP)
-+              dst_col = -dst_col;
-+      if (ctx->rot_mode & IPU_ROT_BIT_VFLIP)
-+              dst_row = -dst_row;
-+
-+      dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
-+              chan->ic_task, ctx, src_col, src_row, dst_col, dst_row);
-+
-+      /*
-+       * finally translate dest row,col using an origin in upper
-+       * left of d_image
-+       */
-+      dst_row += d_image->num_rows - 1;
-+      dst_col += d_image->num_cols - 1;
-+      dst_row /= 2;
-+      dst_col /= 2;
-+
-+      return dst_row * d_image->num_cols + dst_col;
-+}
-+
-+/*
-+ * Fill the out_tile_map[] with transformed destination tile indeces.
-+ */
-+static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      unsigned int row, col, tile = 0;
-+
-+      for (row = 0; row < s_image->num_rows; row++) {
-+              for (col = 0; col < s_image->num_cols; col++) {
-+                      ctx->out_tile_map[tile] =
-+                              transform_tile_index(ctx, row, col);
-+                      tile++;
-+              }
-+      }
-+}
-+
-+static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx,
-+                                  struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      const struct ipu_image_pixfmt *fmt = image->fmt;
-+      unsigned int row, col, tile = 0;
-+      u32 H, top, y_stride, uv_stride;
-+      u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp;
-+      u32 y_row_off, y_col_off, y_off;
-+      u32 y_size, uv_size;
-+
-+      /* setup some convenience vars */
-+      H = image->base.pix.height;
-+
-+      y_stride = image->stride;
-+      uv_stride = y_stride / fmt->uv_width_dec;
-+      if (fmt->uv_packed)
-+              uv_stride *= 2;
-+
-+      y_size = H * y_stride;
-+      uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec);
-+
-+      for (row = 0; row < image->num_rows; row++) {
-+              top = image->tile[tile].top;
-+              y_row_off = top * y_stride;
-+              uv_row_off = (top * uv_stride) / fmt->uv_height_dec;
-+
-+              for (col = 0; col < image->num_cols; col++) {
-+                      y_col_off = image->tile[tile].left;
-+                      uv_col_off = y_col_off / fmt->uv_width_dec;
-+                      if (fmt->uv_packed)
-+                              uv_col_off *= 2;
-+
-+                      y_off = y_row_off + y_col_off;
-+                      uv_off = uv_row_off + uv_col_off;
-+
-+                      u_off = y_size - y_off + uv_off;
-+                      v_off = (fmt->uv_packed) ? 0 : u_off + uv_size;
-+                      if (fmt->uv_swapped) {
-+                              tmp = u_off;
-+                              u_off = v_off;
-+                              v_off = tmp;
-+                      }
-+
-+                      image->tile[tile].offset = y_off;
-+                      image->tile[tile].u_off = u_off;
-+                      image->tile[tile++].v_off = v_off;
-+
-+                      if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) {
-+                              dev_err(priv->ipu->dev,
-+                                      "task %u: ctx %p: %s@[%d,%d]: "
-+                                      "y_off %08x, u_off %08x, v_off %08x\n",
-+                                      chan->ic_task, ctx,
-+                                      image->type == IMAGE_CONVERT_IN ?
-+                                      "Input" : "Output", row, col,
-+                                      y_off, u_off, v_off);
-+                              return -EINVAL;
-+                      }
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx,
-+                                  struct ipu_image_convert_image *image)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      const struct ipu_image_pixfmt *fmt = image->fmt;
-+      unsigned int row, col, tile = 0;
-+      u32 bpp, stride, offset;
-+      u32 row_off, col_off;
-+
-+      /* setup some convenience vars */
-+      stride = image->stride;
-+      bpp = fmt->bpp;
-+
-+      for (row = 0; row < image->num_rows; row++) {
-+              row_off = image->tile[tile].top * stride;
-+
-+              for (col = 0; col < image->num_cols; col++) {
-+                      col_off = (image->tile[tile].left * bpp) >> 3;
-+
-+                      offset = row_off + col_off;
-+
-+                      image->tile[tile].offset = offset;
-+                      image->tile[tile].u_off = 0;
-+                      image->tile[tile++].v_off = 0;
-+
-+                      if (offset & 0x7) {
-+                              dev_err(priv->ipu->dev,
-+                                      "task %u: ctx %p: %s@[%d,%d]: "
-+                                      "phys %08x\n",
-+                                      chan->ic_task, ctx,
-+                                      image->type == IMAGE_CONVERT_IN ?
-+                                      "Input" : "Output", row, col,
-+                                      row_off + col_off);
-+                              return -EINVAL;
-+                      }
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx,
-+                            struct ipu_image_convert_image *image)
-+{
-+      if (image->fmt->planar)
-+              return calc_tile_offsets_planar(ctx, image);
-+
-+      return calc_tile_offsets_packed(ctx, image);
-+}
-+
-+/*
-+ * Calculate the resizing ratio for the IC main processing section given input
-+ * size, fixed downsizing coefficient, and output size.
-+ * Either round to closest for the next tile's first pixel to minimize seams
-+ * and distortion (for all but right column / bottom row), or round down to
-+ * avoid sampling beyond the edges of the input image for this tile's last
-+ * pixel.
-+ * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
-+ */
-+static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff,
-+                           u32 output_size, bool allow_overshoot)
-+{
-+      u32 downsized = input_size >> downsize_coeff;
-+
-+      if (allow_overshoot)
-+              return DIV_ROUND_CLOSEST(8192 * downsized, output_size);
-+      else
-+              return 8192 * (downsized - 1) / (output_size - 1);
-+}
-+
-+/*
-+ * Slightly modify resize coefficients per tile to hide the bilinear
-+ * interpolator reset at tile borders, shifting the right / bottom edge
-+ * by up to a half input pixel. This removes noticeable seams between
-+ * tiles at higher upscaling factors.
-+ */
-+static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_tile *in_tile, *out_tile;
-+      unsigned int col, row, tile_idx;
-+      unsigned int last_output;
-+
-+      for (col = 0; col < ctx->in.num_cols; col++) {
-+              bool closest = (col < ctx->in.num_cols - 1) &&
-+                             !(ctx->rot_mode & IPU_ROT_BIT_HFLIP);
-+              u32 resized_width;
-+              u32 resize_coeff_h;
-+              u32 in_width;
-+
-+              tile_idx = col;
-+              in_tile = &ctx->in.tile[tile_idx];
-+              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      resized_width = out_tile->height;
-+              else
-+                      resized_width = out_tile->width;
-+
-+              resize_coeff_h = calc_resize_coeff(in_tile->width,
-+                                                 ctx->downsize_coeff_h,
-+                                                 resized_width, closest);
-+
-+              dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n",
-+                      __func__, col, resize_coeff_h);
-+
-+              /*
-+               * With the horizontal scaling factor known, round up resized
-+               * width (output width or height) to burst size.
-+               */
-+              resized_width = round_up(resized_width, 8);
-+
-+              /*
-+               * Calculate input width from the last accessed input pixel
-+               * given resized width and scaling coefficients. Round up to
-+               * burst size.
-+               */
-+              last_output = resized_width - 1;
-+              if (closest && ((last_output * resize_coeff_h) % 8192))
-+                      last_output++;
-+              in_width = round_up(
-+                      (DIV_ROUND_UP(last_output * resize_coeff_h, 8192) + 1)
-+                      << ctx->downsize_coeff_h, 8);
-+
-+              for (row = 0; row < ctx->in.num_rows; row++) {
-+                      tile_idx = row * ctx->in.num_cols + col;
-+                      in_tile = &ctx->in.tile[tile_idx];
-+                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                              out_tile->height = resized_width;
-+                      else
-+                              out_tile->width = resized_width;
-+
-+                      in_tile->width = in_width;
-+              }
-+
-+              ctx->resize_coeffs_h[col] = resize_coeff_h;
-+      }
-+
-+      for (row = 0; row < ctx->in.num_rows; row++) {
-+              bool closest = (row < ctx->in.num_rows - 1) &&
-+                             !(ctx->rot_mode & IPU_ROT_BIT_VFLIP);
-+              u32 resized_height;
-+              u32 resize_coeff_v;
-+              u32 in_height;
-+
-+              tile_idx = row * ctx->in.num_cols;
-+              in_tile = &ctx->in.tile[tile_idx];
-+              out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      resized_height = out_tile->width;
-+              else
-+                      resized_height = out_tile->height;
-+
-+              resize_coeff_v = calc_resize_coeff(in_tile->height,
-+                                                 ctx->downsize_coeff_v,
-+                                                 resized_height, closest);
-+
-+              dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n",
-+                      __func__, row, resize_coeff_v);
-+
-+              /*
-+               * With the vertical scaling factor known, round up resized
-+               * height (output width or height) to IDMAC limitations.
-+               */
-+              resized_height = round_up(resized_height, 2);
-+
-+              /*
-+               * Calculate input width from the last accessed input pixel
-+               * given resized height and scaling coefficients. Align to
-+               * IDMAC restrictions.
-+               */
-+              last_output = resized_height - 1;
-+              if (closest && ((last_output * resize_coeff_v) % 8192))
-+                      last_output++;
-+              in_height = round_up(
-+                      (DIV_ROUND_UP(last_output * resize_coeff_v, 8192) + 1)
-+                      << ctx->downsize_coeff_v, 2);
-+
-+              for (col = 0; col < ctx->in.num_cols; col++) {
-+                      tile_idx = row * ctx->in.num_cols + col;
-+                      in_tile = &ctx->in.tile[tile_idx];
-+                      out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]];
-+
-+                      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                              out_tile->width = resized_height;
-+                      else
-+                              out_tile->height = resized_height;
-+
-+                      in_tile->height = in_height;
-+              }
-+
-+              ctx->resize_coeffs_v[row] = resize_coeff_v;
-+      }
-+}
-+
-+/*
-+ * return the number of runs in given queue (pending_q or done_q)
-+ * for this context. hold irqlock when calling.
-+ */
-+static int get_run_count(struct ipu_image_convert_ctx *ctx,
-+                       struct list_head *q)
-+{
-+      struct ipu_image_convert_run *run;
-+      int count = 0;
-+
-+      lockdep_assert_held(&ctx->chan->irqlock);
-+
-+      list_for_each_entry(run, q, list) {
-+              if (run->ctx == ctx)
-+                      count++;
-+      }
-+
-+      return count;
-+}
-+
-+static void convert_stop(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n",
-+              __func__, chan->ic_task, ctx, run);
-+
-+      /* disable IC tasks and the channels */
-+      ipu_ic_task_disable(chan->ic);
-+      ipu_idmac_disable_channel(chan->in_chan);
-+      ipu_idmac_disable_channel(chan->out_chan);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_idmac_disable_channel(chan->rotation_in_chan);
-+              ipu_idmac_disable_channel(chan->rotation_out_chan);
-+              ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan);
-+      }
-+
-+      ipu_ic_disable(chan->ic);
-+}
-+
-+static void init_idmac_channel(struct ipu_image_convert_ctx *ctx,
-+                             struct ipuv3_channel *channel,
-+                             struct ipu_image_convert_image *image,
-+                             enum ipu_rotate_mode rot_mode,
-+                             bool rot_swap_width_height,
-+                             unsigned int tile)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      unsigned int burst_size;
-+      u32 width, height, stride;
-+      dma_addr_t addr0, addr1 = 0;
-+      struct ipu_image tile_image;
-+      unsigned int tile_idx[2];
-+
-+      if (image->type == IMAGE_CONVERT_OUT) {
-+              tile_idx[0] = ctx->out_tile_map[tile];
-+              tile_idx[1] = ctx->out_tile_map[1];
-+      } else {
-+              tile_idx[0] = tile;
-+              tile_idx[1] = 1;
-+      }
-+
-+      if (rot_swap_width_height) {
-+              width = image->tile[tile_idx[0]].height;
-+              height = image->tile[tile_idx[0]].width;
-+              stride = image->tile[tile_idx[0]].rot_stride;
-+              addr0 = ctx->rot_intermediate[0].phys;
-+              if (ctx->double_buffering)
-+                      addr1 = ctx->rot_intermediate[1].phys;
-+      } else {
-+              width = image->tile[tile_idx[0]].width;
-+              height = image->tile[tile_idx[0]].height;
-+              stride = image->stride;
-+              addr0 = image->base.phys0 +
-+                      image->tile[tile_idx[0]].offset;
-+              if (ctx->double_buffering)
-+                      addr1 = image->base.phys0 +
-+                              image->tile[tile_idx[1]].offset;
-+      }
-+
-+      ipu_cpmem_zero(channel);
-+
-+      memset(&tile_image, 0, sizeof(tile_image));
-+      tile_image.pix.width = tile_image.rect.width = width;
-+      tile_image.pix.height = tile_image.rect.height = height;
-+      tile_image.pix.bytesperline = stride;
-+      tile_image.pix.pixelformat =  image->fmt->fourcc;
-+      tile_image.phys0 = addr0;
-+      tile_image.phys1 = addr1;
-+      if (image->fmt->planar && !rot_swap_width_height) {
-+              tile_image.u_offset = image->tile[tile_idx[0]].u_off;
-+              tile_image.v_offset = image->tile[tile_idx[0]].v_off;
-+      }
-+
-+      ipu_cpmem_set_image(channel, &tile_image);
-+
-+      if (rot_mode)
-+              ipu_cpmem_set_rotation(channel, rot_mode);
-+
-+      /*
-+       * Skip writing U and V components to odd rows in the output
-+       * channels for planar 4:2:0.
-+       */
-+      if ((channel == chan->out_chan ||
-+           channel == chan->rotation_out_chan) &&
-+          image->fmt->planar && image->fmt->uv_height_dec == 2)
-+              ipu_cpmem_skip_odd_chroma_rows(channel);
-+
-+      if (channel == chan->rotation_in_chan ||
-+          channel == chan->rotation_out_chan) {
-+              burst_size = 8;
-+              ipu_cpmem_set_block_mode(channel);
-+      } else
-+              burst_size = (width % 16) ? 8 : 16;
-+
-+      ipu_cpmem_set_burstsize(channel, burst_size);
-+
-+      ipu_ic_task_idma_init(chan->ic, channel, width, height,
-+                            burst_size, rot_mode);
-+
-+      /*
-+       * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
-+       * only do this when there is no PRG present.
-+       */
-+      if (!channel->ipu->prg_priv)
-+              ipu_cpmem_set_axi_id(channel, 1);
-+
-+      ipu_idmac_set_double_buffer(channel, ctx->double_buffering);
-+}
-+
-+static int convert_start(struct ipu_image_convert_run *run, unsigned int tile)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      unsigned int dst_tile = ctx->out_tile_map[tile];
-+      unsigned int dest_width, dest_height;
-+      unsigned int col, row;
-+      u32 rsc;
-+      int ret;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
-+              __func__, chan->ic_task, ctx, run, tile, dst_tile);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* swap width/height for resizer */
-+              dest_width = d_image->tile[dst_tile].height;
-+              dest_height = d_image->tile[dst_tile].width;
-+      } else {
-+              dest_width = d_image->tile[dst_tile].width;
-+              dest_height = d_image->tile[dst_tile].height;
-+      }
-+
-+      row = tile / s_image->num_cols;
-+      col = tile % s_image->num_cols;
-+
-+      rsc =  (ctx->downsize_coeff_v << 30) |
-+             (ctx->resize_coeffs_v[row] << 16) |
-+             (ctx->downsize_coeff_h << 14) |
-+             (ctx->resize_coeffs_h[col]);
-+
-+      dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
-+              __func__, s_image->tile[tile].width,
-+              s_image->tile[tile].height, dest_width, dest_height, rsc);
-+
-+      /* setup the IC resizer and CSC */
-+      ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc,
-+                                 s_image->tile[tile].width,
-+                                 s_image->tile[tile].height,
-+                                 dest_width,
-+                                 dest_height,
-+                                 rsc);
-+      if (ret) {
-+              dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* init the source MEM-->IC PP IDMAC channel */
-+      init_idmac_channel(ctx, chan->in_chan, s_image,
-+                         IPU_ROTATE_NONE, false, tile);
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* init the IC PP-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->out_chan, d_image,
-+                                 IPU_ROTATE_NONE, true, tile);
-+
-+              /* init the MEM-->IC PP ROT IDMAC channel */
-+              init_idmac_channel(ctx, chan->rotation_in_chan, d_image,
-+                                 ctx->rot_mode, true, tile);
-+
-+              /* init the destination IC PP ROT-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->rotation_out_chan, d_image,
-+                                 IPU_ROTATE_NONE, false, tile);
-+
-+              /* now link IC PP-->MEM to MEM-->IC PP ROT */
-+              ipu_idmac_link(chan->out_chan, chan->rotation_in_chan);
-+      } else {
-+              /* init the destination IC PP-->MEM IDMAC channel */
-+              init_idmac_channel(ctx, chan->out_chan, d_image,
-+                                 ctx->rot_mode, false, tile);
-+      }
-+
-+      /* enable the IC */
-+      ipu_ic_enable(chan->ic);
-+
-+      /* set buffers ready */
-+      ipu_idmac_select_buffer(chan->in_chan, 0);
-+      ipu_idmac_select_buffer(chan->out_chan, 0);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+              ipu_idmac_select_buffer(chan->rotation_out_chan, 0);
-+      if (ctx->double_buffering) {
-+              ipu_idmac_select_buffer(chan->in_chan, 1);
-+              ipu_idmac_select_buffer(chan->out_chan, 1);
-+              if (ipu_rot_mode_is_irt(ctx->rot_mode))
-+                      ipu_idmac_select_buffer(chan->rotation_out_chan, 1);
-+      }
-+
-+      /* enable the channels! */
-+      ipu_idmac_enable_channel(chan->in_chan);
-+      ipu_idmac_enable_channel(chan->out_chan);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_idmac_enable_channel(chan->rotation_in_chan);
-+              ipu_idmac_enable_channel(chan->rotation_out_chan);
-+      }
-+
-+      ipu_ic_task_enable(chan->ic);
-+
-+      ipu_cpmem_dump(chan->in_chan);
-+      ipu_cpmem_dump(chan->out_chan);
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              ipu_cpmem_dump(chan->rotation_in_chan);
-+              ipu_cpmem_dump(chan->rotation_out_chan);
-+      }
-+
-+      ipu_dump(priv->ipu);
-+
-+      return 0;
-+}
-+
-+/* hold irqlock when calling */
-+static int do_run(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      ctx->in.base.phys0 = run->in_phys;
-+      ctx->out.base.phys0 = run->out_phys;
-+
-+      ctx->cur_buf_num = 0;
-+      ctx->next_tile = 1;
-+
-+      /* remove run from pending_q and set as current */
-+      list_del(&run->list);
-+      chan->current_run = run;
-+
-+      return convert_start(run, 0);
-+}
-+
-+/* hold irqlock when calling */
-+static void run_next(struct ipu_image_convert_chan *chan)
-+{
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run, *tmp;
-+      int ret;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
-+              /* skip contexts that are aborting */
-+              if (run->ctx->aborting) {
-+                      dev_dbg(priv->ipu->dev,
-+                              "%s: task %u: skipping aborting ctx %p run %p\n",
-+                              __func__, chan->ic_task, run->ctx, run);
-+                      continue;
-+              }
-+
-+              ret = do_run(run);
-+              if (!ret)
-+                      break;
-+
-+              /*
-+               * something went wrong with start, add the run
-+               * to done q and continue to the next run in the
-+               * pending q.
-+               */
-+              run->status = ret;
-+              list_add_tail(&run->list, &chan->done_q);
-+              chan->current_run = NULL;
-+      }
-+}
-+
-+static void empty_done_q(struct ipu_image_convert_chan *chan)
-+{
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      while (!list_empty(&chan->done_q)) {
-+              run = list_entry(chan->done_q.next,
-+                               struct ipu_image_convert_run,
-+                               list);
-+
-+              list_del(&run->list);
-+
-+              dev_dbg(priv->ipu->dev,
-+                      "%s: task %u: completing ctx %p run %p with %d\n",
-+                      __func__, chan->ic_task, run->ctx, run, run->status);
-+
-+              /* call the completion callback and free the run */
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              run->ctx->complete(run, run->ctx->complete_context);
-+              spin_lock_irqsave(&chan->irqlock, flags);
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+}
-+
-+/*
-+ * the bottom half thread clears out the done_q, calling the
-+ * completion handler for each.
-+ */
-+static irqreturn_t do_bh(int irq, void *dev_id)
-+{
-+      struct ipu_image_convert_chan *chan = dev_id;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__,
-+              chan->ic_task);
-+
-+      empty_done_q(chan);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /*
-+       * the done_q is cleared out, signal any contexts
-+       * that are aborting that abort can complete.
-+       */
-+      list_for_each_entry(ctx, &chan->ctx_list, list) {
-+              if (ctx->aborting) {
-+                      dev_dbg(priv->ipu->dev,
-+                              "%s: task %u: signaling abort for ctx %p\n",
-+                              __func__, chan->ic_task, ctx);
-+                      complete_all(&ctx->aborted);
-+              }
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__,
-+              chan->ic_task);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx)
-+{
-+      unsigned int cur_tile = ctx->next_tile - 1;
-+      unsigned int next_tile = ctx->next_tile;
-+
-+      if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] !=
-+          ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] ||
-+          ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] !=
-+          ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] ||
-+          ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width ||
-+          ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height ||
-+          ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width ||
-+          ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height)
-+              return true;
-+
-+      return false;
-+}
-+
-+/* hold irqlock when calling */
-+static irqreturn_t do_irq(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_ctx *ctx = run->ctx;
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_tile *src_tile, *dst_tile;
-+      struct ipu_image_convert_image *s_image = &ctx->in;
-+      struct ipu_image_convert_image *d_image = &ctx->out;
-+      struct ipuv3_channel *outch;
-+      unsigned int dst_idx;
-+
-+      lockdep_assert_held(&chan->irqlock);
-+
-+      outch = ipu_rot_mode_is_irt(ctx->rot_mode) ?
-+              chan->rotation_out_chan : chan->out_chan;
-+
-+      /*
-+       * It is difficult to stop the channel DMA before the channels
-+       * enter the paused state. Without double-buffering the channels
-+       * are always in a paused state when the EOF irq occurs, so it
-+       * is safe to stop the channels now. For double-buffering we
-+       * just ignore the abort until the operation completes, when it
-+       * is safe to shut down.
-+       */
-+      if (ctx->aborting && !ctx->double_buffering) {
-+              convert_stop(run);
-+              run->status = -EIO;
-+              goto done;
-+      }
-+
-+      if (ctx->next_tile == ctx->num_tiles) {
-+              /*
-+               * the conversion is complete
-+               */
-+              convert_stop(run);
-+              run->status = 0;
-+              goto done;
-+      }
-+
-+      /*
-+       * not done, place the next tile buffers.
-+       */
-+      if (!ctx->double_buffering) {
-+              if (ic_settings_changed(ctx)) {
-+                      convert_stop(run);
-+                      convert_start(run, ctx->next_tile);
-+              } else {
-+                      src_tile = &s_image->tile[ctx->next_tile];
-+                      dst_idx = ctx->out_tile_map[ctx->next_tile];
-+                      dst_tile = &d_image->tile[dst_idx];
-+
-+                      ipu_cpmem_set_buffer(chan->in_chan, 0,
-+                                           s_image->base.phys0 +
-+                                           src_tile->offset);
-+                      ipu_cpmem_set_buffer(outch, 0,
-+                                           d_image->base.phys0 +
-+                                           dst_tile->offset);
-+                      if (s_image->fmt->planar)
-+                              ipu_cpmem_set_uv_offset(chan->in_chan,
-+                                                      src_tile->u_off,
-+                                                      src_tile->v_off);
-+                      if (d_image->fmt->planar)
-+                              ipu_cpmem_set_uv_offset(outch,
-+                                                      dst_tile->u_off,
-+                                                      dst_tile->v_off);
-+
-+                      ipu_idmac_select_buffer(chan->in_chan, 0);
-+                      ipu_idmac_select_buffer(outch, 0);
-+              }
-+      } else if (ctx->next_tile < ctx->num_tiles - 1) {
-+
-+              src_tile = &s_image->tile[ctx->next_tile + 1];
-+              dst_idx = ctx->out_tile_map[ctx->next_tile + 1];
-+              dst_tile = &d_image->tile[dst_idx];
-+
-+              ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num,
-+                                   s_image->base.phys0 + src_tile->offset);
-+              ipu_cpmem_set_buffer(outch, ctx->cur_buf_num,
-+                                   d_image->base.phys0 + dst_tile->offset);
-+
-+              ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num);
-+              ipu_idmac_select_buffer(outch, ctx->cur_buf_num);
-+
-+              ctx->cur_buf_num ^= 1;
-+      }
-+
-+      ctx->next_tile++;
-+      return IRQ_HANDLED;
-+done:
-+      list_add_tail(&run->list, &chan->done_q);
-+      chan->current_run = NULL;
-+      run_next(chan);
-+      return IRQ_WAKE_THREAD;
-+}
-+
-+static irqreturn_t norotate_irq(int irq, void *data)
-+{
-+      struct ipu_image_convert_chan *chan = data;
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+      irqreturn_t ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* get current run and its context */
-+      run = chan->current_run;
-+      if (!run) {
-+              ret = IRQ_NONE;
-+              goto out;
-+      }
-+
-+      ctx = run->ctx;
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* this is a rotation operation, just ignore */
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              return IRQ_HANDLED;
-+      }
-+
-+      ret = do_irq(run);
-+out:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+
-+static irqreturn_t rotate_irq(int irq, void *data)
-+{
-+      struct ipu_image_convert_chan *chan = data;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+      irqreturn_t ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* get current run and its context */
-+      run = chan->current_run;
-+      if (!run) {
-+              ret = IRQ_NONE;
-+              goto out;
-+      }
-+
-+      ctx = run->ctx;
-+
-+      if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              /* this was NOT a rotation operation, shouldn't happen */
-+              dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
-+              spin_unlock_irqrestore(&chan->irqlock, flags);
-+              return IRQ_HANDLED;
-+      }
-+
-+      ret = do_irq(run);
-+out:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+
-+/*
-+ * try to force the completion of runs for this ctx. Called when
-+ * abort wait times out in ipu_image_convert_abort().
-+ */
-+static void force_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_run *run;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      run = chan->current_run;
-+      if (run && run->ctx == ctx) {
-+              convert_stop(run);
-+              run->status = -EIO;
-+              list_add_tail(&run->list, &chan->done_q);
-+              chan->current_run = NULL;
-+              run_next(chan);
-+      }
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      empty_done_q(chan);
-+}
-+
-+static void release_ipu_resources(struct ipu_image_convert_chan *chan)
-+{
-+      if (chan->out_eof_irq >= 0)
-+              free_irq(chan->out_eof_irq, chan);
-+      if (chan->rot_out_eof_irq >= 0)
-+              free_irq(chan->rot_out_eof_irq, chan);
-+
-+      if (!IS_ERR_OR_NULL(chan->in_chan))
-+              ipu_idmac_put(chan->in_chan);
-+      if (!IS_ERR_OR_NULL(chan->out_chan))
-+              ipu_idmac_put(chan->out_chan);
-+      if (!IS_ERR_OR_NULL(chan->rotation_in_chan))
-+              ipu_idmac_put(chan->rotation_in_chan);
-+      if (!IS_ERR_OR_NULL(chan->rotation_out_chan))
-+              ipu_idmac_put(chan->rotation_out_chan);
-+      if (!IS_ERR_OR_NULL(chan->ic))
-+              ipu_ic_put(chan->ic);
-+
-+      chan->in_chan = chan->out_chan = chan->rotation_in_chan =
-+              chan->rotation_out_chan = NULL;
-+      chan->out_eof_irq = chan->rot_out_eof_irq = -1;
-+}
-+
-+static int get_ipu_resources(struct ipu_image_convert_chan *chan)
-+{
-+      const struct ipu_image_convert_dma_chan *dma = chan->dma_ch;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      int ret;
-+
-+      /* get IC */
-+      chan->ic = ipu_ic_get(priv->ipu, chan->ic_task);
-+      if (IS_ERR(chan->ic)) {
-+              dev_err(priv->ipu->dev, "could not acquire IC\n");
-+              ret = PTR_ERR(chan->ic);
-+              goto err;
-+      }
-+
-+      /* get IDMAC channels */
-+      chan->in_chan = ipu_idmac_get(priv->ipu, dma->in);
-+      chan->out_chan = ipu_idmac_get(priv->ipu, dma->out);
-+      if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) {
-+              dev_err(priv->ipu->dev, "could not acquire idmac channels\n");
-+              ret = -EBUSY;
-+              goto err;
-+      }
-+
-+      chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in);
-+      chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out);
-+      if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) {
-+              dev_err(priv->ipu->dev,
-+                      "could not acquire idmac rotation channels\n");
-+              ret = -EBUSY;
-+              goto err;
-+      }
-+
-+      /* acquire the EOF interrupts */
-+      chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-+                                                chan->out_chan,
-+                                                IPU_IRQ_EOF);
-+
-+      ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
-+                                 0, "ipu-ic", chan);
-+      if (ret < 0) {
-+              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-+                       chan->out_eof_irq);
-+              chan->out_eof_irq = -1;
-+              goto err;
-+      }
-+
-+      chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-+                                                   chan->rotation_out_chan,
-+                                                   IPU_IRQ_EOF);
-+
-+      ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
-+                                 0, "ipu-ic", chan);
-+      if (ret < 0) {
-+              dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-+                      chan->rot_out_eof_irq);
-+              chan->rot_out_eof_irq = -1;
-+              goto err;
-+      }
-+
-+      return 0;
-+err:
-+      release_ipu_resources(chan);
-+      return ret;
-+}
-+
-+static int fill_image(struct ipu_image_convert_ctx *ctx,
-+                    struct ipu_image_convert_image *ic_image,
-+                    struct ipu_image *image,
-+                    enum ipu_image_convert_type type)
-+{
-+      struct ipu_image_convert_priv *priv = ctx->chan->priv;
-+
-+      ic_image->base = *image;
-+      ic_image->type = type;
-+
-+      ic_image->fmt = get_format(image->pix.pixelformat);
-+      if (!ic_image->fmt) {
-+              dev_err(priv->ipu->dev, "pixelformat not supported for %s\n",
-+                      type == IMAGE_CONVERT_OUT ? "Output" : "Input");
-+              return -EINVAL;
-+      }
-+
-+      if (ic_image->fmt->planar)
-+              ic_image->stride = ic_image->base.pix.width;
-+      else
-+              ic_image->stride  = ic_image->base.pix.bytesperline;
-+
-+      return 0;
-+}
-+
-+/* borrowed from drivers/media/v4l2-core/v4l2-common.c */
-+static unsigned int clamp_align(unsigned int x, unsigned int min,
-+                              unsigned int max, unsigned int align)
-+{
-+      /* Bits that must be zero to be aligned */
-+      unsigned int mask = ~((1 << align) - 1);
-+
-+      /* Clamp to aligned min and max */
-+      x = clamp(x, (min + ~mask) & mask, max & mask);
-+
-+      /* Round to nearest aligned value */
-+      if (align)
-+              x = (x + (1 << (align - 1))) & mask;
-+
-+      return x;
-+}
-+
-+/* Adjusts input/output images to IPU restrictions */
-+void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out,
-+                            enum ipu_rotate_mode rot_mode)
-+{
-+      const struct ipu_image_pixfmt *infmt, *outfmt;
-+      u32 w_align_out, h_align_out;
-+      u32 w_align_in, h_align_in;
-+
-+      infmt = get_format(in->pix.pixelformat);
-+      outfmt = get_format(out->pix.pixelformat);
-+
-+      /* set some default pixel formats if needed */
-+      if (!infmt) {
-+              in->pix.pixelformat = V4L2_PIX_FMT_RGB24;
-+              infmt = get_format(V4L2_PIX_FMT_RGB24);
-+      }
-+      if (!outfmt) {
-+              out->pix.pixelformat = V4L2_PIX_FMT_RGB24;
-+              outfmt = get_format(V4L2_PIX_FMT_RGB24);
-+      }
-+
-+      /* image converter does not handle fields */
-+      in->pix.field = out->pix.field = V4L2_FIELD_NONE;
-+
-+      /* resizer cannot downsize more than 4:1 */
-+      if (ipu_rot_mode_is_irt(rot_mode)) {
-+              out->pix.height = max_t(__u32, out->pix.height,
-+                                      in->pix.width / 4);
-+              out->pix.width = max_t(__u32, out->pix.width,
-+                                     in->pix.height / 4);
-+      } else {
-+              out->pix.width = max_t(__u32, out->pix.width,
-+                                     in->pix.width / 4);
-+              out->pix.height = max_t(__u32, out->pix.height,
-+                                      in->pix.height / 4);
-+      }
-+
-+      /* align input width/height */
-+      w_align_in = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt,
-+                                          rot_mode));
-+      h_align_in = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt,
-+                                           rot_mode));
-+      in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W,
-+                                  w_align_in);
-+      in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H,
-+                                   h_align_in);
-+
-+      /* align output width/height */
-+      w_align_out = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt,
-+                                           rot_mode));
-+      h_align_out = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt,
-+                                            rot_mode));
-+      out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W,
-+                                   w_align_out);
-+      out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H,
-+                                    h_align_out);
-+
-+      /* set input/output strides and image sizes */
-+      in->pix.bytesperline = infmt->planar ?
-+              clamp_align(in->pix.width, 2 << w_align_in, MAX_W,
-+                          w_align_in) :
-+              clamp_align((in->pix.width * infmt->bpp) >> 3,
-+                          ((2 << w_align_in) * infmt->bpp) >> 3,
-+                          (MAX_W * infmt->bpp) >> 3,
-+                          w_align_in);
-+      in->pix.sizeimage = infmt->planar ?
-+              (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 :
-+              in->pix.height * in->pix.bytesperline;
-+      out->pix.bytesperline = outfmt->planar ? out->pix.width :
-+              (out->pix.width * outfmt->bpp) >> 3;
-+      out->pix.sizeimage = outfmt->planar ?
-+              (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 :
-+              out->pix.height * out->pix.bytesperline;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_adjust);
-+
-+/*
-+ * this is used by ipu_image_convert_prepare() to verify set input and
-+ * output images are valid before starting the conversion. Clients can
-+ * also call it before calling ipu_image_convert_prepare().
-+ */
-+int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
-+                           enum ipu_rotate_mode rot_mode)
-+{
-+      struct ipu_image testin, testout;
-+
-+      testin = *in;
-+      testout = *out;
-+
-+      ipu_image_convert_adjust(&testin, &testout, rot_mode);
-+
-+      if (testin.pix.width != in->pix.width ||
-+          testin.pix.height != in->pix.height ||
-+          testout.pix.width != out->pix.width ||
-+          testout.pix.height != out->pix.height)
-+              return -EINVAL;
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_verify);
-+
-+/*
-+ * Call ipu_image_convert_prepare() to prepare for the conversion of
-+ * given images and rotation mode. Returns a new conversion context.
-+ */
-+struct ipu_image_convert_ctx *
-+ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                        struct ipu_image *in, struct ipu_image *out,
-+                        enum ipu_rotate_mode rot_mode,
-+                        ipu_image_convert_cb_t complete,
-+                        void *complete_context)
-+{
-+      struct ipu_image_convert_priv *priv = ipu->image_convert_priv;
-+      struct ipu_image_convert_image *s_image, *d_image;
-+      struct ipu_image_convert_chan *chan;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+      unsigned int i;
-+      bool get_res;
-+      int ret;
-+
-+      if (!in || !out || !complete ||
-+          (ic_task != IC_TASK_VIEWFINDER &&
-+           ic_task != IC_TASK_POST_PROCESSOR))
-+              return ERR_PTR(-EINVAL);
-+
-+      /* verify the in/out images before continuing */
-+      ret = ipu_image_convert_verify(in, out, rot_mode);
-+      if (ret) {
-+              dev_err(priv->ipu->dev, "%s: in/out formats invalid\n",
-+                      __func__);
-+              return ERR_PTR(ret);
-+      }
-+
-+      chan = &priv->chan[ic_task];
-+
-+      ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-+      if (!ctx)
-+              return ERR_PTR(-ENOMEM);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__,
-+              chan->ic_task, ctx);
-+
-+      ctx->chan = chan;
-+      init_completion(&ctx->aborted);
-+
-+      ctx->rot_mode = rot_mode;
-+
-+      /* Sets ctx->in.num_rows/cols as well */
-+      ret = calc_image_resize_coefficients(ctx, in, out);
-+      if (ret)
-+              goto out_free;
-+
-+      s_image = &ctx->in;
-+      d_image = &ctx->out;
-+
-+      /* set tiling and rotation */
-+      if (ipu_rot_mode_is_irt(rot_mode)) {
-+              d_image->num_rows = s_image->num_cols;
-+              d_image->num_cols = s_image->num_rows;
-+      } else {
-+              d_image->num_rows = s_image->num_rows;
-+              d_image->num_cols = s_image->num_cols;
-+      }
-+
-+      ctx->num_tiles = d_image->num_cols * d_image->num_rows;
-+
-+      ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
-+      if (ret)
-+              goto out_free;
-+      ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_out_tile_map(ctx);
-+
-+      find_seams(ctx, s_image, d_image);
-+
-+      ret = calc_tile_dimensions(ctx, s_image);
-+      if (ret)
-+              goto out_free;
-+
-+      ret = calc_tile_offsets(ctx, s_image);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_tile_dimensions(ctx, d_image);
-+      ret = calc_tile_offsets(ctx, d_image);
-+      if (ret)
-+              goto out_free;
-+
-+      calc_tile_resize_coefficients(ctx);
-+
-+      ret = ipu_ic_calc_csc(&ctx->csc,
-+                      s_image->base.pix.ycbcr_enc,
-+                      s_image->base.pix.quantization,
-+                      ipu_pixelformat_to_colorspace(s_image->fmt->fourcc),
-+                      d_image->base.pix.ycbcr_enc,
-+                      d_image->base.pix.quantization,
-+                      ipu_pixelformat_to_colorspace(d_image->fmt->fourcc));
-+      if (ret)
-+              goto out_free;
-+
-+      dump_format(ctx, s_image);
-+      dump_format(ctx, d_image);
-+
-+      ctx->complete = complete;
-+      ctx->complete_context = complete_context;
-+
-+      /*
-+       * Can we use double-buffering for this operation? If there is
-+       * only one tile (the whole image can be converted in a single
-+       * operation) there's no point in using double-buffering. Also,
-+       * the IPU's IDMAC channels allow only a single U and V plane
-+       * offset shared between both buffers, but these offsets change
-+       * for every tile, and therefore would have to be updated for
-+       * each buffer which is not possible. So double-buffering is
-+       * impossible when either the source or destination images are
-+       * a planar format (YUV420, YUV422P, etc.). Further, differently
-+       * sized tiles or different resizing coefficients per tile
-+       * prevent double-buffering as well.
-+       */
-+      ctx->double_buffering = (ctx->num_tiles > 1 &&
-+                               !s_image->fmt->planar &&
-+                               !d_image->fmt->planar);
-+      for (i = 1; i < ctx->num_tiles; i++) {
-+              if (ctx->in.tile[i].width != ctx->in.tile[0].width ||
-+                  ctx->in.tile[i].height != ctx->in.tile[0].height ||
-+                  ctx->out.tile[i].width != ctx->out.tile[0].width ||
-+                  ctx->out.tile[i].height != ctx->out.tile[0].height) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+      for (i = 1; i < ctx->in.num_cols; i++) {
-+              if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+      for (i = 1; i < ctx->in.num_rows; i++) {
-+              if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) {
-+                      ctx->double_buffering = false;
-+                      break;
-+              }
-+      }
-+
-+      if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-+              unsigned long intermediate_size = d_image->tile[0].size;
-+
-+              for (i = 1; i < ctx->num_tiles; i++) {
-+                      if (d_image->tile[i].size > intermediate_size)
-+                              intermediate_size = d_image->tile[i].size;
-+              }
-+
-+              ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0],
-+                                  intermediate_size);
-+              if (ret)
-+                      goto out_free;
-+              if (ctx->double_buffering) {
-+                      ret = alloc_dma_buf(priv,
-+                                          &ctx->rot_intermediate[1],
-+                                          intermediate_size);
-+                      if (ret)
-+                              goto out_free_dmabuf0;
-+              }
-+      }
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      get_res = list_empty(&chan->ctx_list);
-+
-+      list_add_tail(&ctx->list, &chan->ctx_list);
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (get_res) {
-+              ret = get_ipu_resources(chan);
-+              if (ret)
-+                      goto out_free_dmabuf1;
-+      }
-+
-+      return ctx;
-+
-+out_free_dmabuf1:
-+      free_dma_buf(priv, &ctx->rot_intermediate[1]);
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+      list_del(&ctx->list);
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+out_free_dmabuf0:
-+      free_dma_buf(priv, &ctx->rot_intermediate[0]);
-+out_free:
-+      kfree(ctx);
-+      return ERR_PTR(ret);
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_prepare);
-+
-+/*
-+ * Carry out a single image conversion run. Only the physaddr's of the input
-+ * and output image buffers are needed. The conversion context must have
-+ * been created previously with ipu_image_convert_prepare().
-+ */
-+int ipu_image_convert_queue(struct ipu_image_convert_run *run)
-+{
-+      struct ipu_image_convert_chan *chan;
-+      struct ipu_image_convert_priv *priv;
-+      struct ipu_image_convert_ctx *ctx;
-+      unsigned long flags;
-+      int ret = 0;
-+
-+      if (!run || !run->ctx || !run->in_phys || !run->out_phys)
-+              return -EINVAL;
-+
-+      ctx = run->ctx;
-+      chan = ctx->chan;
-+      priv = chan->priv;
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__,
-+              chan->ic_task, ctx, run);
-+
-+      INIT_LIST_HEAD(&run->list);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      if (ctx->aborting) {
-+              ret = -EIO;
-+              goto unlock;
-+      }
-+
-+      list_add_tail(&run->list, &chan->pending_q);
-+
-+      if (!chan->current_run) {
-+              ret = do_run(run);
-+              if (ret)
-+                      chan->current_run = NULL;
-+      }
-+unlock:
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_queue);
-+
-+/* Abort any active or pending conversions for this context */
-+static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      struct ipu_image_convert_run *run, *active_run, *tmp;
-+      unsigned long flags;
-+      int run_count, ret;
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      /* move all remaining pending runs in this context to done_q */
-+      list_for_each_entry_safe(run, tmp, &chan->pending_q, list) {
-+              if (run->ctx != ctx)
-+                      continue;
-+              run->status = -EIO;
-+              list_move_tail(&run->list, &chan->done_q);
-+      }
-+
-+      run_count = get_run_count(ctx, &chan->done_q);
-+      active_run = (chan->current_run && chan->current_run->ctx == ctx) ?
-+              chan->current_run : NULL;
-+
-+      if (active_run)
-+              reinit_completion(&ctx->aborted);
-+
-+      ctx->aborting = true;
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (!run_count && !active_run) {
-+              dev_dbg(priv->ipu->dev,
-+                      "%s: task %u: no abort needed for ctx %p\n",
-+                      __func__, chan->ic_task, ctx);
-+              return;
-+      }
-+
-+      if (!active_run) {
-+              empty_done_q(chan);
-+              return;
-+      }
-+
-+      dev_dbg(priv->ipu->dev,
-+              "%s: task %u: wait for completion: %d runs\n",
-+              __func__, chan->ic_task, run_count);
-+
-+      ret = wait_for_completion_timeout(&ctx->aborted,
-+                                        msecs_to_jiffies(10000));
-+      if (ret == 0) {
-+              dev_warn(priv->ipu->dev, "%s: timeout\n", __func__);
-+              force_abort(ctx);
-+      }
-+}
-+
-+void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx)
-+{
-+      __ipu_image_convert_abort(ctx);
-+      ctx->aborting = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_abort);
-+
-+/* Unprepare image conversion context */
-+void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx)
-+{
-+      struct ipu_image_convert_chan *chan = ctx->chan;
-+      struct ipu_image_convert_priv *priv = chan->priv;
-+      unsigned long flags;
-+      bool put_res;
-+
-+      /* make sure no runs are hanging around */
-+      __ipu_image_convert_abort(ctx);
-+
-+      dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__,
-+              chan->ic_task, ctx);
-+
-+      spin_lock_irqsave(&chan->irqlock, flags);
-+
-+      list_del(&ctx->list);
-+
-+      put_res = list_empty(&chan->ctx_list);
-+
-+      spin_unlock_irqrestore(&chan->irqlock, flags);
-+
-+      if (put_res)
-+              release_ipu_resources(chan);
-+
-+      free_dma_buf(priv, &ctx->rot_intermediate[1]);
-+      free_dma_buf(priv, &ctx->rot_intermediate[0]);
-+
-+      kfree(ctx);
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare);
-+
-+/*
-+ * "Canned" asynchronous single image conversion. Allocates and returns
-+ * a new conversion run.  On successful return the caller must free the
-+ * run and call ipu_image_convert_unprepare() after conversion completes.
-+ */
-+struct ipu_image_convert_run *
-+ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                struct ipu_image *in, struct ipu_image *out,
-+                enum ipu_rotate_mode rot_mode,
-+                ipu_image_convert_cb_t complete,
-+                void *complete_context)
-+{
-+      struct ipu_image_convert_ctx *ctx;
-+      struct ipu_image_convert_run *run;
-+      int ret;
-+
-+      ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,
-+                                      complete, complete_context);
-+      if (IS_ERR(ctx))
-+              return ERR_CAST(ctx);
-+
-+      run = kzalloc(sizeof(*run), GFP_KERNEL);
-+      if (!run) {
-+              ipu_image_convert_unprepare(ctx);
-+              return ERR_PTR(-ENOMEM);
-+      }
-+
-+      run->ctx = ctx;
-+      run->in_phys = in->phys0;
-+      run->out_phys = out->phys0;
-+
-+      ret = ipu_image_convert_queue(run);
-+      if (ret) {
-+              ipu_image_convert_unprepare(ctx);
-+              kfree(run);
-+              return ERR_PTR(ret);
-+      }
-+
-+      return run;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert);
-+
-+/* "Canned" synchronous single image conversion */
-+static void image_convert_sync_complete(struct ipu_image_convert_run *run,
-+                                      void *data)
-+{
-+      struct completion *comp = data;
-+
-+      complete(comp);
-+}
-+
-+int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
-+                         struct ipu_image *in, struct ipu_image *out,
-+                         enum ipu_rotate_mode rot_mode)
-+{
-+      struct ipu_image_convert_run *run;
-+      struct completion comp;
-+      int ret;
-+
-+      init_completion(&comp);
-+
-+      run = ipu_image_convert(ipu, ic_task, in, out, rot_mode,
-+                              image_convert_sync_complete, &comp);
-+      if (IS_ERR(run))
-+              return PTR_ERR(run);
-+
-+      ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000));
-+      ret = (ret == 0) ? -ETIMEDOUT : 0;
-+
-+      ipu_image_convert_unprepare(run->ctx);
-+      kfree(run);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_image_convert_sync);
-+
-+int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev)
-+{
-+      struct ipu_image_convert_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->image_convert_priv = priv;
-+      priv->ipu = ipu;
-+
-+      for (i = 0; i < IC_NUM_TASKS; i++) {
-+              struct ipu_image_convert_chan *chan = &priv->chan[i];
-+
-+              chan->ic_task = i;
-+              chan->priv = priv;
-+              chan->dma_ch = &image_convert_dma_chan[i];
-+              chan->out_eof_irq = -1;
-+              chan->rot_out_eof_irq = -1;
-+
-+              spin_lock_init(&chan->irqlock);
-+              INIT_LIST_HEAD(&chan->ctx_list);
-+              INIT_LIST_HEAD(&chan->pending_q);
-+              INIT_LIST_HEAD(&chan->done_q);
-+      }
-+
-+      return 0;
-+}
-+
-+void ipu_image_convert_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-pre.c
-@@ -0,0 +1,346 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (c) 2017 Lucas Stach, Pengutronix
-+ */
-+
-+#include <drm/drm_fourcc.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/genalloc.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+#define IPU_PRE_MAX_WIDTH     2048
-+#define IPU_PRE_NUM_SCANLINES 8
-+
-+#define IPU_PRE_CTRL                                  0x000
-+#define IPU_PRE_CTRL_SET                              0x004
-+#define  IPU_PRE_CTRL_ENABLE                          (1 << 0)
-+#define  IPU_PRE_CTRL_BLOCK_EN                                (1 << 1)
-+#define  IPU_PRE_CTRL_BLOCK_16                                (1 << 2)
-+#define  IPU_PRE_CTRL_SDW_UPDATE                      (1 << 4)
-+#define  IPU_PRE_CTRL_VFLIP                           (1 << 5)
-+#define  IPU_PRE_CTRL_SO                              (1 << 6)
-+#define  IPU_PRE_CTRL_INTERLACED_FIELD                        (1 << 7)
-+#define  IPU_PRE_CTRL_HANDSHAKE_EN                    (1 << 8)
-+#define  IPU_PRE_CTRL_HANDSHAKE_LINE_NUM(v)           ((v & 0x3) << 9)
-+#define  IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN         (1 << 11)
-+#define  IPU_PRE_CTRL_EN_REPEAT                               (1 << 28)
-+#define  IPU_PRE_CTRL_TPR_REST_SEL                    (1 << 29)
-+#define  IPU_PRE_CTRL_CLKGATE                         (1 << 30)
-+#define  IPU_PRE_CTRL_SFTRST                          (1 << 31)
-+
-+#define IPU_PRE_CUR_BUF                                       0x030
-+
-+#define IPU_PRE_NEXT_BUF                              0x040
-+
-+#define IPU_PRE_TPR_CTRL                              0x070
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT(v)              ((v & 0xff) << 0)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK            0xff
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT          (1 << 0)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SPLIT_BUF               (1 << 4)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF      (1 << 5)
-+#define  IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED     (1 << 6)
-+
-+#define IPU_PRE_PREFETCH_ENG_CTRL                     0x080
-+#define  IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN            (1 << 0)
-+#define  IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(v)                ((v & 0x7) << 1)
-+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(v)    ((v & 0x3) << 4)
-+#define  IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(v)  ((v & 0x7) << 8)
-+#define  IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS           (1 << 11)
-+#define  IPU_PRE_PREF_ENG_CTRL_FIELD_INVERSE          (1 << 12)
-+#define  IPU_PRE_PREF_ENG_CTRL_PARTIAL_UV_SWAP                (1 << 14)
-+#define  IPU_PRE_PREF_ENG_CTRL_TPR_COOR_OFFSET_EN     (1 << 15)
-+
-+#define IPU_PRE_PREFETCH_ENG_INPUT_SIZE                       0x0a0
-+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(v)     ((v & 0xffff) << 0)
-+#define  IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(v)    ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_PREFETCH_ENG_PITCH                    0x0d0
-+#define  IPU_PRE_PREFETCH_ENG_PITCH_Y(v)              ((v & 0xffff) << 0)
-+#define  IPU_PRE_PREFETCH_ENG_PITCH_UV(v)             ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_STORE_ENG_CTRL                                0x110
-+#define  IPU_PRE_STORE_ENG_CTRL_STORE_EN              (1 << 0)
-+#define  IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v)               ((v & 0x7) << 1)
-+#define  IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v)  ((v & 0x3) << 4)
-+
-+#define IPU_PRE_STORE_ENG_STATUS                      0x120
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK  0xffff
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK  0x3fff
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL     (1 << 30)
-+#define  IPU_PRE_STORE_ENG_STATUS_STORE_FIELD         (1 << 31)
-+
-+#define IPU_PRE_STORE_ENG_SIZE                                0x130
-+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v)                ((v & 0xffff) << 0)
-+#define  IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v)               ((v & 0xffff) << 16)
-+
-+#define IPU_PRE_STORE_ENG_PITCH                               0x140
-+#define  IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(v)         ((v & 0xffff) << 0)
-+
-+#define IPU_PRE_STORE_ENG_ADDR                                0x150
-+
-+struct ipu_pre {
-+      struct list_head        list;
-+      struct device           *dev;
-+
-+      void __iomem            *regs;
-+      struct clk              *clk_axi;
-+      struct gen_pool         *iram;
-+
-+      dma_addr_t              buffer_paddr;
-+      void                    *buffer_virt;
-+      bool                    in_use;
-+      unsigned int            safe_window_end;
-+      unsigned int            last_bufaddr;
-+};
-+
-+static DEFINE_MUTEX(ipu_pre_list_mutex);
-+static LIST_HEAD(ipu_pre_list);
-+static int available_pres;
-+
-+int ipu_pre_get_available_count(void)
-+{
-+      return available_pres;
-+}
-+
-+struct ipu_pre *
-+ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
-+{
-+      struct device_node *pre_node = of_parse_phandle(dev->of_node,
-+                                                      name, index);
-+      struct ipu_pre *pre;
-+
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_for_each_entry(pre, &ipu_pre_list, list) {
-+              if (pre_node == pre->dev->of_node) {
-+                      mutex_unlock(&ipu_pre_list_mutex);
-+                      device_link_add(dev, pre->dev,
-+                                      DL_FLAG_AUTOREMOVE_CONSUMER);
-+                      of_node_put(pre_node);
-+                      return pre;
-+              }
-+      }
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      of_node_put(pre_node);
-+
-+      return NULL;
-+}
-+
-+int ipu_pre_get(struct ipu_pre *pre)
-+{
-+      u32 val;
-+
-+      if (pre->in_use)
-+              return -EBUSY;
-+
-+      /* first get the engine out of reset and remove clock gating */
-+      writel(0, pre->regs + IPU_PRE_CTRL);
-+
-+      /* init defaults that should be applied to all streams */
-+      val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
-+            IPU_PRE_CTRL_HANDSHAKE_EN |
-+            IPU_PRE_CTRL_TPR_REST_SEL |
-+            IPU_PRE_CTRL_SDW_UPDATE;
-+      writel(val, pre->regs + IPU_PRE_CTRL);
-+
-+      pre->in_use = true;
-+      return 0;
-+}
-+
-+void ipu_pre_put(struct ipu_pre *pre)
-+{
-+      writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
-+
-+      pre->in_use = false;
-+}
-+
-+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
-+                     unsigned int height, unsigned int stride, u32 format,
-+                     uint64_t modifier, unsigned int bufaddr)
-+{
-+      const struct drm_format_info *info = drm_format_info(format);
-+      u32 active_bpp = info->cpp[0] >> 1;
-+      u32 val;
-+
-+      /* calculate safe window for ctrl register updates */
-+      if (modifier == DRM_FORMAT_MOD_LINEAR)
-+              pre->safe_window_end = height - 2;
-+      else
-+              pre->safe_window_end = DIV_ROUND_UP(height, 4) - 1;
-+
-+      writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
-+      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
-+      pre->last_bufaddr = bufaddr;
-+
-+      val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
-+            IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
-+            IPU_PRE_PREF_ENG_CTRL_RD_NUM_BYTES(4) |
-+            IPU_PRE_PREF_ENG_CTRL_SHIFT_BYPASS |
-+            IPU_PRE_PREF_ENG_CTRL_PREFETCH_EN;
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_CTRL);
-+
-+      val = IPU_PRE_PREFETCH_ENG_INPUT_SIZE_WIDTH(width) |
-+            IPU_PRE_PREFETCH_ENG_INPUT_SIZE_HEIGHT(height);
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_INPUT_SIZE);
-+
-+      val = IPU_PRE_PREFETCH_ENG_PITCH_Y(stride);
-+      writel(val, pre->regs + IPU_PRE_PREFETCH_ENG_PITCH);
-+
-+      val = IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(active_bpp) |
-+            IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(4) |
-+            IPU_PRE_STORE_ENG_CTRL_STORE_EN;
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_CTRL);
-+
-+      val = IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(width) |
-+            IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(height);
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_SIZE);
-+
-+      val = IPU_PRE_STORE_ENG_PITCH_OUT_PITCH(stride);
-+      writel(val, pre->regs + IPU_PRE_STORE_ENG_PITCH);
-+
-+      writel(pre->buffer_paddr, pre->regs + IPU_PRE_STORE_ENG_ADDR);
-+
-+      val = readl(pre->regs + IPU_PRE_TPR_CTRL);
-+      val &= ~IPU_PRE_TPR_CTRL_TILE_FORMAT_MASK;
-+      if (modifier != DRM_FORMAT_MOD_LINEAR) {
-+              /* only support single buffer formats for now */
-+              val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SINGLE_BUF;
-+              if (modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED)
-+                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_SUPER_TILED;
-+              if (info->cpp[0] == 2)
-+                      val |= IPU_PRE_TPR_CTRL_TILE_FORMAT_16_BIT;
-+      }
-+      writel(val, pre->regs + IPU_PRE_TPR_CTRL);
-+
-+      val = readl(pre->regs + IPU_PRE_CTRL);
-+      val |= IPU_PRE_CTRL_EN_REPEAT | IPU_PRE_CTRL_ENABLE |
-+             IPU_PRE_CTRL_SDW_UPDATE;
-+      if (modifier == DRM_FORMAT_MOD_LINEAR)
-+              val &= ~IPU_PRE_CTRL_BLOCK_EN;
-+      else
-+              val |= IPU_PRE_CTRL_BLOCK_EN;
-+      writel(val, pre->regs + IPU_PRE_CTRL);
-+}
-+
-+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
-+{
-+      unsigned long timeout = jiffies + msecs_to_jiffies(5);
-+      unsigned short current_yblock;
-+      u32 val;
-+
-+      if (bufaddr == pre->last_bufaddr)
-+              return;
-+
-+      writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
-+      pre->last_bufaddr = bufaddr;
-+
-+      do {
-+              if (time_after(jiffies, timeout)) {
-+                      dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
-+                      return;
-+              }
-+
-+              val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS);
-+              current_yblock =
-+                      (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
-+                      IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
-+      } while (current_yblock == 0 || current_yblock >= pre->safe_window_end);
-+
-+      writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET);
-+}
-+
-+bool ipu_pre_update_pending(struct ipu_pre *pre)
-+{
-+      return !!(readl_relaxed(pre->regs + IPU_PRE_CTRL) &
-+                IPU_PRE_CTRL_SDW_UPDATE);
-+}
-+
-+u32 ipu_pre_get_baddr(struct ipu_pre *pre)
-+{
-+      return (u32)pre->buffer_paddr;
-+}
-+
-+static int ipu_pre_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct resource *res;
-+      struct ipu_pre *pre;
-+
-+      pre = devm_kzalloc(dev, sizeof(*pre), GFP_KERNEL);
-+      if (!pre)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      pre->regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(pre->regs))
-+              return PTR_ERR(pre->regs);
-+
-+      pre->clk_axi = devm_clk_get(dev, "axi");
-+      if (IS_ERR(pre->clk_axi))
-+              return PTR_ERR(pre->clk_axi);
-+
-+      pre->iram = of_gen_pool_get(dev->of_node, "fsl,iram", 0);
-+      if (!pre->iram)
-+              return -EPROBE_DEFER;
-+
-+      /*
-+       * Allocate IRAM buffer with maximum size. This could be made dynamic,
-+       * but as there is no other user of this IRAM region and we can fit all
-+       * max sized buffers into it, there is no need yet.
-+       */
-+      pre->buffer_virt = gen_pool_dma_alloc(pre->iram, IPU_PRE_MAX_WIDTH *
-+                                            IPU_PRE_NUM_SCANLINES * 4,
-+                                            &pre->buffer_paddr);
-+      if (!pre->buffer_virt)
-+              return -ENOMEM;
-+
-+      clk_prepare_enable(pre->clk_axi);
-+
-+      pre->dev = dev;
-+      platform_set_drvdata(pdev, pre);
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_add(&pre->list, &ipu_pre_list);
-+      available_pres++;
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      return 0;
-+}
-+
-+static int ipu_pre_remove(struct platform_device *pdev)
-+{
-+      struct ipu_pre *pre = platform_get_drvdata(pdev);
-+
-+      mutex_lock(&ipu_pre_list_mutex);
-+      list_del(&pre->list);
-+      available_pres--;
-+      mutex_unlock(&ipu_pre_list_mutex);
-+
-+      clk_disable_unprepare(pre->clk_axi);
-+
-+      if (pre->buffer_virt)
-+              gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
-+                            IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
-+      return 0;
-+}
-+
-+static const struct of_device_id ipu_pre_dt_ids[] = {
-+      { .compatible = "fsl,imx6qp-pre", },
-+      { /* sentinel */ },
-+};
-+
-+struct platform_driver ipu_pre_drv = {
-+      .probe          = ipu_pre_probe,
-+      .remove         = ipu_pre_remove,
-+      .driver         = {
-+              .name   = "imx-ipu-pre",
-+              .of_match_table = ipu_pre_dt_ids,
-+      },
-+};
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-prg.c
-@@ -0,0 +1,483 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (c) 2016-2017 Lucas Stach, Pengutronix
-+ */
-+
-+#include <drm/drm_fourcc.h>
-+#include <linux/clk.h>
-+#include <linux/err.h>
-+#include <linux/iopoll.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regmap.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+#define IPU_PRG_CTL                           0x00
-+#define  IPU_PRG_CTL_BYPASS(i)                        (1 << (0 + i))
-+#define  IPU_PRG_CTL_SOFT_ARID_MASK           0x3
-+#define  IPU_PRG_CTL_SOFT_ARID_SHIFT(i)               (8 + i * 2)
-+#define  IPU_PRG_CTL_SOFT_ARID(i, v)          ((v & 0x3) << (8 + 2 * i))
-+#define  IPU_PRG_CTL_SO(i)                    (1 << (16 + i))
-+#define  IPU_PRG_CTL_VFLIP(i)                 (1 << (19 + i))
-+#define  IPU_PRG_CTL_BLOCK_MODE(i)            (1 << (22 + i))
-+#define  IPU_PRG_CTL_CNT_LOAD_EN(i)           (1 << (25 + i))
-+#define  IPU_PRG_CTL_SOFTRST                  (1 << 30)
-+#define  IPU_PRG_CTL_SHADOW_EN                        (1 << 31)
-+
-+#define IPU_PRG_STATUS                                0x04
-+#define  IPU_PRG_STATUS_BUFFER0_READY(i)      (1 << (0 + i * 2))
-+#define  IPU_PRG_STATUS_BUFFER1_READY(i)      (1 << (1 + i * 2))
-+
-+#define IPU_PRG_QOS                           0x08
-+#define  IPU_PRG_QOS_ARID_MASK                        0xf
-+#define  IPU_PRG_QOS_ARID_SHIFT(i)            (0 + i * 4)
-+
-+#define IPU_PRG_REG_UPDATE                    0x0c
-+#define  IPU_PRG_REG_UPDATE_REG_UPDATE                (1 << 0)
-+
-+#define IPU_PRG_STRIDE(i)                     (0x10 + i * 0x4)
-+#define  IPU_PRG_STRIDE_STRIDE_MASK           0x3fff
-+
-+#define IPU_PRG_CROP_LINE                     0x1c
-+
-+#define IPU_PRG_THD                           0x20
-+
-+#define IPU_PRG_BADDR(i)                      (0x24 + i * 0x4)
-+
-+#define IPU_PRG_OFFSET(i)                     (0x30 + i * 0x4)
-+
-+#define IPU_PRG_ILO(i)                                (0x3c + i * 0x4)
-+
-+#define IPU_PRG_HEIGHT(i)                     (0x48 + i * 0x4)
-+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_MASK               0xfff
-+#define  IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT      0
-+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_MASK               0xfff
-+#define  IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT      16
-+
-+struct ipu_prg_channel {
-+      bool                    enabled;
-+      int                     used_pre;
-+};
-+
-+struct ipu_prg {
-+      struct list_head        list;
-+      struct device           *dev;
-+      int                     id;
-+
-+      void __iomem            *regs;
-+      struct clk              *clk_ipg, *clk_axi;
-+      struct regmap           *iomuxc_gpr;
-+      struct ipu_pre          *pres[3];
-+
-+      struct ipu_prg_channel  chan[3];
-+};
-+
-+static DEFINE_MUTEX(ipu_prg_list_mutex);
-+static LIST_HEAD(ipu_prg_list);
-+
-+struct ipu_prg *
-+ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id)
-+{
-+      struct device_node *prg_node = of_parse_phandle(dev->of_node,
-+                                                      name, 0);
-+      struct ipu_prg *prg;
-+
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_for_each_entry(prg, &ipu_prg_list, list) {
-+              if (prg_node == prg->dev->of_node) {
-+                      mutex_unlock(&ipu_prg_list_mutex);
-+                      device_link_add(dev, prg->dev,
-+                                      DL_FLAG_AUTOREMOVE_CONSUMER);
-+                      prg->id = ipu_id;
-+                      of_node_put(prg_node);
-+                      return prg;
-+              }
-+      }
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      of_node_put(prg_node);
-+
-+      return NULL;
-+}
-+
-+int ipu_prg_max_active_channels(void)
-+{
-+      return ipu_pre_get_available_count();
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_max_active_channels);
-+
-+bool ipu_prg_present(struct ipu_soc *ipu)
-+{
-+      if (ipu->prg_priv)
-+              return true;
-+
-+      return false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_present);
-+
-+bool ipu_prg_format_supported(struct ipu_soc *ipu, uint32_t format,
-+                            uint64_t modifier)
-+{
-+      const struct drm_format_info *info = drm_format_info(format);
-+
-+      if (info->num_planes != 1)
-+              return false;
-+
-+      switch (modifier) {
-+      case DRM_FORMAT_MOD_LINEAR:
-+      case DRM_FORMAT_MOD_VIVANTE_TILED:
-+      case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
-+              return true;
-+      default:
-+              return false;
-+      }
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_format_supported);
-+
-+int ipu_prg_enable(struct ipu_soc *ipu)
-+{
-+      struct ipu_prg *prg = ipu->prg_priv;
-+
-+      if (!prg)
-+              return 0;
-+
-+      return pm_runtime_get_sync(prg->dev);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_enable);
-+
-+void ipu_prg_disable(struct ipu_soc *ipu)
-+{
-+      struct ipu_prg *prg = ipu->prg_priv;
-+
-+      if (!prg)
-+              return;
-+
-+      pm_runtime_put(prg->dev);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_disable);
-+
-+/*
-+ * The channel configuartion functions below are not thread safe, as they
-+ * must be only called from the atomic commit path in the DRM driver, which
-+ * is properly serialized.
-+ */
-+static int ipu_prg_ipu_to_prg_chan(int ipu_chan)
-+{
-+      /*
-+       * This isn't clearly documented in the RM, but IPU to PRG channel
-+       * assignment is fixed, as only with this mapping the control signals
-+       * match up.
-+       */
-+      switch (ipu_chan) {
-+      case IPUV3_CHANNEL_MEM_BG_SYNC:
-+              return 0;
-+      case IPUV3_CHANNEL_MEM_FG_SYNC:
-+              return 1;
-+      case IPUV3_CHANNEL_MEM_DC_SYNC:
-+              return 2;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static int ipu_prg_get_pre(struct ipu_prg *prg, int prg_chan)
-+{
-+      int i, ret;
-+
-+      /* channel 0 is special as it is hardwired to one of the PREs */
-+      if (prg_chan == 0) {
-+              ret = ipu_pre_get(prg->pres[0]);
-+              if (ret)
-+                      goto fail;
-+              prg->chan[prg_chan].used_pre = 0;
-+              return 0;
-+      }
-+
-+      for (i = 1; i < 3; i++) {
-+              ret = ipu_pre_get(prg->pres[i]);
-+              if (!ret) {
-+                      u32 val, mux;
-+                      int shift;
-+
-+                      prg->chan[prg_chan].used_pre = i;
-+
-+                      /* configure the PRE to PRG channel mux */
-+                      shift = (i == 1) ? 12 : 14;
-+                      mux = (prg->id << 1) | (prg_chan - 1);
-+                      regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
-+                                         0x3 << shift, mux << shift);
-+
-+                      /* check other mux, must not point to same channel */
-+                      shift = (i == 1) ? 14 : 12;
-+                      regmap_read(prg->iomuxc_gpr, IOMUXC_GPR5, &val);
-+                      if (((val >> shift) & 0x3) == mux) {
-+                              regmap_update_bits(prg->iomuxc_gpr, IOMUXC_GPR5,
-+                                                 0x3 << shift,
-+                                                 (mux ^ 0x1) << shift);
-+                      }
-+
-+                      return 0;
-+              }
-+      }
-+
-+fail:
-+      dev_err(prg->dev, "could not get PRE for PRG chan %d", prg_chan);
-+      return ret;
-+}
-+
-+static void ipu_prg_put_pre(struct ipu_prg *prg, int prg_chan)
-+{
-+      struct ipu_prg_channel *chan = &prg->chan[prg_chan];
-+
-+      ipu_pre_put(prg->pres[chan->used_pre]);
-+      chan->used_pre = -1;
-+}
-+
-+void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+      u32 val;
-+
-+      if (prg_chan < 0)
-+              return;
-+
-+      chan = &prg->chan[prg_chan];
-+      if (!chan->enabled)
-+              return;
-+
-+      pm_runtime_get_sync(prg->dev);
-+
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      val |= IPU_PRG_CTL_BYPASS(prg_chan);
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
-+      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
-+
-+      pm_runtime_put(prg->dev);
-+
-+      ipu_prg_put_pre(prg, prg_chan);
-+
-+      chan->enabled = false;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_disable);
-+
-+int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan,
-+                            unsigned int axi_id, unsigned int width,
-+                            unsigned int height, unsigned int stride,
-+                            u32 format, uint64_t modifier, unsigned long *eba)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+      u32 val;
-+      int ret;
-+
-+      if (prg_chan < 0)
-+              return prg_chan;
-+
-+      chan = &prg->chan[prg_chan];
-+
-+      if (chan->enabled) {
-+              ipu_pre_update(prg->pres[chan->used_pre], *eba);
-+              return 0;
-+      }
-+
-+      ret = ipu_prg_get_pre(prg, prg_chan);
-+      if (ret)
-+              return ret;
-+
-+      ipu_pre_configure(prg->pres[chan->used_pre],
-+                        width, height, stride, format, modifier, *eba);
-+
-+
-+      pm_runtime_get_sync(prg->dev);
-+
-+      val = (stride - 1) & IPU_PRG_STRIDE_STRIDE_MASK;
-+      writel(val, prg->regs + IPU_PRG_STRIDE(prg_chan));
-+
-+      val = ((height & IPU_PRG_HEIGHT_PRE_HEIGHT_MASK) <<
-+             IPU_PRG_HEIGHT_PRE_HEIGHT_SHIFT) |
-+            ((height & IPU_PRG_HEIGHT_IPU_HEIGHT_MASK) <<
-+             IPU_PRG_HEIGHT_IPU_HEIGHT_SHIFT);
-+      writel(val, prg->regs + IPU_PRG_HEIGHT(prg_chan));
-+
-+      val = ipu_pre_get_baddr(prg->pres[chan->used_pre]);
-+      *eba = val;
-+      writel(val, prg->regs + IPU_PRG_BADDR(prg_chan));
-+
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      /* config AXI ID */
-+      val &= ~(IPU_PRG_CTL_SOFT_ARID_MASK <<
-+               IPU_PRG_CTL_SOFT_ARID_SHIFT(prg_chan));
-+      val |= IPU_PRG_CTL_SOFT_ARID(prg_chan, axi_id);
-+      /* enable channel */
-+      val &= ~IPU_PRG_CTL_BYPASS(prg_chan);
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      val = IPU_PRG_REG_UPDATE_REG_UPDATE;
-+      writel(val, prg->regs + IPU_PRG_REG_UPDATE);
-+
-+      /* wait for both double buffers to be filled */
-+      readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val,
-+                         (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) &&
-+                         (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)),
-+                         5, 1000);
-+
-+      pm_runtime_put(prg->dev);
-+
-+      chan->enabled = true;
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_configure);
-+
-+bool ipu_prg_channel_configure_pending(struct ipuv3_channel *ipu_chan)
-+{
-+      int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num);
-+      struct ipu_prg *prg = ipu_chan->ipu->prg_priv;
-+      struct ipu_prg_channel *chan;
-+
-+      if (prg_chan < 0)
-+              return false;
-+
-+      chan = &prg->chan[prg_chan];
-+      WARN_ON(!chan->enabled);
-+
-+      return ipu_pre_update_pending(prg->pres[chan->used_pre]);
-+}
-+EXPORT_SYMBOL_GPL(ipu_prg_channel_configure_pending);
-+
-+static int ipu_prg_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct resource *res;
-+      struct ipu_prg *prg;
-+      u32 val;
-+      int i, ret;
-+
-+      prg = devm_kzalloc(dev, sizeof(*prg), GFP_KERNEL);
-+      if (!prg)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      prg->regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(prg->regs))
-+              return PTR_ERR(prg->regs);
-+
-+
-+      prg->clk_ipg = devm_clk_get(dev, "ipg");
-+      if (IS_ERR(prg->clk_ipg))
-+              return PTR_ERR(prg->clk_ipg);
-+
-+      prg->clk_axi = devm_clk_get(dev, "axi");
-+      if (IS_ERR(prg->clk_axi))
-+              return PTR_ERR(prg->clk_axi);
-+
-+      prg->iomuxc_gpr =
-+              syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
-+      if (IS_ERR(prg->iomuxc_gpr))
-+              return PTR_ERR(prg->iomuxc_gpr);
-+
-+      for (i = 0; i < 3; i++) {
-+              prg->pres[i] = ipu_pre_lookup_by_phandle(dev, "fsl,pres", i);
-+              if (!prg->pres[i])
-+                      return -EPROBE_DEFER;
-+      }
-+
-+      ret = clk_prepare_enable(prg->clk_ipg);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_prepare_enable(prg->clk_axi);
-+      if (ret) {
-+              clk_disable_unprepare(prg->clk_ipg);
-+              return ret;
-+      }
-+
-+      /* init to free running mode */
-+      val = readl(prg->regs + IPU_PRG_CTL);
-+      val |= IPU_PRG_CTL_SHADOW_EN;
-+      writel(val, prg->regs + IPU_PRG_CTL);
-+
-+      /* disable address threshold */
-+      writel(0xffffffff, prg->regs + IPU_PRG_THD);
-+
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+
-+      prg->dev = dev;
-+      platform_set_drvdata(pdev, prg);
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_add(&prg->list, &ipu_prg_list);
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      return 0;
-+}
-+
-+static int ipu_prg_remove(struct platform_device *pdev)
-+{
-+      struct ipu_prg *prg = platform_get_drvdata(pdev);
-+
-+      mutex_lock(&ipu_prg_list_mutex);
-+      list_del(&prg->list);
-+      mutex_unlock(&ipu_prg_list_mutex);
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM
-+static int prg_suspend(struct device *dev)
-+{
-+      struct ipu_prg *prg = dev_get_drvdata(dev);
-+
-+      clk_disable_unprepare(prg->clk_axi);
-+      clk_disable_unprepare(prg->clk_ipg);
-+
-+      return 0;
-+}
-+
-+static int prg_resume(struct device *dev)
-+{
-+      struct ipu_prg *prg = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = clk_prepare_enable(prg->clk_ipg);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_prepare_enable(prg->clk_axi);
-+      if (ret) {
-+              clk_disable_unprepare(prg->clk_ipg);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
-+static const struct dev_pm_ops prg_pm_ops = {
-+      SET_RUNTIME_PM_OPS(prg_suspend, prg_resume, NULL)
-+};
-+
-+static const struct of_device_id ipu_prg_dt_ids[] = {
-+      { .compatible = "fsl,imx6qp-prg", },
-+      { /* sentinel */ },
-+};
-+
-+struct platform_driver ipu_prg_drv = {
-+      .probe          = ipu_prg_probe,
-+      .remove         = ipu_prg_remove,
-+      .driver         = {
-+              .name   = "imx-ipu-prg",
-+              .pm     = &prg_pm_ops,
-+              .of_match_table = ipu_prg_dt_ids,
-+      },
-+};
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-prv.h
-@@ -0,0 +1,274 @@
-+/* SPDX-License-Identifier: GPL-2.0-or-later */
-+/*
-+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#ifndef __IPU_PRV_H__
-+#define __IPU_PRV_H__
-+
-+struct ipu_soc;
-+
-+#include <linux/types.h>
-+#include <linux/device.h>
-+#include <linux/clk.h>
-+#include <linux/platform_device.h>
-+
-+#include <video/imx-ipu-v3.h>
-+
-+#define IPU_MCU_T_DEFAULT     8
-+#define IPU_CM_IDMAC_REG_OFS  0x00008000
-+#define IPU_CM_IC_REG_OFS     0x00020000
-+#define IPU_CM_IRT_REG_OFS    0x00028000
-+#define IPU_CM_CSI0_REG_OFS   0x00030000
-+#define IPU_CM_CSI1_REG_OFS   0x00038000
-+#define IPU_CM_SMFC_REG_OFS   0x00050000
-+#define IPU_CM_DC_REG_OFS     0x00058000
-+#define IPU_CM_DMFC_REG_OFS   0x00060000
-+
-+/* Register addresses */
-+/* IPU Common registers */
-+#define IPU_CM_REG(offset)    (offset)
-+
-+#define IPU_CONF                      IPU_CM_REG(0)
-+
-+#define IPU_SRM_PRI1                  IPU_CM_REG(0x00a0)
-+#define IPU_SRM_PRI2                  IPU_CM_REG(0x00a4)
-+#define IPU_FS_PROC_FLOW1             IPU_CM_REG(0x00a8)
-+#define IPU_FS_PROC_FLOW2             IPU_CM_REG(0x00ac)
-+#define IPU_FS_PROC_FLOW3             IPU_CM_REG(0x00b0)
-+#define IPU_FS_DISP_FLOW1             IPU_CM_REG(0x00b4)
-+#define IPU_FS_DISP_FLOW2             IPU_CM_REG(0x00b8)
-+#define IPU_SKIP                      IPU_CM_REG(0x00bc)
-+#define IPU_DISP_ALT_CONF             IPU_CM_REG(0x00c0)
-+#define IPU_DISP_GEN                  IPU_CM_REG(0x00c4)
-+#define IPU_DISP_ALT1                 IPU_CM_REG(0x00c8)
-+#define IPU_DISP_ALT2                 IPU_CM_REG(0x00cc)
-+#define IPU_DISP_ALT3                 IPU_CM_REG(0x00d0)
-+#define IPU_DISP_ALT4                 IPU_CM_REG(0x00d4)
-+#define IPU_SNOOP                     IPU_CM_REG(0x00d8)
-+#define IPU_MEM_RST                   IPU_CM_REG(0x00dc)
-+#define IPU_PM                                IPU_CM_REG(0x00e0)
-+#define IPU_GPR                               IPU_CM_REG(0x00e4)
-+#define IPU_CHA_DB_MODE_SEL(ch)               IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_DB_MODE_SEL(ch)   IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
-+#define IPU_CHA_CUR_BUF(ch)           IPU_CM_REG(0x023C + 4 * ((ch) / 32))
-+#define IPU_ALT_CUR_BUF0              IPU_CM_REG(0x0244)
-+#define IPU_ALT_CUR_BUF1              IPU_CM_REG(0x0248)
-+#define IPU_SRM_STAT                  IPU_CM_REG(0x024C)
-+#define IPU_PROC_TASK_STAT            IPU_CM_REG(0x0250)
-+#define IPU_DISP_TASK_STAT            IPU_CM_REG(0x0254)
-+#define IPU_CHA_BUF0_RDY(ch)          IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
-+#define IPU_CHA_BUF1_RDY(ch)          IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
-+#define IPU_CHA_BUF2_RDY(ch)          IPU_CM_REG(0x0288 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_BUF0_RDY(ch)      IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
-+#define IPU_ALT_CHA_BUF1_RDY(ch)      IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
-+
-+#define IPU_INT_CTRL(n)               IPU_CM_REG(0x003C + 4 * (n))
-+#define IPU_INT_STAT(n)               IPU_CM_REG(0x0200 + 4 * (n))
-+
-+/* SRM_PRI2 */
-+#define DP_S_SRM_MODE_MASK            (0x3 << 3)
-+#define DP_S_SRM_MODE_NOW             (0x3 << 3)
-+#define DP_S_SRM_MODE_NEXT_FRAME      (0x1 << 3)
-+
-+/* FS_PROC_FLOW1 */
-+#define FS_PRPENC_ROT_SRC_SEL_MASK    (0xf << 0)
-+#define FS_PRPENC_ROT_SRC_SEL_ENC             (0x7 << 0)
-+#define FS_PRPVF_ROT_SRC_SEL_MASK     (0xf << 8)
-+#define FS_PRPVF_ROT_SRC_SEL_VF                       (0x8 << 8)
-+#define FS_PP_SRC_SEL_MASK            (0xf << 12)
-+#define FS_PP_ROT_SRC_SEL_MASK                (0xf << 16)
-+#define FS_PP_ROT_SRC_SEL_PP                  (0x5 << 16)
-+#define FS_VDI1_SRC_SEL_MASK          (0x3 << 20)
-+#define FS_VDI3_SRC_SEL_MASK          (0x3 << 20)
-+#define FS_PRP_SRC_SEL_MASK           (0xf << 24)
-+#define FS_VDI_SRC_SEL_MASK           (0x3 << 28)
-+#define FS_VDI_SRC_SEL_CSI_DIRECT             (0x1 << 28)
-+#define FS_VDI_SRC_SEL_VDOA                   (0x2 << 28)
-+
-+/* FS_PROC_FLOW2 */
-+#define FS_PRP_ENC_DEST_SEL_MASK      (0xf << 0)
-+#define FS_PRP_ENC_DEST_SEL_IRT_ENC           (0x1 << 0)
-+#define FS_PRPVF_DEST_SEL_MASK                (0xf << 4)
-+#define FS_PRPVF_DEST_SEL_IRT_VF              (0x1 << 4)
-+#define FS_PRPVF_ROT_DEST_SEL_MASK    (0xf << 8)
-+#define FS_PP_DEST_SEL_MASK           (0xf << 12)
-+#define FS_PP_DEST_SEL_IRT_PP                 (0x3 << 12)
-+#define FS_PP_ROT_DEST_SEL_MASK               (0xf << 16)
-+#define FS_PRPENC_ROT_DEST_SEL_MASK   (0xf << 20)
-+#define FS_PRP_DEST_SEL_MASK          (0xf << 24)
-+
-+#define IPU_DI0_COUNTER_RELEASE                       (1 << 24)
-+#define IPU_DI1_COUNTER_RELEASE                       (1 << 25)
-+
-+#define IPU_IDMAC_REG(offset) (offset)
-+
-+#define IDMAC_CONF                    IPU_IDMAC_REG(0x0000)
-+#define IDMAC_CHA_EN(ch)              IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
-+#define IDMAC_SEP_ALPHA                       IPU_IDMAC_REG(0x000c)
-+#define IDMAC_ALT_SEP_ALPHA           IPU_IDMAC_REG(0x0010)
-+#define IDMAC_CHA_PRI(ch)             IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
-+#define IDMAC_WM_EN(ch)                       IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
-+#define IDMAC_CH_LOCK_EN_1            IPU_IDMAC_REG(0x0024)
-+#define IDMAC_CH_LOCK_EN_2            IPU_IDMAC_REG(0x0028)
-+#define IDMAC_SUB_ADDR_0              IPU_IDMAC_REG(0x002c)
-+#define IDMAC_SUB_ADDR_1              IPU_IDMAC_REG(0x0030)
-+#define IDMAC_SUB_ADDR_2              IPU_IDMAC_REG(0x0034)
-+#define IDMAC_BAND_EN(ch)             IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
-+#define IDMAC_CHA_BUSY(ch)            IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
-+
-+#define IPU_NUM_IRQS  (32 * 15)
-+
-+enum ipu_modules {
-+      IPU_CONF_CSI0_EN                = (1 << 0),
-+      IPU_CONF_CSI1_EN                = (1 << 1),
-+      IPU_CONF_IC_EN                  = (1 << 2),
-+      IPU_CONF_ROT_EN                 = (1 << 3),
-+      IPU_CONF_ISP_EN                 = (1 << 4),
-+      IPU_CONF_DP_EN                  = (1 << 5),
-+      IPU_CONF_DI0_EN                 = (1 << 6),
-+      IPU_CONF_DI1_EN                 = (1 << 7),
-+      IPU_CONF_SMFC_EN                = (1 << 8),
-+      IPU_CONF_DC_EN                  = (1 << 9),
-+      IPU_CONF_DMFC_EN                = (1 << 10),
-+
-+      IPU_CONF_VDI_EN                 = (1 << 12),
-+
-+      IPU_CONF_IDMAC_DIS              = (1 << 22),
-+
-+      IPU_CONF_IC_DMFC_SEL            = (1 << 25),
-+      IPU_CONF_IC_DMFC_SYNC           = (1 << 26),
-+      IPU_CONF_VDI_DMFC_SYNC          = (1 << 27),
-+
-+      IPU_CONF_CSI0_DATA_SOURCE       = (1 << 28),
-+      IPU_CONF_CSI1_DATA_SOURCE       = (1 << 29),
-+      IPU_CONF_IC_INPUT               = (1 << 30),
-+      IPU_CONF_CSI_SEL                = (1 << 31),
-+};
-+
-+struct ipuv3_channel {
-+      unsigned int num;
-+      struct ipu_soc *ipu;
-+      struct list_head list;
-+};
-+
-+struct ipu_cpmem;
-+struct ipu_csi;
-+struct ipu_dc_priv;
-+struct ipu_dmfc_priv;
-+struct ipu_di;
-+struct ipu_ic_priv;
-+struct ipu_vdi;
-+struct ipu_image_convert_priv;
-+struct ipu_smfc_priv;
-+struct ipu_pre;
-+struct ipu_prg;
-+
-+struct ipu_devtype;
-+
-+struct ipu_soc {
-+      struct device           *dev;
-+      const struct ipu_devtype        *devtype;
-+      enum ipuv3_type         ipu_type;
-+      spinlock_t              lock;
-+      struct mutex            channel_lock;
-+      struct list_head        channels;
-+
-+      void __iomem            *cm_reg;
-+      void __iomem            *idmac_reg;
-+
-+      int                     id;
-+      int                     usecount;
-+
-+      struct clk              *clk;
-+
-+      int                     irq_sync;
-+      int                     irq_err;
-+      struct irq_domain       *domain;
-+
-+      struct ipu_cpmem        *cpmem_priv;
-+      struct ipu_dc_priv      *dc_priv;
-+      struct ipu_dp_priv      *dp_priv;
-+      struct ipu_dmfc_priv    *dmfc_priv;
-+      struct ipu_di           *di_priv[2];
-+      struct ipu_csi          *csi_priv[2];
-+      struct ipu_ic_priv      *ic_priv;
-+      struct ipu_vdi          *vdi_priv;
-+      struct ipu_image_convert_priv *image_convert_priv;
-+      struct ipu_smfc_priv    *smfc_priv;
-+      struct ipu_prg          *prg_priv;
-+};
-+
-+static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
-+{
-+      return readl(ipu->idmac_reg + offset);
-+}
-+
-+static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
-+                                 unsigned offset)
-+{
-+      writel(value, ipu->idmac_reg + offset);
-+}
-+
-+void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync);
-+
-+int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
-+int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
-+
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
-+
-+int ipu_csi_init(struct ipu_soc *ipu, struct device *dev, int id,
-+               unsigned long base, u32 module, struct clk *clk_ipu);
-+void ipu_csi_exit(struct ipu_soc *ipu, int id);
-+
-+int ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
-+              unsigned long base, unsigned long tpmem_base);
-+void ipu_ic_exit(struct ipu_soc *ipu);
-+
-+int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
-+               unsigned long base, u32 module);
-+void ipu_vdi_exit(struct ipu_soc *ipu);
-+
-+int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev);
-+void ipu_image_convert_exit(struct ipu_soc *ipu);
-+
-+int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
-+              unsigned long base, u32 module, struct clk *ipu_clk);
-+void ipu_di_exit(struct ipu_soc *ipu, int id);
-+
-+int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              struct clk *ipu_clk);
-+void ipu_dmfc_exit(struct ipu_soc *ipu);
-+
-+int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_dp_exit(struct ipu_soc *ipu);
-+
-+int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-+              unsigned long template_base);
-+void ipu_dc_exit(struct ipu_soc *ipu);
-+
-+int ipu_cpmem_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_cpmem_exit(struct ipu_soc *ipu);
-+
-+int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base);
-+void ipu_smfc_exit(struct ipu_soc *ipu);
-+
-+struct ipu_pre *ipu_pre_lookup_by_phandle(struct device *dev, const char *name,
-+                                        int index);
-+int ipu_pre_get_available_count(void);
-+int ipu_pre_get(struct ipu_pre *pre);
-+void ipu_pre_put(struct ipu_pre *pre);
-+u32 ipu_pre_get_baddr(struct ipu_pre *pre);
-+void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
-+                     unsigned int height, unsigned int stride, u32 format,
-+                     uint64_t modifier, unsigned int bufaddr);
-+void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr);
-+bool ipu_pre_update_pending(struct ipu_pre *pre);
-+
-+struct ipu_prg *ipu_prg_lookup_by_phandle(struct device *dev, const char *name,
-+                                        int ipu_id);
-+
-+extern struct platform_driver ipu_pre_drv;
-+extern struct platform_driver ipu_prg_drv;
-+
-+#endif                                /* __IPU_PRV_H__ */
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-smfc.c
-@@ -0,0 +1,202 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
-+ */
-+#include <linux/export.h>
-+#include <linux/types.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/errno.h>
-+#include <linux/spinlock.h>
-+#include <linux/delay.h>
-+#include <linux/clk.h>
-+#include <video/imx-ipu-v3.h>
-+
-+#include "ipu-prv.h"
-+
-+struct ipu_smfc {
-+      struct ipu_smfc_priv *priv;
-+      int chno;
-+      bool inuse;
-+};
-+
-+struct ipu_smfc_priv {
-+      void __iomem *base;
-+      spinlock_t lock;
-+      struct ipu_soc *ipu;
-+      struct ipu_smfc channel[4];
-+      int use_count;
-+};
-+
-+/*SMFC Registers */
-+#define SMFC_MAP      0x0000
-+#define SMFC_WMC      0x0004
-+#define SMFC_BS               0x0008
-+
-+int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 4;
-+      val = readl(priv->base + SMFC_BS);
-+      val &= ~(0xf << shift);
-+      val |= burstsize << shift;
-+      writel(val, priv->base + SMFC_BS);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
-+
-+int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 3;
-+      val = readl(priv->base + SMFC_MAP);
-+      val &= ~(0x7 << shift);
-+      val |= ((csi_id << 2) | mipi_id) << shift;
-+      writel(val, priv->base + SMFC_MAP);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
-+
-+int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+      u32 val, shift;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
-+      val = readl(priv->base + SMFC_WMC);
-+      val &= ~(0x3f << shift);
-+      val |= ((clr_level << 3) | set_level) << shift;
-+      writel(val, priv->base + SMFC_WMC);
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
-+
-+int ipu_smfc_enable(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (!priv->use_count)
-+              ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
-+
-+      priv->use_count++;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_enable);
-+
-+int ipu_smfc_disable(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      priv->use_count--;
-+
-+      if (!priv->use_count)
-+              ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
-+
-+      if (priv->use_count < 0)
-+              priv->use_count = 0;
-+
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_disable);
-+
-+struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
-+{
-+      struct ipu_smfc_priv *priv = ipu->smfc_priv;
-+      struct ipu_smfc *smfc, *ret;
-+      unsigned long flags;
-+
-+      if (chno >= 4)
-+              return ERR_PTR(-EINVAL);
-+
-+      smfc = &priv->channel[chno];
-+      ret = smfc;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+
-+      if (smfc->inuse) {
-+              ret = ERR_PTR(-EBUSY);
-+              goto unlock;
-+      }
-+
-+      smfc->inuse = true;
-+unlock:
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_get);
-+
-+void ipu_smfc_put(struct ipu_smfc *smfc)
-+{
-+      struct ipu_smfc_priv *priv = smfc->priv;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&priv->lock, flags);
-+      smfc->inuse = false;
-+      spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_smfc_put);
-+
-+int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
-+                unsigned long base)
-+{
-+      struct ipu_smfc_priv *priv;
-+      int i;
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      ipu->smfc_priv = priv;
-+      spin_lock_init(&priv->lock);
-+      priv->ipu = ipu;
-+
-+      priv->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!priv->base)
-+              return -ENOMEM;
-+
-+      for (i = 0; i < 4; i++) {
-+              priv->channel[i].priv = priv;
-+              priv->channel[i].chno = i;
-+      }
-+
-+      pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
-+
-+      return 0;
-+}
-+
-+void ipu_smfc_exit(struct ipu_soc *ipu)
-+{
-+}
---- /dev/null
-+++ b/drivers/gpu/ipu-v3/ipu-vdi.c
-@@ -0,0 +1,234 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2012-2016 Mentor Graphics Inc.
-+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
-+ */
-+#include <linux/io.h>
-+#include "ipu-prv.h"
-+
-+struct ipu_vdi {
-+      void __iomem *base;
-+      u32 module;
-+      spinlock_t lock;
-+      int use_count;
-+      struct ipu_soc *ipu;
-+};
-+
-+
-+/* VDI Register Offsets */
-+#define VDI_FSIZE 0x0000
-+#define VDI_C     0x0004
-+
-+/* VDI Register Fields */
-+#define VDI_C_CH_420             (0 << 1)
-+#define VDI_C_CH_422             (1 << 1)
-+#define VDI_C_MOT_SEL_MASK       (0x3 << 2)
-+#define VDI_C_MOT_SEL_FULL       (2 << 2)
-+#define VDI_C_MOT_SEL_LOW        (1 << 2)
-+#define VDI_C_MOT_SEL_MED        (0 << 2)
-+#define VDI_C_BURST_SIZE1_4      (3 << 4)
-+#define VDI_C_BURST_SIZE2_4      (3 << 8)
-+#define VDI_C_BURST_SIZE3_4      (3 << 12)
-+#define VDI_C_BURST_SIZE_MASK    0xF
-+#define VDI_C_BURST_SIZE1_OFFSET 4
-+#define VDI_C_BURST_SIZE2_OFFSET 8
-+#define VDI_C_BURST_SIZE3_OFFSET 12
-+#define VDI_C_VWM1_SET_1         (0 << 16)
-+#define VDI_C_VWM1_SET_2         (1 << 16)
-+#define VDI_C_VWM1_CLR_2         (1 << 19)
-+#define VDI_C_VWM3_SET_1         (0 << 22)
-+#define VDI_C_VWM3_SET_2         (1 << 22)
-+#define VDI_C_VWM3_CLR_2         (1 << 25)
-+#define VDI_C_TOP_FIELD_MAN_1    (1 << 30)
-+#define VDI_C_TOP_FIELD_AUTO_1   (1 << 31)
-+
-+static inline u32 ipu_vdi_read(struct ipu_vdi *vdi, unsigned int offset)
-+{
-+      return readl(vdi->base + offset);
-+}
-+
-+static inline void ipu_vdi_write(struct ipu_vdi *vdi, u32 value,
-+                               unsigned int offset)
-+{
-+      writel(value, vdi->base + offset);
-+}
-+
-+void ipu_vdi_set_field_order(struct ipu_vdi *vdi, v4l2_std_id std, u32 field)
-+{
-+      bool top_field_0 = false;
-+      unsigned long flags;
-+      u32 reg;
-+
-+      switch (field) {
-+      case V4L2_FIELD_INTERLACED_TB:
-+      case V4L2_FIELD_SEQ_TB:
-+      case V4L2_FIELD_TOP:
-+              top_field_0 = true;
-+              break;
-+      case V4L2_FIELD_INTERLACED_BT:
-+      case V4L2_FIELD_SEQ_BT:
-+      case V4L2_FIELD_BOTTOM:
-+              top_field_0 = false;
-+              break;
-+      default:
-+              top_field_0 = (std & V4L2_STD_525_60) ? true : false;
-+              break;
-+      }
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+      if (top_field_0)
-+              reg &= ~(VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1);
-+      else
-+              reg |= VDI_C_TOP_FIELD_MAN_1 | VDI_C_TOP_FIELD_AUTO_1;
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_set_field_order);
-+
-+void ipu_vdi_set_motion(struct ipu_vdi *vdi, enum ipu_motion_sel motion_sel)
-+{
-+      unsigned long flags;
-+      u32 reg;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+
-+      reg &= ~VDI_C_MOT_SEL_MASK;
-+
-+      switch (motion_sel) {
-+      case MED_MOTION:
-+              reg |= VDI_C_MOT_SEL_MED;
-+              break;
-+      case HIGH_MOTION:
-+              reg |= VDI_C_MOT_SEL_FULL;
-+              break;
-+      default:
-+              reg |= VDI_C_MOT_SEL_LOW;
-+              break;
-+      }
-+
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_set_motion);
-+
-+void ipu_vdi_setup(struct ipu_vdi *vdi, u32 code, int xres, int yres)
-+{
-+      unsigned long flags;
-+      u32 pixel_fmt, reg;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      reg = ((yres - 1) << 16) | (xres - 1);
-+      ipu_vdi_write(vdi, reg, VDI_FSIZE);
-+
-+      /*
-+       * Full motion, only vertical filter is used.
-+       * Burst size is 4 accesses
-+       */
-+      if (code == MEDIA_BUS_FMT_UYVY8_2X8 ||
-+          code == MEDIA_BUS_FMT_UYVY8_1X16 ||
-+          code == MEDIA_BUS_FMT_YUYV8_2X8 ||
-+          code == MEDIA_BUS_FMT_YUYV8_1X16)
-+              pixel_fmt = VDI_C_CH_422;
-+      else
-+              pixel_fmt = VDI_C_CH_420;
-+
-+      reg = ipu_vdi_read(vdi, VDI_C);
-+      reg |= pixel_fmt;
-+      reg |= VDI_C_BURST_SIZE2_4;
-+      reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_CLR_2;
-+      reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_CLR_2;
-+      ipu_vdi_write(vdi, reg, VDI_C);
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_setup);
-+
-+void ipu_vdi_unsetup(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+      ipu_vdi_write(vdi, 0, VDI_FSIZE);
-+      ipu_vdi_write(vdi, 0, VDI_C);
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_unsetup);
-+
-+int ipu_vdi_enable(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      if (!vdi->use_count)
-+              ipu_module_enable(vdi->ipu, vdi->module);
-+
-+      vdi->use_count++;
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_enable);
-+
-+int ipu_vdi_disable(struct ipu_vdi *vdi)
-+{
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&vdi->lock, flags);
-+
-+      if (vdi->use_count) {
-+              if (!--vdi->use_count)
-+                      ipu_module_disable(vdi->ipu, vdi->module);
-+      }
-+
-+      spin_unlock_irqrestore(&vdi->lock, flags);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_disable);
-+
-+struct ipu_vdi *ipu_vdi_get(struct ipu_soc *ipu)
-+{
-+      return ipu->vdi_priv;
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_get);
-+
-+void ipu_vdi_put(struct ipu_vdi *vdi)
-+{
-+}
-+EXPORT_SYMBOL_GPL(ipu_vdi_put);
-+
-+int ipu_vdi_init(struct ipu_soc *ipu, struct device *dev,
-+               unsigned long base, u32 module)
-+{
-+      struct ipu_vdi *vdi;
-+
-+      vdi = devm_kzalloc(dev, sizeof(*vdi), GFP_KERNEL);
-+      if (!vdi)
-+              return -ENOMEM;
-+
-+      ipu->vdi_priv = vdi;
-+
-+      spin_lock_init(&vdi->lock);
-+      vdi->module = module;
-+      vdi->base = devm_ioremap(dev, base, PAGE_SIZE);
-+      if (!vdi->base)
-+              return -ENOMEM;
-+
-+      dev_dbg(dev, "VDI base: 0x%08lx remapped to %p\n", base, vdi->base);
-+      vdi->ipu = ipu;
-+
-+      return 0;
-+}
-+
-+void ipu_vdi_exit(struct ipu_soc *ipu)
-+{
-+}
---- a/drivers/video/Kconfig
-+++ b/drivers/video/Kconfig
-@@ -15,7 +15,7 @@ source "drivers/char/agp/Kconfig"
- source "drivers/gpu/vga/Kconfig"
- source "drivers/gpu/host1x/Kconfig"
--source "drivers/gpu/imx/Kconfig"
-+source "drivers/gpu/ipu-v3/Kconfig"
- source "drivers/gpu/drm/Kconfig"
diff --git a/target/linux/layerscape/patches-5.4/805-display-0050-Revert-drm-imx-Revert-a-patch-which-merges-imx-drm-c.patch b/target/linux/layerscape/patches-5.4/805-display-0050-Revert-drm-imx-Revert-a-patch-which-merges-imx-drm-c.patch
deleted file mode 100644 (file)
index c04aede..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-From c0dd62d0bc48c0d9e833116ea2696cc000633897 Mon Sep 17 00:00:00 2001
-From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 2 Mar 2020 13:46:39 +0800
-Subject: [PATCH] Revert "drm/imx: Revert a patch which merges imx-drm-core and
- ipuv3-crtc in one module"
-
-This reverts commit 1e7f3c4066d9afb4bc036b9d4b6f5b18f3c918c7.
----
- drivers/gpu/drm/imx/Kconfig        |  7 -------
- drivers/gpu/drm/imx/Makefile       |  4 +---
- drivers/gpu/drm/imx/imx-drm-core.c | 18 +++++++++++++++++-
- drivers/gpu/drm/imx/imx-drm.h      |  2 ++
- drivers/gpu/drm/imx/ipuv3-crtc.c   |  8 +-------
- 5 files changed, 21 insertions(+), 18 deletions(-)
-
---- a/drivers/gpu/drm/imx/Kconfig
-+++ b/drivers/gpu/drm/imx/Kconfig
-@@ -33,13 +33,6 @@ config DRM_IMX_LDB
-         Choose this to enable the internal LVDS Display Bridge (LDB)
-         found on i.MX53 and i.MX6 processors.
--config DRM_IMX_IPUV3
--      tristate
--      depends on DRM_IMX
--      depends on IMX_IPUV3_CORE
--      default y if DRM_IMX=y
--      default m if DRM_IMX=m
--
- config DRM_IMX_HDMI
-       tristate "Freescale i.MX DRM HDMI"
-       select DRM_DW_HDMI
---- a/drivers/gpu/drm/imx/Makefile
-+++ b/drivers/gpu/drm/imx/Makefile
-@@ -1,6 +1,6 @@
- # SPDX-License-Identifier: GPL-2.0
--imxdrm-objs := imx-drm-core.o
-+imxdrm-objs := imx-drm-core.o ipuv3-crtc.o ipuv3-plane.o
- obj-$(CONFIG_DRM_IMX) += imxdrm.o
-@@ -8,7 +8,5 @@ obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) +
- obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
- obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
--imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
--obj-$(CONFIG_DRM_IMX_IPUV3)   += imx-ipuv3-crtc.o
- obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o
- obj-$(CONFIG_DRM_IMX_CDNS_MHDP) += cdn-mhdp-imxdrv.o cdn-mhdp-dp-phy.o cdn-mhdp-hdmi-phy.o cdn-mhdp-imx8qm.o cdn-mhdp-ls1028a.o
---- a/drivers/gpu/drm/imx/imx-drm-core.c
-+++ b/drivers/gpu/drm/imx/imx-drm-core.c
-@@ -361,7 +361,23 @@ static struct platform_driver imx_drm_pd
-               .of_match_table = imx_drm_dt_ids,
-       },
- };
--module_platform_driver(imx_drm_pdrv);
-+
-+static struct platform_driver * const drivers[] = {
-+      &imx_drm_pdrv,
-+      &ipu_drm_driver,
-+};
-+
-+static int __init imx_drm_init(void)
-+{
-+      return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_init(imx_drm_init);
-+
-+static void __exit imx_drm_exit(void)
-+{
-+      platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-+}
-+module_exit(imx_drm_exit);
- MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
- MODULE_DESCRIPTION("i.MX drm driver core");
---- a/drivers/gpu/drm/imx/imx-drm.h
-+++ b/drivers/gpu/drm/imx/imx-drm.h
-@@ -28,6 +28,8 @@ int imx_drm_init_drm(struct platform_dev
-               int preferred_bpp);
- int imx_drm_exit_drm(void);
-+extern struct platform_driver ipu_drm_driver;
-+
- void imx_drm_mode_config_init(struct drm_device *drm);
- struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
---- a/drivers/gpu/drm/imx/ipuv3-crtc.c
-+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
-@@ -492,16 +492,10 @@ static int ipu_drm_remove(struct platfor
-       return 0;
- }
--static struct platform_driver ipu_drm_driver = {
-+struct platform_driver ipu_drm_driver = {
-       .driver = {
-               .name = "imx-ipuv3-crtc",
-       },
-       .probe = ipu_drm_probe,
-       .remove = ipu_drm_remove,
- };
--module_platform_driver(ipu_drm_driver);
--
--MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
--MODULE_DESCRIPTION(DRIVER_DESC);
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("platform:imx-ipuv3-crtc");