All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:33 ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This series adds initial graphics support for the Rockchip RK356[68]
SoCs.  Graphics support is based around the VOP2 controller which
replaces the VOP controller found on earlier Rockchip SoCs. The driver
has been tested with HDMI support included in this series and MIPI-DSI
which is not included because it needs some more work. The driver is
taken from the downstream Rockchip kernel and heavily polished, most non
standard features have been removed for now. I tested the driver with
the libdrm modetest utility and also with weston with both pixman and
panfrost driver support. Michael Riesch reported the driver to work on
the RK3566 as well, but device tree support for this SoC is not yet
included in this series.

The HDMI changes are based on patches from Benjamin Gaignard, but
modified a bit as I found out that the HDMI port on the RK3568 only
needs one additional clock, not two. Also I added regulator support
which is needed to get the HDMI up on the rk3568-EVB board.

All review and testing feedback welcome

Sascha

Benjamin Gaignard (2):
  dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  drm/rockchip: dw_hdmi: add rk3568 support

Sascha Hauer (10):
  drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
  drm/rockchip: dw_hdmi: add regulator support
  of: graph: Allow disabled endpoints
  dt-bindings: of: graph: Allow disabled endpoints
  dt-bindings: display: rockchip: Add binding for VOP2
  arm64: dts: rockchip: rk356x: Add VOP2 nodes
  arm64: dts: rockchip: rk356x: Add HDMI nodes
  arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  drm/rockchip: Make VOP driver optional
  drm: rockchip: Add VOP2 driver

 .../display/rockchip/rockchip,dw-hdmi.yaml    |   12 +-
 .../display/rockchip/rockchip-vop2.yaml       |  114 +
 .../bindings/media/video-interfaces.yaml      |    8 +
 arch/arm/configs/multi_v7_defconfig           |    1 +
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     |   24 +
 arch/arm64/boot/dts/rockchip/rk356x.dtsi      |  117 +
 arch/arm64/configs/defconfig                  |    1 +
 drivers/gpu/drm/drm_of.c                      |    6 +-
 drivers/gpu/drm/rockchip/Kconfig              |   13 +
 drivers/gpu/drm/rockchip/Makefile             |    4 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   |  137 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |    3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h   |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 3611 +++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  |  916 +++++
 drivers/of/property.c                         |    3 +
 17 files changed, 5731 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 201+ messages in thread

* [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:33 ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This series adds initial graphics support for the Rockchip RK356[68]
SoCs.  Graphics support is based around the VOP2 controller which
replaces the VOP controller found on earlier Rockchip SoCs. The driver
has been tested with HDMI support included in this series and MIPI-DSI
which is not included because it needs some more work. The driver is
taken from the downstream Rockchip kernel and heavily polished, most non
standard features have been removed for now. I tested the driver with
the libdrm modetest utility and also with weston with both pixman and
panfrost driver support. Michael Riesch reported the driver to work on
the RK3566 as well, but device tree support for this SoC is not yet
included in this series.

The HDMI changes are based on patches from Benjamin Gaignard, but
modified a bit as I found out that the HDMI port on the RK3568 only
needs one additional clock, not two. Also I added regulator support
which is needed to get the HDMI up on the rk3568-EVB board.

All review and testing feedback welcome

Sascha

Benjamin Gaignard (2):
  dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  drm/rockchip: dw_hdmi: add rk3568 support

Sascha Hauer (10):
  drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
  drm/rockchip: dw_hdmi: add regulator support
  of: graph: Allow disabled endpoints
  dt-bindings: of: graph: Allow disabled endpoints
  dt-bindings: display: rockchip: Add binding for VOP2
  arm64: dts: rockchip: rk356x: Add VOP2 nodes
  arm64: dts: rockchip: rk356x: Add HDMI nodes
  arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  drm/rockchip: Make VOP driver optional
  drm: rockchip: Add VOP2 driver

 .../display/rockchip/rockchip,dw-hdmi.yaml    |   12 +-
 .../display/rockchip/rockchip-vop2.yaml       |  114 +
 .../bindings/media/video-interfaces.yaml      |    8 +
 arch/arm/configs/multi_v7_defconfig           |    1 +
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     |   24 +
 arch/arm64/boot/dts/rockchip/rk356x.dtsi      |  117 +
 arch/arm64/configs/defconfig                  |    1 +
 drivers/gpu/drm/drm_of.c                      |    6 +-
 drivers/gpu/drm/rockchip/Kconfig              |   13 +
 drivers/gpu/drm/rockchip/Makefile             |    4 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   |  137 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |    3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h   |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 3611 +++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  |  916 +++++
 drivers/of/property.c                         |    3 +
 17 files changed, 5731 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:33 ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This series adds initial graphics support for the Rockchip RK356[68]
SoCs.  Graphics support is based around the VOP2 controller which
replaces the VOP controller found on earlier Rockchip SoCs. The driver
has been tested with HDMI support included in this series and MIPI-DSI
which is not included because it needs some more work. The driver is
taken from the downstream Rockchip kernel and heavily polished, most non
standard features have been removed for now. I tested the driver with
the libdrm modetest utility and also with weston with both pixman and
panfrost driver support. Michael Riesch reported the driver to work on
the RK3566 as well, but device tree support for this SoC is not yet
included in this series.

The HDMI changes are based on patches from Benjamin Gaignard, but
modified a bit as I found out that the HDMI port on the RK3568 only
needs one additional clock, not two. Also I added regulator support
which is needed to get the HDMI up on the rk3568-EVB board.

All review and testing feedback welcome

Sascha

Benjamin Gaignard (2):
  dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  drm/rockchip: dw_hdmi: add rk3568 support

Sascha Hauer (10):
  drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
  drm/rockchip: dw_hdmi: add regulator support
  of: graph: Allow disabled endpoints
  dt-bindings: of: graph: Allow disabled endpoints
  dt-bindings: display: rockchip: Add binding for VOP2
  arm64: dts: rockchip: rk356x: Add VOP2 nodes
  arm64: dts: rockchip: rk356x: Add HDMI nodes
  arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  drm/rockchip: Make VOP driver optional
  drm: rockchip: Add VOP2 driver

 .../display/rockchip/rockchip,dw-hdmi.yaml    |   12 +-
 .../display/rockchip/rockchip-vop2.yaml       |  114 +
 .../bindings/media/video-interfaces.yaml      |    8 +
 arch/arm/configs/multi_v7_defconfig           |    1 +
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     |   24 +
 arch/arm64/boot/dts/rockchip/rk356x.dtsi      |  117 +
 arch/arm64/configs/defconfig                  |    1 +
 drivers/gpu/drm/drm_of.c                      |    6 +-
 drivers/gpu/drm/rockchip/Kconfig              |   13 +
 drivers/gpu/drm/rockchip/Makefile             |    4 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   |  137 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |    3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h   |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 3611 +++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  |  916 +++++
 drivers/of/property.c                         |    3 +
 17 files changed, 5731 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:33 ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

This series adds initial graphics support for the Rockchip RK356[68]
SoCs.  Graphics support is based around the VOP2 controller which
replaces the VOP controller found on earlier Rockchip SoCs. The driver
has been tested with HDMI support included in this series and MIPI-DSI
which is not included because it needs some more work. The driver is
taken from the downstream Rockchip kernel and heavily polished, most non
standard features have been removed for now. I tested the driver with
the libdrm modetest utility and also with weston with both pixman and
panfrost driver support. Michael Riesch reported the driver to work on
the RK3566 as well, but device tree support for this SoC is not yet
included in this series.

The HDMI changes are based on patches from Benjamin Gaignard, but
modified a bit as I found out that the HDMI port on the RK3568 only
needs one additional clock, not two. Also I added regulator support
which is needed to get the HDMI up on the rk3568-EVB board.

All review and testing feedback welcome

Sascha

Benjamin Gaignard (2):
  dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  drm/rockchip: dw_hdmi: add rk3568 support

Sascha Hauer (10):
  drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
  drm/rockchip: dw_hdmi: add regulator support
  of: graph: Allow disabled endpoints
  dt-bindings: of: graph: Allow disabled endpoints
  dt-bindings: display: rockchip: Add binding for VOP2
  arm64: dts: rockchip: rk356x: Add VOP2 nodes
  arm64: dts: rockchip: rk356x: Add HDMI nodes
  arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  drm/rockchip: Make VOP driver optional
  drm: rockchip: Add VOP2 driver

 .../display/rockchip/rockchip,dw-hdmi.yaml    |   12 +-
 .../display/rockchip/rockchip-vop2.yaml       |  114 +
 .../bindings/media/video-interfaces.yaml      |    8 +
 arch/arm/configs/multi_v7_defconfig           |    1 +
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     |   24 +
 arch/arm64/boot/dts/rockchip/rk356x.dtsi      |  117 +
 arch/arm64/configs/defconfig                  |    1 +
 drivers/gpu/drm/drm_of.c                      |    6 +-
 drivers/gpu/drm/rockchip/Kconfig              |   13 +
 drivers/gpu/drm/rockchip/Makefile             |    4 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   |  137 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c   |    3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h   |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h   |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c  | 3611 +++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c  |  916 +++++
 drivers/of/property.c                         |    3 +
 17 files changed, 5731 insertions(+), 35 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 201+ messages in thread

* [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Rob Herring, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Define a new compatible for rk3568 HDMI.
This version of HDMI hardware block needs two new clocks hclk_vio and hclk
to provide phy reference clocks.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index da3b889ad8fcd..53fa42479d5b7 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -23,6 +23,7 @@ properties:
       - rockchip,rk3288-dw-hdmi
       - rockchip,rk3328-dw-hdmi
       - rockchip,rk3399-dw-hdmi
+      - rockchip,rk3568-dw-hdmi
 
   reg-io-width:
     const: 4
@@ -49,8 +50,11 @@ properties:
           - vpll
       - enum:
           - grf
+          - hclk_vio
+          - vpll
+      - enum:
+          - hclk
           - vpll
-      - const: vpll
 
   ddc-i2c-bus:
     $ref: /schemas/types.yaml#/definitions/phandle
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Rob Herring, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Define a new compatible for rk3568 HDMI.
This version of HDMI hardware block needs two new clocks hclk_vio and hclk
to provide phy reference clocks.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index da3b889ad8fcd..53fa42479d5b7 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -23,6 +23,7 @@ properties:
       - rockchip,rk3288-dw-hdmi
       - rockchip,rk3328-dw-hdmi
       - rockchip,rk3399-dw-hdmi
+      - rockchip,rk3568-dw-hdmi
 
   reg-io-width:
     const: 4
@@ -49,8 +50,11 @@ properties:
           - vpll
       - enum:
           - grf
+          - hclk_vio
+          - vpll
+      - enum:
+          - hclk
           - vpll
-      - const: vpll
 
   ddc-i2c-bus:
     $ref: /schemas/types.yaml#/definitions/phandle
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Rob Herring, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Define a new compatible for rk3568 HDMI.
This version of HDMI hardware block needs two new clocks hclk_vio and hclk
to provide phy reference clocks.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index da3b889ad8fcd..53fa42479d5b7 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -23,6 +23,7 @@ properties:
       - rockchip,rk3288-dw-hdmi
       - rockchip,rk3328-dw-hdmi
       - rockchip,rk3399-dw-hdmi
+      - rockchip,rk3568-dw-hdmi
 
   reg-io-width:
     const: 4
@@ -49,8 +50,11 @@ properties:
           - vpll
       - enum:
           - grf
+          - hclk_vio
+          - vpll
+      - enum:
+          - hclk
           - vpll
-      - const: vpll
 
   ddc-i2c-bus:
     $ref: /schemas/types.yaml#/definitions/phandle
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Define a new compatible for rk3568 HDMI.
This version of HDMI hardware block needs two new clocks hclk_vio and hclk
to provide phy reference clocks.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index da3b889ad8fcd..53fa42479d5b7 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -23,6 +23,7 @@ properties:
       - rockchip,rk3288-dw-hdmi
       - rockchip,rk3328-dw-hdmi
       - rockchip,rk3399-dw-hdmi
+      - rockchip,rk3568-dw-hdmi
 
   reg-io-width:
     const: 4
@@ -49,8 +50,11 @@ properties:
           - vpll
       - enum:
           - grf
+          - hclk_vio
+          - vpll
+      - enum:
+          - hclk
           - vpll
-      - const: vpll
 
   ddc-i2c-bus:
     $ref: /schemas/types.yaml#/definitions/phandle
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 02/12] drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The driver returns an error when devm_phy_optional_get() fails leaving
the previously enabled clock turned on. Change order and enable the
clock only after the phy has been acquired.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 830bdd5e9b7ce..8677c82716784 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -529,13 +529,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
-	if (ret) {
-		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
-			      ret);
-		return ret;
-	}
-
 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
 	if (IS_ERR(hdmi->phy)) {
 		ret = PTR_ERR(hdmi->phy);
@@ -544,6 +537,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hdmi->vpll_clk);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
+			      ret);
+		return ret;
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 02/12] drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The driver returns an error when devm_phy_optional_get() fails leaving
the previously enabled clock turned on. Change order and enable the
clock only after the phy has been acquired.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 830bdd5e9b7ce..8677c82716784 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -529,13 +529,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
-	if (ret) {
-		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
-			      ret);
-		return ret;
-	}
-
 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
 	if (IS_ERR(hdmi->phy)) {
 		ret = PTR_ERR(hdmi->phy);
@@ -544,6 +537,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hdmi->vpll_clk);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
+			      ret);
+		return ret;
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 02/12] drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The driver returns an error when devm_phy_optional_get() fails leaving
the previously enabled clock turned on. Change order and enable the
clock only after the phy has been acquired.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 830bdd5e9b7ce..8677c82716784 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -529,13 +529,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
-	if (ret) {
-		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
-			      ret);
-		return ret;
-	}
-
 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
 	if (IS_ERR(hdmi->phy)) {
 		ret = PTR_ERR(hdmi->phy);
@@ -544,6 +537,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hdmi->vpll_clk);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
+			      ret);
+		return ret;
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 02/12] drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

The driver returns an error when devm_phy_optional_get() fails leaving
the previously enabled clock turned on. Change order and enable the
clock only after the phy has been acquired.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 830bdd5e9b7ce..8677c82716784 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -529,13 +529,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
-	if (ret) {
-		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
-			      ret);
-		return ret;
-	}
-
 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
 	if (IS_ERR(hdmi->phy)) {
 		ret = PTR_ERR(hdmi->phy);
@@ -544,6 +537,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hdmi->vpll_clk);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
+			      ret);
+		return ret;
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 03/12] drm/rockchip: dw_hdmi: add rk3568 support
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Add a new dw_hdmi_plat_data struct and new compatible for rk3568.
This version of the HDMI hardware block needs a new clock to provide
the phy reference clock: hclk. As this is the third clock the driver
uses it is switched to devm_clk_bulk_get_optional() to simplify the
clock handling.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 74 +++++++++++++++------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 8677c82716784..29608c25e2d0e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -50,6 +50,10 @@
 #define RK3399_GRF_SOC_CON20		0x6250
 #define RK3399_HDMI_LCDC_SEL		BIT(6)
 
+#define RK3568_GRF_VO_CON1		0x0364
+#define RK3568_HDMI_SDAIN_MSK		BIT(15)
+#define RK3568_HDMI_SCLIN_MSK		BIT(14)
+
 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
 
 /**
@@ -64,11 +68,18 @@ struct rockchip_hdmi_chip_data {
 	u32	lcdsel_lit;
 };
 
+#define RK_HDMI_CLK_VPLL	0
+#define RK_HDMI_CLK_HCLK	1
+#define RK_HDMI_CLK_GRF		2
+#define RK_HDMI_NCLOCKS		3
+#define RK_HDMI_NCLOCKS_HDMI	2
+
 struct rockchip_hdmi {
 	struct device *dev;
 	struct regmap *regmap;
 	struct drm_encoder encoder;
 	const struct rockchip_hdmi_chip_data *chip_data;
+	struct clk_bulk_data clks[RK_HDMI_NCLOCKS];
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
@@ -189,6 +200,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
 	struct device_node *np = hdmi->dev->of_node;
+	int ret;
 
 	hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
 	if (IS_ERR(hdmi->regmap)) {
@@ -196,25 +208,19 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 		return PTR_ERR(hdmi->regmap);
 	}
 
-	hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
-	if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
-		hdmi->vpll_clk = NULL;
-	} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->vpll_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get vpll clock\n");
-		return PTR_ERR(hdmi->vpll_clk);
-	}
+	hdmi->clks[RK_HDMI_CLK_VPLL].id = "vpll";
+	hdmi->clks[RK_HDMI_CLK_HCLK].id = "hclk";
+	hdmi->clks[RK_HDMI_CLK_GRF].id = "grf";
+	ret = devm_clk_bulk_get_optional(hdmi->dev, RK_HDMI_NCLOCKS, hdmi->clks);
+	printk("%s: %d 0x%08lx 0x%08lx 0x%08lx\n", __func__, ret,
+	       (unsigned long)hdmi->clks[0].clk,
+	       (unsigned long)hdmi->clks[1].clk,
+	       (unsigned long)hdmi->clks[2].clk);
+	if (ret)
+		return ret;
 
-	hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
-	if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
-		hdmi->grf_clk = NULL;
-	} else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->grf_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
-		return PTR_ERR(hdmi->grf_clk);
-	}
+	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
+	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
 	return 0;
 }
@@ -257,7 +263,7 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 
-	clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
+	clk_set_rate(hdmi->clks[RK_HDMI_CLK_VPLL].clk, adj_mode->clock * 1000);
 }
 
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
@@ -467,6 +473,19 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
 	.use_drm_infoframe = true,
 };
 
+static struct rockchip_hdmi_chip_data rk3568_chip_data = {
+	.lcdsel_grf_reg = -1,
+};
+
+static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
+	.mode_valid = dw_hdmi_rockchip_mode_valid,
+	.mpll_cfg   = rockchip_mpll_cfg,
+	.cur_ctr    = rockchip_cur_ctr,
+	.phy_config = rockchip_phy_config,
+	.phy_data = &rk3568_chip_data,
+	.use_drm_infoframe = true,
+};
+
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3228-dw-hdmi",
 	  .data = &rk3228_hdmi_drv_data
@@ -480,6 +499,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3399-dw-hdmi",
 	  .data = &rk3399_hdmi_drv_data
 	},
+	{ .compatible = "rockchip,rk3568-dw-hdmi",
+	  .data = &rk3568_hdmi_drv_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
@@ -537,13 +559,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
+	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
 		return ret;
 	}
 
+	if (hdmi->chip_data == &rk3568_chip_data) {
+		regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
+			     HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK,
+					   RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK));
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
@@ -558,7 +588,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
 		drm_encoder_cleanup(encoder);
-		clk_disable_unprepare(hdmi->vpll_clk);
+		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	}
 
 	return ret;
@@ -570,7 +600,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 	struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
 
 	dw_hdmi_unbind(hdmi->hdmi);
-	clk_disable_unprepare(hdmi->vpll_clk);
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 03/12] drm/rockchip: dw_hdmi: add rk3568 support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Add a new dw_hdmi_plat_data struct and new compatible for rk3568.
This version of the HDMI hardware block needs a new clock to provide
the phy reference clock: hclk. As this is the third clock the driver
uses it is switched to devm_clk_bulk_get_optional() to simplify the
clock handling.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 74 +++++++++++++++------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 8677c82716784..29608c25e2d0e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -50,6 +50,10 @@
 #define RK3399_GRF_SOC_CON20		0x6250
 #define RK3399_HDMI_LCDC_SEL		BIT(6)
 
+#define RK3568_GRF_VO_CON1		0x0364
+#define RK3568_HDMI_SDAIN_MSK		BIT(15)
+#define RK3568_HDMI_SCLIN_MSK		BIT(14)
+
 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
 
 /**
@@ -64,11 +68,18 @@ struct rockchip_hdmi_chip_data {
 	u32	lcdsel_lit;
 };
 
+#define RK_HDMI_CLK_VPLL	0
+#define RK_HDMI_CLK_HCLK	1
+#define RK_HDMI_CLK_GRF		2
+#define RK_HDMI_NCLOCKS		3
+#define RK_HDMI_NCLOCKS_HDMI	2
+
 struct rockchip_hdmi {
 	struct device *dev;
 	struct regmap *regmap;
 	struct drm_encoder encoder;
 	const struct rockchip_hdmi_chip_data *chip_data;
+	struct clk_bulk_data clks[RK_HDMI_NCLOCKS];
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
@@ -189,6 +200,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
 	struct device_node *np = hdmi->dev->of_node;
+	int ret;
 
 	hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
 	if (IS_ERR(hdmi->regmap)) {
@@ -196,25 +208,19 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 		return PTR_ERR(hdmi->regmap);
 	}
 
-	hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
-	if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
-		hdmi->vpll_clk = NULL;
-	} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->vpll_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get vpll clock\n");
-		return PTR_ERR(hdmi->vpll_clk);
-	}
+	hdmi->clks[RK_HDMI_CLK_VPLL].id = "vpll";
+	hdmi->clks[RK_HDMI_CLK_HCLK].id = "hclk";
+	hdmi->clks[RK_HDMI_CLK_GRF].id = "grf";
+	ret = devm_clk_bulk_get_optional(hdmi->dev, RK_HDMI_NCLOCKS, hdmi->clks);
+	printk("%s: %d 0x%08lx 0x%08lx 0x%08lx\n", __func__, ret,
+	       (unsigned long)hdmi->clks[0].clk,
+	       (unsigned long)hdmi->clks[1].clk,
+	       (unsigned long)hdmi->clks[2].clk);
+	if (ret)
+		return ret;
 
-	hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
-	if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
-		hdmi->grf_clk = NULL;
-	} else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->grf_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
-		return PTR_ERR(hdmi->grf_clk);
-	}
+	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
+	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
 	return 0;
 }
@@ -257,7 +263,7 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 
-	clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
+	clk_set_rate(hdmi->clks[RK_HDMI_CLK_VPLL].clk, adj_mode->clock * 1000);
 }
 
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
@@ -467,6 +473,19 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
 	.use_drm_infoframe = true,
 };
 
+static struct rockchip_hdmi_chip_data rk3568_chip_data = {
+	.lcdsel_grf_reg = -1,
+};
+
+static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
+	.mode_valid = dw_hdmi_rockchip_mode_valid,
+	.mpll_cfg   = rockchip_mpll_cfg,
+	.cur_ctr    = rockchip_cur_ctr,
+	.phy_config = rockchip_phy_config,
+	.phy_data = &rk3568_chip_data,
+	.use_drm_infoframe = true,
+};
+
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3228-dw-hdmi",
 	  .data = &rk3228_hdmi_drv_data
@@ -480,6 +499,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3399-dw-hdmi",
 	  .data = &rk3399_hdmi_drv_data
 	},
+	{ .compatible = "rockchip,rk3568-dw-hdmi",
+	  .data = &rk3568_hdmi_drv_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
@@ -537,13 +559,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
+	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
 		return ret;
 	}
 
+	if (hdmi->chip_data == &rk3568_chip_data) {
+		regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
+			     HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK,
+					   RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK));
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
@@ -558,7 +588,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
 		drm_encoder_cleanup(encoder);
-		clk_disable_unprepare(hdmi->vpll_clk);
+		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	}
 
 	return ret;
@@ -570,7 +600,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 	struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
 
 	dw_hdmi_unbind(hdmi->hdmi);
-	clk_disable_unprepare(hdmi->vpll_clk);
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 03/12] drm/rockchip: dw_hdmi: add rk3568 support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Add a new dw_hdmi_plat_data struct and new compatible for rk3568.
This version of the HDMI hardware block needs a new clock to provide
the phy reference clock: hclk. As this is the third clock the driver
uses it is switched to devm_clk_bulk_get_optional() to simplify the
clock handling.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 74 +++++++++++++++------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 8677c82716784..29608c25e2d0e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -50,6 +50,10 @@
 #define RK3399_GRF_SOC_CON20		0x6250
 #define RK3399_HDMI_LCDC_SEL		BIT(6)
 
+#define RK3568_GRF_VO_CON1		0x0364
+#define RK3568_HDMI_SDAIN_MSK		BIT(15)
+#define RK3568_HDMI_SCLIN_MSK		BIT(14)
+
 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
 
 /**
@@ -64,11 +68,18 @@ struct rockchip_hdmi_chip_data {
 	u32	lcdsel_lit;
 };
 
+#define RK_HDMI_CLK_VPLL	0
+#define RK_HDMI_CLK_HCLK	1
+#define RK_HDMI_CLK_GRF		2
+#define RK_HDMI_NCLOCKS		3
+#define RK_HDMI_NCLOCKS_HDMI	2
+
 struct rockchip_hdmi {
 	struct device *dev;
 	struct regmap *regmap;
 	struct drm_encoder encoder;
 	const struct rockchip_hdmi_chip_data *chip_data;
+	struct clk_bulk_data clks[RK_HDMI_NCLOCKS];
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
@@ -189,6 +200,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
 	struct device_node *np = hdmi->dev->of_node;
+	int ret;
 
 	hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
 	if (IS_ERR(hdmi->regmap)) {
@@ -196,25 +208,19 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 		return PTR_ERR(hdmi->regmap);
 	}
 
-	hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
-	if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
-		hdmi->vpll_clk = NULL;
-	} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->vpll_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get vpll clock\n");
-		return PTR_ERR(hdmi->vpll_clk);
-	}
+	hdmi->clks[RK_HDMI_CLK_VPLL].id = "vpll";
+	hdmi->clks[RK_HDMI_CLK_HCLK].id = "hclk";
+	hdmi->clks[RK_HDMI_CLK_GRF].id = "grf";
+	ret = devm_clk_bulk_get_optional(hdmi->dev, RK_HDMI_NCLOCKS, hdmi->clks);
+	printk("%s: %d 0x%08lx 0x%08lx 0x%08lx\n", __func__, ret,
+	       (unsigned long)hdmi->clks[0].clk,
+	       (unsigned long)hdmi->clks[1].clk,
+	       (unsigned long)hdmi->clks[2].clk);
+	if (ret)
+		return ret;
 
-	hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
-	if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
-		hdmi->grf_clk = NULL;
-	} else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->grf_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
-		return PTR_ERR(hdmi->grf_clk);
-	}
+	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
+	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
 	return 0;
 }
@@ -257,7 +263,7 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 
-	clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
+	clk_set_rate(hdmi->clks[RK_HDMI_CLK_VPLL].clk, adj_mode->clock * 1000);
 }
 
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
@@ -467,6 +473,19 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
 	.use_drm_infoframe = true,
 };
 
+static struct rockchip_hdmi_chip_data rk3568_chip_data = {
+	.lcdsel_grf_reg = -1,
+};
+
+static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
+	.mode_valid = dw_hdmi_rockchip_mode_valid,
+	.mpll_cfg   = rockchip_mpll_cfg,
+	.cur_ctr    = rockchip_cur_ctr,
+	.phy_config = rockchip_phy_config,
+	.phy_data = &rk3568_chip_data,
+	.use_drm_infoframe = true,
+};
+
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3228-dw-hdmi",
 	  .data = &rk3228_hdmi_drv_data
@@ -480,6 +499,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3399-dw-hdmi",
 	  .data = &rk3399_hdmi_drv_data
 	},
+	{ .compatible = "rockchip,rk3568-dw-hdmi",
+	  .data = &rk3568_hdmi_drv_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
@@ -537,13 +559,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
+	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
 		return ret;
 	}
 
+	if (hdmi->chip_data == &rk3568_chip_data) {
+		regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
+			     HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK,
+					   RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK));
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
@@ -558,7 +588,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
 		drm_encoder_cleanup(encoder);
-		clk_disable_unprepare(hdmi->vpll_clk);
+		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	}
 
 	return ret;
@@ -570,7 +600,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 	struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
 
 	dw_hdmi_unbind(hdmi->hdmi);
-	clk_disable_unprepare(hdmi->vpll_clk);
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 03/12] drm/rockchip: dw_hdmi: add rk3568 support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

From: Benjamin Gaignard <benjamin.gaignard@collabora.com>

Add a new dw_hdmi_plat_data struct and new compatible for rk3568.
This version of the HDMI hardware block needs a new clock to provide
the phy reference clock: hclk. As this is the third clock the driver
uses it is switched to devm_clk_bulk_get_optional() to simplify the
clock handling.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 74 +++++++++++++++------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 8677c82716784..29608c25e2d0e 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -50,6 +50,10 @@
 #define RK3399_GRF_SOC_CON20		0x6250
 #define RK3399_HDMI_LCDC_SEL		BIT(6)
 
+#define RK3568_GRF_VO_CON1		0x0364
+#define RK3568_HDMI_SDAIN_MSK		BIT(15)
+#define RK3568_HDMI_SCLIN_MSK		BIT(14)
+
 #define HIWORD_UPDATE(val, mask)	(val | (mask) << 16)
 
 /**
@@ -64,11 +68,18 @@ struct rockchip_hdmi_chip_data {
 	u32	lcdsel_lit;
 };
 
+#define RK_HDMI_CLK_VPLL	0
+#define RK_HDMI_CLK_HCLK	1
+#define RK_HDMI_CLK_GRF		2
+#define RK_HDMI_NCLOCKS		3
+#define RK_HDMI_NCLOCKS_HDMI	2
+
 struct rockchip_hdmi {
 	struct device *dev;
 	struct regmap *regmap;
 	struct drm_encoder encoder;
 	const struct rockchip_hdmi_chip_data *chip_data;
+	struct clk_bulk_data clks[RK_HDMI_NCLOCKS];
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
@@ -189,6 +200,7 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 {
 	struct device_node *np = hdmi->dev->of_node;
+	int ret;
 
 	hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
 	if (IS_ERR(hdmi->regmap)) {
@@ -196,25 +208,19 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 		return PTR_ERR(hdmi->regmap);
 	}
 
-	hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
-	if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
-		hdmi->vpll_clk = NULL;
-	} else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->vpll_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get vpll clock\n");
-		return PTR_ERR(hdmi->vpll_clk);
-	}
+	hdmi->clks[RK_HDMI_CLK_VPLL].id = "vpll";
+	hdmi->clks[RK_HDMI_CLK_HCLK].id = "hclk";
+	hdmi->clks[RK_HDMI_CLK_GRF].id = "grf";
+	ret = devm_clk_bulk_get_optional(hdmi->dev, RK_HDMI_NCLOCKS, hdmi->clks);
+	printk("%s: %d 0x%08lx 0x%08lx 0x%08lx\n", __func__, ret,
+	       (unsigned long)hdmi->clks[0].clk,
+	       (unsigned long)hdmi->clks[1].clk,
+	       (unsigned long)hdmi->clks[2].clk);
+	if (ret)
+		return ret;
 
-	hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
-	if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
-		hdmi->grf_clk = NULL;
-	} else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (IS_ERR(hdmi->grf_clk)) {
-		DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n");
-		return PTR_ERR(hdmi->grf_clk);
-	}
+	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
+	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
 	return 0;
 }
@@ -257,7 +263,7 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 
-	clk_set_rate(hdmi->vpll_clk, adj_mode->clock * 1000);
+	clk_set_rate(hdmi->clks[RK_HDMI_CLK_VPLL].clk, adj_mode->clock * 1000);
 }
 
 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
@@ -467,6 +473,19 @@ static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
 	.use_drm_infoframe = true,
 };
 
+static struct rockchip_hdmi_chip_data rk3568_chip_data = {
+	.lcdsel_grf_reg = -1,
+};
+
+static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = {
+	.mode_valid = dw_hdmi_rockchip_mode_valid,
+	.mpll_cfg   = rockchip_mpll_cfg,
+	.cur_ctr    = rockchip_cur_ctr,
+	.phy_config = rockchip_phy_config,
+	.phy_data = &rk3568_chip_data,
+	.use_drm_infoframe = true,
+};
+
 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3228-dw-hdmi",
 	  .data = &rk3228_hdmi_drv_data
@@ -480,6 +499,9 @@ static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
 	{ .compatible = "rockchip,rk3399-dw-hdmi",
 	  .data = &rk3399_hdmi_drv_data
 	},
+	{ .compatible = "rockchip,rk3568-dw-hdmi",
+	  .data = &rk3568_hdmi_drv_data
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
@@ -537,13 +559,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
+	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
 		return ret;
 	}
 
+	if (hdmi->chip_data == &rk3568_chip_data) {
+		regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
+			     HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK,
+					   RK3568_HDMI_SDAIN_MSK |
+					   RK3568_HDMI_SCLIN_MSK));
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 
@@ -558,7 +588,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
 		drm_encoder_cleanup(encoder);
-		clk_disable_unprepare(hdmi->vpll_clk);
+		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	}
 
 	return ret;
@@ -570,7 +600,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 	struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
 
 	dw_hdmi_unbind(hdmi->hdmi);
-	clk_disable_unprepare(hdmi->vpll_clk);
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
for the HDMI port. add support for these to the driver for boards which
have them supplied by switchable regulators.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index 53fa42479d5b7..293b2cfbf739f 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -28,6 +28,12 @@ properties:
   reg-io-width:
     const: 4
 
+  avdd-0v9-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
+  avdd-1v8-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
   clocks:
     minItems: 2
     items:
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 29608c25e2d0e..b8fe56c89cdc9 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_edid.h>
@@ -83,6 +84,8 @@ struct rockchip_hdmi {
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
+	struct regulator *avdd_0v9;
+	struct regulator *avdd_1v8;
 	struct phy *phy;
 };
 
@@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
 	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
+	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");
+	if (IS_ERR(hdmi->avdd_0v9)) {
+		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_0v9);
+
+		hdmi->avdd_0v9 = NULL;
+	}
+
+	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
+	if (IS_ERR(hdmi->avdd_1v8)) {
+		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_1v8);
+
+		hdmi->avdd_1v8 = NULL;
+	}
+
 	return 0;
 }
 
@@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	if (hdmi->avdd_0v9) {
+		ret = regulator_enable(hdmi->avdd_0v9);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
+			goto err_avdd_0v9;
+		}
+	}
+
+	if (hdmi->avdd_1v8) {
+		ret = regulator_enable(hdmi->avdd_1v8);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
+			goto err_avdd_1v8;
+		}
+	}
+
 	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
-		return ret;
+		goto err_clk;
 	}
 
 	if (hdmi->chip_data == &rk3568_chip_data) {
@@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	 */
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
-		drm_encoder_cleanup(encoder);
-		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+		goto err_bind;
 	}
 
+	return 0;
+
+err_bind:
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+	drm_encoder_cleanup(encoder);
+err_clk:
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+err_avdd_1v8:
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
+err_avdd_0v9:
 	return ret;
 }
 
@@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 
 	dw_hdmi_unbind(hdmi->hdmi);
 	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
for the HDMI port. add support for these to the driver for boards which
have them supplied by switchable regulators.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index 53fa42479d5b7..293b2cfbf739f 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -28,6 +28,12 @@ properties:
   reg-io-width:
     const: 4
 
+  avdd-0v9-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
+  avdd-1v8-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
   clocks:
     minItems: 2
     items:
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 29608c25e2d0e..b8fe56c89cdc9 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_edid.h>
@@ -83,6 +84,8 @@ struct rockchip_hdmi {
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
+	struct regulator *avdd_0v9;
+	struct regulator *avdd_1v8;
 	struct phy *phy;
 };
 
@@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
 	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
+	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");
+	if (IS_ERR(hdmi->avdd_0v9)) {
+		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_0v9);
+
+		hdmi->avdd_0v9 = NULL;
+	}
+
+	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
+	if (IS_ERR(hdmi->avdd_1v8)) {
+		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_1v8);
+
+		hdmi->avdd_1v8 = NULL;
+	}
+
 	return 0;
 }
 
@@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	if (hdmi->avdd_0v9) {
+		ret = regulator_enable(hdmi->avdd_0v9);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
+			goto err_avdd_0v9;
+		}
+	}
+
+	if (hdmi->avdd_1v8) {
+		ret = regulator_enable(hdmi->avdd_1v8);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
+			goto err_avdd_1v8;
+		}
+	}
+
 	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
-		return ret;
+		goto err_clk;
 	}
 
 	if (hdmi->chip_data == &rk3568_chip_data) {
@@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	 */
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
-		drm_encoder_cleanup(encoder);
-		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+		goto err_bind;
 	}
 
+	return 0;
+
+err_bind:
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+	drm_encoder_cleanup(encoder);
+err_clk:
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+err_avdd_1v8:
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
+err_avdd_0v9:
 	return ret;
 }
 
@@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 
 	dw_hdmi_unbind(hdmi->hdmi);
 	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
for the HDMI port. add support for these to the driver for boards which
have them supplied by switchable regulators.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index 53fa42479d5b7..293b2cfbf739f 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -28,6 +28,12 @@ properties:
   reg-io-width:
     const: 4
 
+  avdd-0v9-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
+  avdd-1v8-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
   clocks:
     minItems: 2
     items:
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 29608c25e2d0e..b8fe56c89cdc9 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_edid.h>
@@ -83,6 +84,8 @@ struct rockchip_hdmi {
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
+	struct regulator *avdd_0v9;
+	struct regulator *avdd_1v8;
 	struct phy *phy;
 };
 
@@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
 	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
+	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");
+	if (IS_ERR(hdmi->avdd_0v9)) {
+		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_0v9);
+
+		hdmi->avdd_0v9 = NULL;
+	}
+
+	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
+	if (IS_ERR(hdmi->avdd_1v8)) {
+		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_1v8);
+
+		hdmi->avdd_1v8 = NULL;
+	}
+
 	return 0;
 }
 
@@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	if (hdmi->avdd_0v9) {
+		ret = regulator_enable(hdmi->avdd_0v9);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
+			goto err_avdd_0v9;
+		}
+	}
+
+	if (hdmi->avdd_1v8) {
+		ret = regulator_enable(hdmi->avdd_1v8);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
+			goto err_avdd_1v8;
+		}
+	}
+
 	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
-		return ret;
+		goto err_clk;
 	}
 
 	if (hdmi->chip_data == &rk3568_chip_data) {
@@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	 */
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
-		drm_encoder_cleanup(encoder);
-		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+		goto err_bind;
 	}
 
+	return 0;
+
+err_bind:
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+	drm_encoder_cleanup(encoder);
+err_clk:
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+err_avdd_1v8:
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
+err_avdd_0v9:
 	return ret;
 }
 
@@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 
 	dw_hdmi_unbind(hdmi->hdmi);
 	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
for the HDMI port. add support for these to the driver for boards which
have them supplied by switchable regulators.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
 2 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
index 53fa42479d5b7..293b2cfbf739f 100644
--- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
@@ -28,6 +28,12 @@ properties:
   reg-io-width:
     const: 4
 
+  avdd-0v9-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
+  avdd-1v8-supply:
+    description: A 0.9V supply that powers up the SoC internal circuitry.
+
   clocks:
     minItems: 2
     items:
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 29608c25e2d0e..b8fe56c89cdc9 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/bridge/dw_hdmi.h>
 #include <drm/drm_edid.h>
@@ -83,6 +84,8 @@ struct rockchip_hdmi {
 	struct clk *vpll_clk;
 	struct clk *grf_clk;
 	struct dw_hdmi *hdmi;
+	struct regulator *avdd_0v9;
+	struct regulator *avdd_1v8;
 	struct phy *phy;
 };
 
@@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
 	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
 	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
 
+	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");
+	if (IS_ERR(hdmi->avdd_0v9)) {
+		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_0v9);
+
+		hdmi->avdd_0v9 = NULL;
+	}
+
+	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
+	if (IS_ERR(hdmi->avdd_1v8)) {
+		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
+			return PTR_ERR(hdmi->avdd_1v8);
+
+		hdmi->avdd_1v8 = NULL;
+	}
+
 	return 0;
 }
 
@@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 		return ret;
 	}
 
+	if (hdmi->avdd_0v9) {
+		ret = regulator_enable(hdmi->avdd_0v9);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
+			goto err_avdd_0v9;
+		}
+	}
+
+	if (hdmi->avdd_1v8) {
+		ret = regulator_enable(hdmi->avdd_1v8);
+		if (ret) {
+			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
+			goto err_avdd_1v8;
+		}
+	}
+
 	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
 			      ret);
-		return ret;
+		goto err_clk;
 	}
 
 	if (hdmi->chip_data == &rk3568_chip_data) {
@@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	 */
 	if (IS_ERR(hdmi->hdmi)) {
 		ret = PTR_ERR(hdmi->hdmi);
-		drm_encoder_cleanup(encoder);
-		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+		goto err_bind;
 	}
 
+	return 0;
+
+err_bind:
+	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+	drm_encoder_cleanup(encoder);
+err_clk:
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+err_avdd_1v8:
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
+err_avdd_0v9:
 	return ret;
 }
 
@@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
 
 	dw_hdmi_unbind(hdmi->hdmi);
 	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
+
+	if (hdmi->avdd_1v8)
+		regulator_disable(hdmi->avdd_1v8);
+
+	if (hdmi->avdd_0v9)
+		regulator_disable(hdmi->avdd_0v9);
 }
 
 static const struct component_ops dw_hdmi_rockchip_ops = {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 05/12] of: graph: Allow disabled endpoints
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/drm_of.c | 6 ++----
 drivers/of/property.c    | 3 +++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 37c34146eea83..c2fd9fe505767 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -67,10 +67,8 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
 
 	for_each_endpoint_of_node(port, ep) {
 		remote_port = of_graph_get_remote_port(ep);
-		if (!remote_port) {
-			of_node_put(ep);
-			return 0;
-		}
+		if (!remote_port)
+			continue;
 
 		possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
 
diff --git a/drivers/of/property.c b/drivers/of/property.c
index a3483484a5a2a..40f8da7baa0a9 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -730,6 +730,9 @@ EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
  */
 struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
 {
+	if (!of_device_is_available(node))
+		return NULL;
+
 	/* Get remote endpoint node. */
 	return of_parse_phandle(node, "remote-endpoint", 0);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 05/12] of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/drm_of.c | 6 ++----
 drivers/of/property.c    | 3 +++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 37c34146eea83..c2fd9fe505767 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -67,10 +67,8 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
 
 	for_each_endpoint_of_node(port, ep) {
 		remote_port = of_graph_get_remote_port(ep);
-		if (!remote_port) {
-			of_node_put(ep);
-			return 0;
-		}
+		if (!remote_port)
+			continue;
 
 		possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
 
diff --git a/drivers/of/property.c b/drivers/of/property.c
index a3483484a5a2a..40f8da7baa0a9 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -730,6 +730,9 @@ EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
  */
 struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
 {
+	if (!of_device_is_available(node))
+		return NULL;
+
 	/* Get remote endpoint node. */
 	return of_parse_phandle(node, "remote-endpoint", 0);
 }
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 05/12] of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/drm_of.c | 6 ++----
 drivers/of/property.c    | 3 +++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 37c34146eea83..c2fd9fe505767 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -67,10 +67,8 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
 
 	for_each_endpoint_of_node(port, ep) {
 		remote_port = of_graph_get_remote_port(ep);
-		if (!remote_port) {
-			of_node_put(ep);
-			return 0;
-		}
+		if (!remote_port)
+			continue;
 
 		possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
 
diff --git a/drivers/of/property.c b/drivers/of/property.c
index a3483484a5a2a..40f8da7baa0a9 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -730,6 +730,9 @@ EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
  */
 struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
 {
+	if (!of_device_is_available(node))
+		return NULL;
+
 	/* Get remote endpoint node. */
 	return of_parse_phandle(node, "remote-endpoint", 0);
 }
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 05/12] of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/drm_of.c | 6 ++----
 drivers/of/property.c    | 3 +++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 37c34146eea83..c2fd9fe505767 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -67,10 +67,8 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
 
 	for_each_endpoint_of_node(port, ep) {
 		remote_port = of_graph_get_remote_port(ep);
-		if (!remote_port) {
-			of_node_put(ep);
-			return 0;
-		}
+		if (!remote_port)
+			continue;
 
 		possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
 
diff --git a/drivers/of/property.c b/drivers/of/property.c
index a3483484a5a2a..40f8da7baa0a9 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -730,6 +730,9 @@ EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
  */
 struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
 {
+	if (!of_device_is_available(node))
+		return NULL;
+
 	/* Get remote endpoint node. */
 	return of_parse_phandle(node, "remote-endpoint", 0);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 06/12] dt-bindings: of: graph: Allow disabled endpoints
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../devicetree/bindings/media/video-interfaces.yaml       | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index 4391dce2caee6..d7e516cd66f5f 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -84,6 +84,14 @@ properties:
       source) by the master device (data sink). In the master mode the data
       source device is also the source of the synchronization signals.
 
+  status:
+    enum:
+      - ok
+      - okay
+      - disabled
+    description:
+      Enables or disables the link. Disabled links are ignored.
+
   bus-type:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum:
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 06/12] dt-bindings: of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../devicetree/bindings/media/video-interfaces.yaml       | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index 4391dce2caee6..d7e516cd66f5f 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -84,6 +84,14 @@ properties:
       source) by the master device (data sink). In the master mode the data
       source device is also the source of the synchronization signals.
 
+  status:
+    enum:
+      - ok
+      - okay
+      - disabled
+    description:
+      Enables or disables the link. Disabled links are ignored.
+
   bus-type:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum:
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 06/12] dt-bindings: of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../devicetree/bindings/media/video-interfaces.yaml       | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index 4391dce2caee6..d7e516cd66f5f 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -84,6 +84,14 @@ properties:
       source) by the master device (data sink). In the master mode the data
       source device is also the source of the synchronization signals.
 
+  status:
+    enum:
+      - ok
+      - okay
+      - disabled
+    description:
+      Enables or disables the link. Disabled links are ignored.
+
   bus-type:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum:
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 06/12] dt-bindings: of: graph: Allow disabled endpoints
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

There are cases in which a SoC allows many different routes between
components, but not all of them make sense for a board. With this patch
we allow standard status = "disabled" properties for ports. With this
a SoC level dtsi file can describe all possible ports and only the ones
that make sense for the given hardware are enabled at board level.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../devicetree/bindings/media/video-interfaces.yaml       | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index 4391dce2caee6..d7e516cd66f5f 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -84,6 +84,14 @@ properties:
       source) by the master device (data sink). In the master mode the data
       source device is also the source of the synchronization signals.
 
+  status:
+    enum:
+      - ok
+      - okay
+      - disabled
+    description:
+      Enables or disables the link. Disabled links are ignored.
+
   bus-type:
     $ref: /schemas/types.yaml#/definitions/uint32
     enum:
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
The binding differs slightly from the existing VOP binding, so add a new
binding file for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
new file mode 100644
index 0000000000000..d566c423f9d8d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC display controller (VOP2)
+
+description:
+  VOP2 (Video Output Processor v2) is the display controller for the Rockchip
+  series of SoCs which transfers the image data from a video memory
+  buffer to an external LCD interface.
+
+maintainers:
+  - Sandy Huang <hjc@rock-chips.com>
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop
+
+  reg:
+    minItems: 1
+    items:
+      - description:
+          Must contain one entry corresponding to the base address and length
+          of the register space.
+      - description:
+          Can optionally contain a second entry corresponding to
+          the CRTC gamma LUT address.
+
+  interrupts:
+    maxItems: 1
+    description:
+      The VOP interrupt is shared by several interrupt sources, such as
+      frame start (VSYNC), line flag and other status interrupts.
+
+  clocks:
+    items:
+      - description: Clock for ddr buffer transfer.
+      - description: Clock for the ahb bus to R/W the phy regs.
+      - description: Pixel clock for video port 0.
+      - description: Pixel clock for video port 1.
+      - description: Pixel clock for video port 2.
+
+  clock-names:
+    items:
+      - const: aclk_vop
+      - const: hclk_vop
+      - const: dclk_vp0
+      - const: dclk_vp1
+      - const: dclk_vp2
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+  assigned-clocks:
+    maxItems: 2
+
+  assigned-clock-rates:
+    maxItems: 2
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/rk3568-power.h>
+    vop: vop@fe040000 {
+      compatible = "rockchip,rk3568-vop";
+      reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru ACLK_VOP>,
+               <&cru HCLK_VOP>,
+               <&cru DCLK_VOP0>,
+               <&cru DCLK_VOP1>,
+               <&cru DCLK_VOP2>;
+      clock-names = "aclk_vop",
+                    "hclk_vop",
+                    "dclk_vp0",
+                    "dclk_vp1",
+                    "dclk_vp2";
+      power-domains = <&power RK3568_PD_VO>;
+      iommus = <&vop_mmu>;
+      vop_out: port {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        vp0_out_dsi0: endpoint@0 {
+          reg = <0>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+        vp0_out_hdmi: endpoint@1 {
+          reg = <1>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+      };
+    };
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
The binding differs slightly from the existing VOP binding, so add a new
binding file for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
new file mode 100644
index 0000000000000..d566c423f9d8d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC display controller (VOP2)
+
+description:
+  VOP2 (Video Output Processor v2) is the display controller for the Rockchip
+  series of SoCs which transfers the image data from a video memory
+  buffer to an external LCD interface.
+
+maintainers:
+  - Sandy Huang <hjc@rock-chips.com>
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop
+
+  reg:
+    minItems: 1
+    items:
+      - description:
+          Must contain one entry corresponding to the base address and length
+          of the register space.
+      - description:
+          Can optionally contain a second entry corresponding to
+          the CRTC gamma LUT address.
+
+  interrupts:
+    maxItems: 1
+    description:
+      The VOP interrupt is shared by several interrupt sources, such as
+      frame start (VSYNC), line flag and other status interrupts.
+
+  clocks:
+    items:
+      - description: Clock for ddr buffer transfer.
+      - description: Clock for the ahb bus to R/W the phy regs.
+      - description: Pixel clock for video port 0.
+      - description: Pixel clock for video port 1.
+      - description: Pixel clock for video port 2.
+
+  clock-names:
+    items:
+      - const: aclk_vop
+      - const: hclk_vop
+      - const: dclk_vp0
+      - const: dclk_vp1
+      - const: dclk_vp2
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+  assigned-clocks:
+    maxItems: 2
+
+  assigned-clock-rates:
+    maxItems: 2
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/rk3568-power.h>
+    vop: vop@fe040000 {
+      compatible = "rockchip,rk3568-vop";
+      reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru ACLK_VOP>,
+               <&cru HCLK_VOP>,
+               <&cru DCLK_VOP0>,
+               <&cru DCLK_VOP1>,
+               <&cru DCLK_VOP2>;
+      clock-names = "aclk_vop",
+                    "hclk_vop",
+                    "dclk_vp0",
+                    "dclk_vp1",
+                    "dclk_vp2";
+      power-domains = <&power RK3568_PD_VO>;
+      iommus = <&vop_mmu>;
+      vop_out: port {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        vp0_out_dsi0: endpoint@0 {
+          reg = <0>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+        vp0_out_hdmi: endpoint@1 {
+          reg = <1>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+      };
+    };
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
The binding differs slightly from the existing VOP binding, so add a new
binding file for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
new file mode 100644
index 0000000000000..d566c423f9d8d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC display controller (VOP2)
+
+description:
+  VOP2 (Video Output Processor v2) is the display controller for the Rockchip
+  series of SoCs which transfers the image data from a video memory
+  buffer to an external LCD interface.
+
+maintainers:
+  - Sandy Huang <hjc@rock-chips.com>
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop
+
+  reg:
+    minItems: 1
+    items:
+      - description:
+          Must contain one entry corresponding to the base address and length
+          of the register space.
+      - description:
+          Can optionally contain a second entry corresponding to
+          the CRTC gamma LUT address.
+
+  interrupts:
+    maxItems: 1
+    description:
+      The VOP interrupt is shared by several interrupt sources, such as
+      frame start (VSYNC), line flag and other status interrupts.
+
+  clocks:
+    items:
+      - description: Clock for ddr buffer transfer.
+      - description: Clock for the ahb bus to R/W the phy regs.
+      - description: Pixel clock for video port 0.
+      - description: Pixel clock for video port 1.
+      - description: Pixel clock for video port 2.
+
+  clock-names:
+    items:
+      - const: aclk_vop
+      - const: hclk_vop
+      - const: dclk_vp0
+      - const: dclk_vp1
+      - const: dclk_vp2
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+  assigned-clocks:
+    maxItems: 2
+
+  assigned-clock-rates:
+    maxItems: 2
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/rk3568-power.h>
+    vop: vop@fe040000 {
+      compatible = "rockchip,rk3568-vop";
+      reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru ACLK_VOP>,
+               <&cru HCLK_VOP>,
+               <&cru DCLK_VOP0>,
+               <&cru DCLK_VOP1>,
+               <&cru DCLK_VOP2>;
+      clock-names = "aclk_vop",
+                    "hclk_vop",
+                    "dclk_vp0",
+                    "dclk_vp1",
+                    "dclk_vp2";
+      power-domains = <&power RK3568_PD_VO>;
+      iommus = <&vop_mmu>;
+      vop_out: port {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        vp0_out_dsi0: endpoint@0 {
+          reg = <0>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+        vp0_out_hdmi: endpoint@1 {
+          reg = <1>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+      };
+    };
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
The binding differs slightly from the existing VOP binding, so add a new
binding file for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml

diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
new file mode 100644
index 0000000000000..d566c423f9d8d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/rockchip/rockchip-vop2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip SoC display controller (VOP2)
+
+description:
+  VOP2 (Video Output Processor v2) is the display controller for the Rockchip
+  series of SoCs which transfers the image data from a video memory
+  buffer to an external LCD interface.
+
+maintainers:
+  - Sandy Huang <hjc@rock-chips.com>
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop
+
+  reg:
+    minItems: 1
+    items:
+      - description:
+          Must contain one entry corresponding to the base address and length
+          of the register space.
+      - description:
+          Can optionally contain a second entry corresponding to
+          the CRTC gamma LUT address.
+
+  interrupts:
+    maxItems: 1
+    description:
+      The VOP interrupt is shared by several interrupt sources, such as
+      frame start (VSYNC), line flag and other status interrupts.
+
+  clocks:
+    items:
+      - description: Clock for ddr buffer transfer.
+      - description: Clock for the ahb bus to R/W the phy regs.
+      - description: Pixel clock for video port 0.
+      - description: Pixel clock for video port 1.
+      - description: Pixel clock for video port 2.
+
+  clock-names:
+    items:
+      - const: aclk_vop
+      - const: hclk_vop
+      - const: dclk_vp0
+      - const: dclk_vp1
+      - const: dclk_vp2
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+  assigned-clocks:
+    maxItems: 2
+
+  assigned-clock-rates:
+    maxItems: 2
+
+  iommus:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/rk3568-cru.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/power/rk3568-power.h>
+    vop: vop@fe040000 {
+      compatible = "rockchip,rk3568-vop";
+      reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+      interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+      clocks = <&cru ACLK_VOP>,
+               <&cru HCLK_VOP>,
+               <&cru DCLK_VOP0>,
+               <&cru DCLK_VOP1>,
+               <&cru DCLK_VOP2>;
+      clock-names = "aclk_vop",
+                    "hclk_vop",
+                    "dclk_vp0",
+                    "dclk_vp1",
+                    "dclk_vp2";
+      power-domains = <&power RK3568_PD_VO>;
+      iommus = <&vop_mmu>;
+      vop_out: port {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        vp0_out_dsi0: endpoint@0 {
+          reg = <0>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+        vp0_out_hdmi: endpoint@1 {
+          reg = <1>;
+          remote-endpoint = <&dsi0_in_vp0>;
+        };
+      };
+    };
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is the display output controller on the RK3568. Add the node
for it to the dtsi file along with the required display-subsystem node
and the iommu node.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 46d9552f60284..6ebf7c14e096a 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
 		};
 	};
 
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vop_out>;
+	};
+
+	vop: vop@fe040000 {
+		compatible = "rockchip,rk3568-vop";
+		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+		reg-names = "regs", "gamma_lut";
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
+		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
+		iommus = <&vop_mmu>;
+		power-domains = <&power RK3568_PD_VO>;
+		status = "disabled";
+
+		vop_out: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vp0: port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+			};
+
+			vp1: port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+			};
+
+			vp2: port@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <2>;
+			};
+		};
+	};
+
+	vop_mmu: iommu@fe043e00 {
+		compatible = "rockchip,rk3568-iommu";
+		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is the display output controller on the RK3568. Add the node
for it to the dtsi file along with the required display-subsystem node
and the iommu node.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 46d9552f60284..6ebf7c14e096a 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
 		};
 	};
 
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vop_out>;
+	};
+
+	vop: vop@fe040000 {
+		compatible = "rockchip,rk3568-vop";
+		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+		reg-names = "regs", "gamma_lut";
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
+		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
+		iommus = <&vop_mmu>;
+		power-domains = <&power RK3568_PD_VO>;
+		status = "disabled";
+
+		vop_out: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vp0: port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+			};
+
+			vp1: port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+			};
+
+			vp2: port@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <2>;
+			};
+		};
+	};
+
+	vop_mmu: iommu@fe043e00 {
+		compatible = "rockchip,rk3568-iommu";
+		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 is the display output controller on the RK3568. Add the node
for it to the dtsi file along with the required display-subsystem node
and the iommu node.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 46d9552f60284..6ebf7c14e096a 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
 		};
 	};
 
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vop_out>;
+	};
+
+	vop: vop@fe040000 {
+		compatible = "rockchip,rk3568-vop";
+		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+		reg-names = "regs", "gamma_lut";
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
+		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
+		iommus = <&vop_mmu>;
+		power-domains = <&power RK3568_PD_VO>;
+		status = "disabled";
+
+		vop_out: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vp0: port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+			};
+
+			vp1: port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+			};
+
+			vp2: port@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <2>;
+			};
+		};
+	};
+
+	vop_mmu: iommu@fe043e00 {
+		compatible = "rockchip,rk3568-iommu";
+		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

The VOP2 is the display output controller on the RK3568. Add the node
for it to the dtsi file along with the required display-subsystem node
and the iommu node.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 46d9552f60284..6ebf7c14e096a 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
 		};
 	};
 
+	display_subsystem: display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vop_out>;
+	};
+
+	vop: vop@fe040000 {
+		compatible = "rockchip,rk3568-vop";
+		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
+		reg-names = "regs", "gamma_lut";
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
+		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
+		iommus = <&vop_mmu>;
+		power-domains = <&power RK3568_PD_VO>;
+		status = "disabled";
+
+		vop_out: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			vp0: port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+			};
+
+			vp1: port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+			};
+
+			vp2: port@2 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <2>;
+			};
+		};
+	};
+
+	vop_mmu: iommu@fe043e00 {
+		compatible = "rockchip,rk3568-iommu";
+		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+		clock-names = "aclk", "iface";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

Add support for the HDMI port found on RK3568.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 6ebf7c14e096a..53be61a7ce595 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -472,18 +472,36 @@ vp0: port@0 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
+
+				vp0_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp0>;
+					status = "disabled";
+				};
 			};
 
 			vp1: port@1 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <1>;
+
+				vp1_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp1>;
+					status = "disabled";
+				};
 			};
 
 			vp2: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <2>;
+
+				vp2_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp2>;
+					status = "disabled";
+				};
 			};
 		};
 	};
@@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
 		status = "disabled";
 	};
 
+	hdmi: hdmi@fe0a0000 {
+		compatible = "rockchip,rk3568-dw-hdmi";
+		reg = <0x0 0xfe0a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_HDMI_HOST>,
+			 <&cru CLK_HDMI_SFR>,
+			 <&cru CLK_HDMI_CEC>,
+			 <&cru HCLK_VOP>;
+		clock-names = "iahb", "isfr", "cec", "hclk";
+		power-domains = <&power RK3568_PD_VO>;
+		reg-io-width = <4>;
+		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_in_vp0: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vp0_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp1: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vp1_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp2: endpoint@2 {
+					reg = <2>;
+					remote-endpoint = <&vp2_out_hdmi>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

Add support for the HDMI port found on RK3568.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 6ebf7c14e096a..53be61a7ce595 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -472,18 +472,36 @@ vp0: port@0 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
+
+				vp0_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp0>;
+					status = "disabled";
+				};
 			};
 
 			vp1: port@1 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <1>;
+
+				vp1_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp1>;
+					status = "disabled";
+				};
 			};
 
 			vp2: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <2>;
+
+				vp2_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp2>;
+					status = "disabled";
+				};
 			};
 		};
 	};
@@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
 		status = "disabled";
 	};
 
+	hdmi: hdmi@fe0a0000 {
+		compatible = "rockchip,rk3568-dw-hdmi";
+		reg = <0x0 0xfe0a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_HDMI_HOST>,
+			 <&cru CLK_HDMI_SFR>,
+			 <&cru CLK_HDMI_CEC>,
+			 <&cru HCLK_VOP>;
+		clock-names = "iahb", "isfr", "cec", "hclk";
+		power-domains = <&power RK3568_PD_VO>;
+		reg-io-width = <4>;
+		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_in_vp0: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vp0_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp1: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vp1_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp2: endpoint@2 {
+					reg = <2>;
+					remote-endpoint = <&vp2_out_hdmi>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

Add support for the HDMI port found on RK3568.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 6ebf7c14e096a..53be61a7ce595 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -472,18 +472,36 @@ vp0: port@0 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
+
+				vp0_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp0>;
+					status = "disabled";
+				};
 			};
 
 			vp1: port@1 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <1>;
+
+				vp1_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp1>;
+					status = "disabled";
+				};
 			};
 
 			vp2: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <2>;
+
+				vp2_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp2>;
+					status = "disabled";
+				};
 			};
 		};
 	};
@@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
 		status = "disabled";
 	};
 
+	hdmi: hdmi@fe0a0000 {
+		compatible = "rockchip,rk3568-dw-hdmi";
+		reg = <0x0 0xfe0a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_HDMI_HOST>,
+			 <&cru CLK_HDMI_SFR>,
+			 <&cru CLK_HDMI_CEC>,
+			 <&cru HCLK_VOP>;
+		clock-names = "iahb", "isfr", "cec", "hclk";
+		power-domains = <&power RK3568_PD_VO>;
+		reg-io-width = <4>;
+		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_in_vp0: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vp0_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp1: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vp1_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp2: endpoint@2 {
+					reg = <2>;
+					remote-endpoint = <&vp2_out_hdmi>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

Add support for the HDMI port found on RK3568.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 6ebf7c14e096a..53be61a7ce595 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -472,18 +472,36 @@ vp0: port@0 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
+
+				vp0_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp0>;
+					status = "disabled";
+				};
 			};
 
 			vp1: port@1 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <1>;
+
+				vp1_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp1>;
+					status = "disabled";
+				};
 			};
 
 			vp2: port@2 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <2>;
+
+				vp2_out_hdmi: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&hdmi_in_vp2>;
+					status = "disabled";
+				};
 			};
 		};
 	};
@@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
 		status = "disabled";
 	};
 
+	hdmi: hdmi@fe0a0000 {
+		compatible = "rockchip,rk3568-dw-hdmi";
+		reg = <0x0 0xfe0a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_HDMI_HOST>,
+			 <&cru CLK_HDMI_SFR>,
+			 <&cru CLK_HDMI_CEC>,
+			 <&cru HCLK_VOP>;
+		clock-names = "iahb", "isfr", "cec", "hclk";
+		power-domains = <&power RK3568_PD_VO>;
+		reg-io-width = <4>;
+		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_in_vp0: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vp0_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp1: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vp1_out_hdmi>;
+					status = "disabled";
+				};
+
+				hdmi_in_vp2: endpoint@2 {
+					reg = <2>;
+					remote-endpoint = <&vp2_out_hdmi>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
 	qos_gpu: qos@fe128000 {
 		compatible = "rockchip,rk3568-qos", "syscon";
 		reg = <0x0 0xfe128000 0x0 0x20>;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This enabled the VOP2 display controller along with hdmi and the
required port routes which is enough to get a picture out of the
hdmi port of the board.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 184e2aa2416af..156e001492173 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda0v9_image>;
+	avdd-1v8-supply = <&vcca1v8_image>;
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -390,3 +396,21 @@ &sdmmc0 {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This enabled the VOP2 display controller along with hdmi and the
required port routes which is enough to get a picture out of the
hdmi port of the board.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 184e2aa2416af..156e001492173 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda0v9_image>;
+	avdd-1v8-supply = <&vcca1v8_image>;
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -390,3 +396,21 @@ &sdmmc0 {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

This enabled the VOP2 display controller along with hdmi and the
required port routes which is enough to get a picture out of the
hdmi port of the board.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 184e2aa2416af..156e001492173 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda0v9_image>;
+	avdd-1v8-supply = <&vcca1v8_image>;
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -390,3 +396,21 @@ &sdmmc0 {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

This enabled the VOP2 display controller along with hdmi and the
required port routes which is enough to get a picture out of the
hdmi port of the board.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
index 184e2aa2416af..156e001492173 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
@@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda0v9_image>;
+	avdd-1v8-supply = <&vcca1v8_image>;
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -390,3 +396,21 @@ &sdmmc0 {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 11/12] drm/rockchip: Make VOP driver optional
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

With upcoming VOP2 support VOP won't be the only choice anymore, so make
the VOP driver optional.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/configs/multi_v7_defconfig         | 1 +
 arch/arm64/configs/defconfig                | 1 +
 drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
 drivers/gpu/drm/rockchip/Makefile           | 3 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index c951aeed2138c..fc123e8f3e2f9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
 CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
 CONFIG_ROCKCHIP_DW_MIPI_DSI=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f2e2b9bdd7024..a623386473dc9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_CDN_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 9f1ecefc39332..a1c4158259099 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -21,8 +21,15 @@ config DRM_ROCKCHIP
 
 if DRM_ROCKCHIP
 
+config ROCKCHIP_VOP
+	bool "Rockchip VOP driver"
+	help
+	  This selects support for the VOP driver. You should enable it
+	  on all older SoCs up to RK3399.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
+	depends on ROCKCHIP_VOP
 	help
 	  This selects support for Rockchip SoC specific extensions
 	  for the Analogix Core DP driver. If you want to enable DP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -4,9 +4,10 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
+		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index e4ebe60b3cc1a..64fa5fd62c01a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
 	int ret;
 
 	num_rockchip_sub_drivers = 0;
-	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

With upcoming VOP2 support VOP won't be the only choice anymore, so make
the VOP driver optional.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/configs/multi_v7_defconfig         | 1 +
 arch/arm64/configs/defconfig                | 1 +
 drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
 drivers/gpu/drm/rockchip/Makefile           | 3 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index c951aeed2138c..fc123e8f3e2f9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
 CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
 CONFIG_ROCKCHIP_DW_MIPI_DSI=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f2e2b9bdd7024..a623386473dc9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_CDN_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 9f1ecefc39332..a1c4158259099 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -21,8 +21,15 @@ config DRM_ROCKCHIP
 
 if DRM_ROCKCHIP
 
+config ROCKCHIP_VOP
+	bool "Rockchip VOP driver"
+	help
+	  This selects support for the VOP driver. You should enable it
+	  on all older SoCs up to RK3399.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
+	depends on ROCKCHIP_VOP
 	help
 	  This selects support for Rockchip SoC specific extensions
 	  for the Analogix Core DP driver. If you want to enable DP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -4,9 +4,10 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
+		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index e4ebe60b3cc1a..64fa5fd62c01a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
 	int ret;
 
 	num_rockchip_sub_drivers = 0;
-	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

With upcoming VOP2 support VOP won't be the only choice anymore, so make
the VOP driver optional.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/configs/multi_v7_defconfig         | 1 +
 arch/arm64/configs/defconfig                | 1 +
 drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
 drivers/gpu/drm/rockchip/Makefile           | 3 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index c951aeed2138c..fc123e8f3e2f9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
 CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
 CONFIG_ROCKCHIP_DW_MIPI_DSI=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f2e2b9bdd7024..a623386473dc9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_CDN_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 9f1ecefc39332..a1c4158259099 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -21,8 +21,15 @@ config DRM_ROCKCHIP
 
 if DRM_ROCKCHIP
 
+config ROCKCHIP_VOP
+	bool "Rockchip VOP driver"
+	help
+	  This selects support for the VOP driver. You should enable it
+	  on all older SoCs up to RK3399.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
+	depends on ROCKCHIP_VOP
 	help
 	  This selects support for Rockchip SoC specific extensions
 	  for the Analogix Core DP driver. If you want to enable DP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -4,9 +4,10 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
+		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index e4ebe60b3cc1a..64fa5fd62c01a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
 	int ret;
 
 	num_rockchip_sub_drivers = 0;
-	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

With upcoming VOP2 support VOP won't be the only choice anymore, so make
the VOP driver optional.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/configs/multi_v7_defconfig         | 1 +
 arch/arm64/configs/defconfig                | 1 +
 drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
 drivers/gpu/drm/rockchip/Makefile           | 3 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index c951aeed2138c..fc123e8f3e2f9 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
 CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
 CONFIG_ROCKCHIP_DW_MIPI_DSI=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index f2e2b9bdd7024..a623386473dc9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_VOP=y
 CONFIG_ROCKCHIP_ANALOGIX_DP=y
 CONFIG_ROCKCHIP_CDN_DP=y
 CONFIG_ROCKCHIP_DW_HDMI=y
diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index 9f1ecefc39332..a1c4158259099 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -21,8 +21,15 @@ config DRM_ROCKCHIP
 
 if DRM_ROCKCHIP
 
+config ROCKCHIP_VOP
+	bool "Rockchip VOP driver"
+	help
+	  This selects support for the VOP driver. You should enable it
+	  on all older SoCs up to RK3399.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
+	depends on ROCKCHIP_VOP
 	help
 	  This selects support for Rockchip SoC specific extensions
 	  for the Analogix Core DP driver. If you want to enable DP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -4,9 +4,10 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
-		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
+		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index e4ebe60b3cc1a..64fa5fd62c01a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
 	int ret;
 
 	num_rockchip_sub_drivers = 0;
-	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 12/12] drm: rockchip: Add VOP2 driver
  2021-11-17 14:33 ` Sascha Hauer
  (?)
@ 2021-11-17 14:33   ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
It replaces the VOP unit found in the older Rockchip SoCs.

This driver has been derived from the downstream Rockchip Kernel and
heavily modified:

- All nonstandard DRM properties have been removed
- dropped struct vop2_plane_state and pass around less data between
  functions
- Dropped all DRM_FORMAT_* not known on upstream
- rework register access to get rid of excessively used macros

The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
board. Overlay support is tested with the modetest utility. AFBC support
is still present in the driver, but currently untested due to the lack
of suitable image sources. Also the driver has been tested with weston
using pixman and (yet to be upstreamed) panfrost driver support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/Kconfig             |    6 +
 drivers/gpu/drm/rockchip/Makefile            |    1 +
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h  |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h  |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 3611 ++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c |  916 +++++
 8 files changed, 5331 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index a1c4158259099..b841f4873f7f3 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -27,6 +27,12 @@ config ROCKCHIP_VOP
 	  This selects support for the VOP driver. You should enable it
 	  on all older SoCs up to RK3399.
 
+config ROCKCHIP_VOP2
+	bool "Rockchip VOP2 driver"
+	help
+	  This selects support for the VOP2 driver. You should enable it
+	  on all newer SoCs beginning form RK3568.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
 	depends on ROCKCHIP_VOP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index cd6e7bb5ce9c5..29848caef5c21 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index b8fe56c89cdc9..f6296b8a123ab 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -324,6 +324,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
 
 	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
 	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+	s->output_if = VOP_OUTPUT_IF_HDMI0;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 64fa5fd62c01a..2bd9acb265e5a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -474,6 +474,7 @@ static int __init rockchip_drm_init(void)
 
 	num_rockchip_sub_drivers = 0;
 	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index aa0909e8edf93..cdd2c2847441a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,12 +18,26 @@
 
 #define ROCKCHIP_MAX_FB_BUFFER	3
 #define ROCKCHIP_MAX_CONNECTOR	2
-#define ROCKCHIP_MAX_CRTC	2
+#define ROCKCHIP_MAX_CRTC	4
 
 struct drm_device;
 struct drm_connector;
 struct iommu_domain;
 
+#define VOP_OUTPUT_IF_RGB       BIT(0)
+#define VOP_OUTPUT_IF_BT1120    BIT(1)
+#define VOP_OUTPUT_IF_BT656     BIT(2)
+#define VOP_OUTPUT_IF_LVDS0     BIT(3)
+#define VOP_OUTPUT_IF_LVDS1     BIT(4)
+#define VOP_OUTPUT_IF_MIPI0     BIT(5)
+#define VOP_OUTPUT_IF_MIPI1     BIT(6)
+#define VOP_OUTPUT_IF_eDP0      BIT(7)
+#define VOP_OUTPUT_IF_eDP1      BIT(8)
+#define VOP_OUTPUT_IF_DP0       BIT(9)
+#define VOP_OUTPUT_IF_DP1       BIT(10)
+#define VOP_OUTPUT_IF_HDMI0     BIT(11)
+#define VOP_OUTPUT_IF_HDMI1     BIT(12)
+
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
 	int output_type;
@@ -31,6 +45,10 @@ struct rockchip_crtc_state {
 	int output_bpc;
 	int output_flags;
 	bool enable_afbc;
+	uint32_t bus_format;
+	uint32_t output_if;
+	u32 bus_flags;
+	int color_space;
 };
 #define to_rockchip_crtc_state(s) \
 		container_of(s, struct rockchip_crtc_state, base)
@@ -65,4 +83,6 @@ extern struct platform_driver rockchip_dp_driver;
 extern struct platform_driver rockchip_lvds_driver;
 extern struct platform_driver vop_platform_driver;
 extern struct platform_driver rk3066_hdmi_driver;
+extern struct platform_driver vop2_platform_driver;
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 857d97cdc67c6..1eccadf72b59b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -7,6 +7,8 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#include <drm/drm_modes.h>
+
 /*
  * major: IP major version, used for IP structure
  * minor: big feature change under same structure
@@ -15,6 +17,14 @@
 #define VOP_MAJOR(version)		((version) >> 8)
 #define VOP_MINOR(version)		((version) & 0xff)
 
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE    BIT(0)
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE      BIT(1)
+#define ROCKCHIP_OUTPUT_DATA_SWAP                       BIT(2)
+
+#define VOP_FEATURE_OUTPUT_10BIT        BIT(0)
+#define VOP_FEATURE_AFBDC               BIT(1)
+#define VOP_FEATURE_ALPHA_SCALE         BIT(2)
+
 #define NUM_YUV2YUV_COEFFICIENTS 12
 
 /* AFBC supports a number of configurable modes. Relevant to us is block size
@@ -54,9 +64,23 @@ struct vop_afbc {
 	struct vop_reg enable;
 	struct vop_reg win_sel;
 	struct vop_reg format;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg auto_gating_en;
+	struct vop_reg block_split_en;
+	struct vop_reg pic_vir_width;
+	struct vop_reg tile_num;
 	struct vop_reg hreg_block_split;
+	struct vop_reg pic_offset;
 	struct vop_reg pic_size;
+	struct vop_reg dsp_offset;
+	struct vop_reg transform_offset;
 	struct vop_reg hdr_ptr;
+	struct vop_reg half_block_en;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rotate_270;
+	struct vop_reg rotate_90;
 	struct vop_reg rstn;
 };
 
@@ -184,6 +208,12 @@ struct vop_win_phy {
 	struct vop_reg channel;
 };
 
+struct vop_grf_ctrl {
+	struct vop_reg grf_dclk_inv;
+	struct vop_reg grf_bt1120_clk_inv;
+	struct vop_reg grf_bt656_clk_inv;
+};
+
 struct vop_win_yuv2yuv_data {
 	uint32_t base;
 	const struct vop_yuv2yuv_phy *phy;
@@ -409,5 +439,749 @@ static inline int scl_vop_cal_lb_mode(int width, bool is_yuv)
 	return lb_mode;
 }
 
+static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
+{
+	return us * mode->clock / mode->htotal / 1000;
+}
+
 extern const struct component_ops vop_component_ops;
+
+#define WIN_FEATURE_HDR2SDR		BIT(0)
+#define WIN_FEATURE_SDR2HDR		BIT(1)
+#define WIN_FEATURE_PRE_OVERLAY		BIT(2)
+#define WIN_FEATURE_AFBDC		BIT(3)
+#define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
+#define WIN_FEATURE_CLUSTER_SUB		BIT(5)
+/* a mirror win can only get fb address
+ * from source win:
+ * Cluster1---->Cluster0
+ * Esmart1 ---->Esmart0
+ * Smart1  ---->Smart0
+ * This is a feather on rk3566
+ */
+#define WIN_FEATURE_MIRROR		BIT(6)
+#define WIN_FEATURE_MULTI_AREA		BIT(7)
+
+#define ROCKCHIP_MAX_LAYER       16
+#define MEDIA_BUS_FMT_SRGB888_3X8              0x101c
+#define WIN_FEATURE_MIRROR               BIT(6)
+#define MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA       0x101b
+#define MEDIA_BUS_FMT_SRGB888_DUMMY_4X8                0x101f
+
+/*
+ *  the delay number of a window in different mode.
+ */
+enum win_dly_mode {
+	VOP2_DLY_MODE_DEFAULT,   /**< default mode */
+	VOP2_DLY_MODE_HISO_S,    /** HDR in SDR out mode, as a SDR window */
+	VOP2_DLY_MODE_HIHO_H,    /** HDR in HDR out mode, as a HDR window */
+	VOP2_DLY_MODE_MAX,
+};
+
+struct vop_rect {
+	int width;
+	int height;
+};
+
+/* interrupt define */
+#define FS_NEW_INTR			BIT(4)
+#define ADDR_SAME_INTR			BIT(5)
+#define LINE_FLAG1_INTR			BIT(6)
+#define WIN0_EMPTY_INTR			BIT(7)
+#define WIN1_EMPTY_INTR			BIT(8)
+#define WIN2_EMPTY_INTR			BIT(9)
+#define WIN3_EMPTY_INTR			BIT(10)
+#define HWC_EMPTY_INTR			BIT(11)
+#define POST_BUF_EMPTY_INTR		BIT(12)
+#define PWM_GEN_INTR			BIT(13)
+#define DMA_FINISH_INTR			BIT(14)
+#define FS_FIELD_INTR			BIT(15)
+#define FE_INTR				BIT(16)
+#define WB_UV_FIFO_FULL_INTR		BIT(17)
+#define WB_YRGB_FIFO_FULL_INTR		BIT(18)
+#define WB_COMPLETE_INTR		BIT(19)
+
+#define VOP2_INTR_MASK			(DSP_HOLD_VALID_INTR | FS_INTR | \
+					 LINE_FLAG_INTR | BUS_ERROR_INTR | \
+					 FS_NEW_INTR | LINE_FLAG1_INTR | \
+					 WIN0_EMPTY_INTR | WIN1_EMPTY_INTR | \
+					 WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | \
+					 HWC_EMPTY_INTR | \
+					 POST_BUF_EMPTY_INTR | \
+					 DMA_FINISH_INTR | FS_FIELD_INTR | \
+					 FE_INTR)
+#define DSP_HOLD_VALID_INTR_EN(x)	((x) << 4)
+#define FS_INTR_EN(x)			((x) << 5)
+#define LINE_FLAG_INTR_EN(x)		((x) << 6)
+#define BUS_ERROR_INTR_EN(x)		((x) << 7)
+#define DSP_HOLD_VALID_INTR_MASK	(1 << 4)
+#define FS_INTR_MASK			(1 << 5)
+#define LINE_FLAG_INTR_MASK		(1 << 6)
+#define BUS_ERROR_INTR_MASK		(1 << 7)
+
+#define INTR_CLR_SHIFT			8
+#define DSP_HOLD_VALID_INTR_CLR		(1 << (INTR_CLR_SHIFT + 0))
+#define FS_INTR_CLR			(1 << (INTR_CLR_SHIFT + 1))
+#define LINE_FLAG_INTR_CLR		(1 << (INTR_CLR_SHIFT + 2))
+#define BUS_ERROR_INTR_CLR		(1 << (INTR_CLR_SHIFT + 3))
+
+#define DSP_LINE_NUM(x)			(((x) & 0x1fff) << 12)
+#define DSP_LINE_NUM_MASK		(0x1fff << 12)
+
+/* src alpha ctrl define */
+#define SRC_FADING_VALUE(x)		(((x) & 0xff) << 24)
+#define SRC_GLOBAL_ALPHA(x)		(((x) & 0xff) << 16)
+#define SRC_FACTOR_M0(x)		(((x) & 0x7) << 6)
+#define SRC_ALPHA_CAL_M0(x)		(((x) & 0x1) << 5)
+#define SRC_BLEND_M0(x)			(((x) & 0x3) << 3)
+#define SRC_ALPHA_M0(x)			(((x) & 0x1) << 2)
+#define SRC_COLOR_M0(x)			(((x) & 0x1) << 1)
+#define SRC_ALPHA_EN(x)			(((x) & 0x1) << 0)
+/* dst alpha ctrl define */
+#define DST_FACTOR_M0(x)		(((x) & 0x7) << 6)
+
+/*
+ * display output interface supported by rockchip lcdc
+ */
+#define ROCKCHIP_OUT_MODE_P888		0
+#define ROCKCHIP_OUT_MODE_BT1120	0
+#define ROCKCHIP_OUT_MODE_P666		1
+#define ROCKCHIP_OUT_MODE_P565		2
+#define ROCKCHIP_OUT_MODE_BT656		5
+#define ROCKCHIP_OUT_MODE_S888		8
+#define ROCKCHIP_OUT_MODE_S888_DUMMY	12
+#define ROCKCHIP_OUT_MODE_YUV420	14
+/* for use special outface */
+#define ROCKCHIP_OUT_MODE_AAAA		15
+
+#define ROCKCHIP_OUT_MODE_TYPE(x)	((x) >> 16)
+#define ROCKCHIP_OUT_MODE(x)		((x) & 0xffff)
+
+enum vop_csc_format {
+	CSC_BT601L,
+	CSC_BT709L,
+	CSC_BT601F,
+	CSC_BT2020,
+};
+
+enum src_factor_mode {
+	SRC_FAC_ALPHA_ZERO,
+	SRC_FAC_ALPHA_ONE,
+	SRC_FAC_ALPHA_DST,
+	SRC_FAC_ALPHA_DST_INVERSE,
+	SRC_FAC_ALPHA_SRC,
+	SRC_FAC_ALPHA_SRC_GLOBAL,
+};
+
+enum dst_factor_mode {
+	DST_FAC_ALPHA_ZERO,
+	DST_FAC_ALPHA_ONE,
+	DST_FAC_ALPHA_SRC,
+	DST_FAC_ALPHA_SRC_INVERSE,
+	DST_FAC_ALPHA_DST,
+	DST_FAC_ALPHA_DST_GLOBAL,
+};
+
+enum vop2_scale_up_mode {
+	VOP2_SCALE_UP_NRST_NBOR,
+	VOP2_SCALE_UP_BIL,
+	VOP2_SCALE_UP_BIC,
+};
+
+enum vop2_scale_down_mode {
+	VOP2_SCALE_DOWN_NRST_NBOR,
+	VOP2_SCALE_DOWN_BIL,
+	VOP2_SCALE_DOWN_AVG,
+};
+
+struct vop2_cluster_regs {
+	struct vop_reg enable;
+	struct vop_reg afbc_enable;
+	struct vop_reg lb_mode;
+};
+
+struct vop2_scl_regs {
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg yrgb_hscl_filter_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_vscl_filter_mode;
+	struct vop_reg cbcr_ver_scl_mode;
+	struct vop_reg cbcr_hscl_filter_mode;
+	struct vop_reg cbcr_hor_scl_mode;
+	struct vop_reg cbcr_vscl_filter_mode;
+	struct vop_reg vsd_cbcr_gt2;
+	struct vop_reg vsd_cbcr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+};
+
+struct vop2_win_regs {
+	const struct vop2_scl_regs *scl;
+	const struct vop2_cluster_regs *cluster;
+	const struct vop_afbc *afbc;
+
+	struct vop_reg gate;
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg csc_mode;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg act_info;
+	struct vop_reg dsp_info;
+	struct vop_reg dsp_st;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg yrgb_vir;
+	struct vop_reg uv_vir;
+	struct vop_reg yuv_clip;
+	struct vop_reg lb_mode;
+	struct vop_reg y2r_en;
+	struct vop_reg r2y_en;
+	struct vop_reg channel;
+	struct vop_reg dst_alpha_ctl;
+	struct vop_reg src_alpha_ctl;
+	struct vop_reg alpha_mode;
+	struct vop_reg alpha_en;
+	struct vop_reg global_alpha_val;
+	struct vop_reg color_key;
+	struct vop_reg color_key_en;
+	struct vop_reg dither_up;
+};
+
+struct vop2_video_port_regs {
+	struct vop_reg cfg_done;
+	struct vop_reg overlay_mode;
+	struct vop_reg dsp_background;
+	struct vop_reg port_mux;
+	struct vop_reg out_mode;
+	struct vop_reg standby;
+	struct vop_reg dsp_interlace;
+	struct vop_reg dsp_filed_pol;
+	struct vop_reg dsp_data_swap;
+	struct vop_reg post_dsp_out_r2y;
+	struct vop_reg pre_scan_htiming;
+	struct vop_reg htotal_pw;
+	struct vop_reg hact_st_end;
+	struct vop_reg vtotal_pw;
+	struct vop_reg vact_st_end;
+	struct vop_reg vact_st_end_f1;
+	struct vop_reg vs_st_end_f1;
+	struct vop_reg hpost_st_end;
+	struct vop_reg vpost_st_end;
+	struct vop_reg vpost_st_end_f1;
+	struct vop_reg post_scl_factor;
+	struct vop_reg post_scl_ctrl;
+	struct vop_reg dither_down_sel;
+	struct vop_reg dither_down_mode;
+	struct vop_reg dither_down_en;
+	struct vop_reg pre_dither_down_en;
+	struct vop_reg dither_up_en;
+	struct vop_reg bg_dly;
+
+	struct vop_reg core_dclk_div;
+	struct vop_reg p2i_en;
+	struct vop_reg mipi_dual_en;
+	struct vop_reg mipi_dual_channel_swap;
+	struct vop_reg dsp_lut_en;
+
+	struct vop_reg dclk_div2;
+	struct vop_reg dclk_div2_phase_lock;
+
+	struct vop_reg hdr10_en;
+	struct vop_reg hdr_lut_update_en;
+	struct vop_reg hdr_lut_mode;
+	struct vop_reg hdr_lut_mst;
+	struct vop_reg sdr2hdr_eotf_en;
+	struct vop_reg sdr2hdr_r2r_en;
+	struct vop_reg sdr2hdr_r2r_mode;
+	struct vop_reg sdr2hdr_oetf_en;
+	struct vop_reg sdr2hdr_bypass_en;
+	struct vop_reg sdr2hdr_auto_gating_en;
+	struct vop_reg sdr2hdr_path_en;
+	struct vop_reg hdr2sdr_en;
+	struct vop_reg hdr2sdr_bypass_en;
+	struct vop_reg hdr2sdr_auto_gating_en;
+	struct vop_reg hdr2sdr_src_min;
+	struct vop_reg hdr2sdr_src_max;
+	struct vop_reg hdr2sdr_normfaceetf;
+	struct vop_reg hdr2sdr_dst_min;
+	struct vop_reg hdr2sdr_dst_max;
+	struct vop_reg hdr2sdr_normfacgamma;
+	uint32_t hdr2sdr_eetf_oetf_y0_offset;
+	uint32_t hdr2sdr_sat_y0_offset;
+	uint32_t sdr2hdr_eotf_oetf_y0_offset;
+	uint32_t sdr2hdr_oetf_dx_pow1_offset;
+	uint32_t sdr2hdr_oetf_xn1_offset;
+	struct vop_reg hdr_src_color_ctrl;
+	struct vop_reg hdr_dst_color_ctrl;
+	struct vop_reg hdr_src_alpha_ctrl;
+	struct vop_reg hdr_dst_alpha_ctrl;
+
+	/* BCSH */
+	struct vop_reg bcsh_brightness;
+	struct vop_reg bcsh_contrast;
+	struct vop_reg bcsh_sat_con;
+	struct vop_reg bcsh_sin_hue;
+	struct vop_reg bcsh_cos_hue;
+	struct vop_reg bcsh_r2y_csc_mode;
+	struct vop_reg bcsh_r2y_en;
+	struct vop_reg bcsh_y2r_csc_mode;
+	struct vop_reg bcsh_y2r_en;
+	struct vop_reg bcsh_out_mode;
+	struct vop_reg bcsh_en;
+
+	/* 3d lut */
+	struct vop_reg cubic_lut_en;
+	struct vop_reg cubic_lut_update_en;
+	struct vop_reg cubic_lut_mst;
+};
+
+struct vop2_wb_regs {
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg dither_en;
+	struct vop_reg r2y_en;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg vp_id;
+	struct vop_reg fifo_throd;
+	struct vop_reg scale_x_factor;
+	struct vop_reg scale_x_en;
+	struct vop_reg scale_y_en;
+	struct vop_reg axi_yrgb_id;
+	struct vop_reg axi_uv_id;
+};
+
+struct vop2_win_data {
+	const char *name;
+	uint8_t phys_id;
+
+	uint32_t base;
+	enum drm_plane_type type;
+
+	uint32_t nformats;
+	const uint32_t *formats;
+	const uint64_t *format_modifiers;
+	const unsigned int supported_rotations;
+
+	const struct vop2_win_regs *regs;
+
+	/*
+	 * vertical/horizontal scale up/down filter mode
+	 */
+	const u8 hsu_filter_mode;
+	const u8 hsd_filter_mode;
+	const u8 vsu_filter_mode;
+	const u8 vsd_filter_mode;
+	/**
+	 * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2
+	 */
+	int layer_sel_id;
+	uint64_t feature;
+
+	unsigned int max_upscale_factor;
+	unsigned int max_downscale_factor;
+	const uint8_t dly[VOP2_DLY_MODE_MAX];
+};
+
+struct vop2_wb_data {
+	uint32_t nformats;
+	const uint32_t *formats;
+	struct vop_rect max_output;
+	const struct vop2_wb_regs *regs;
+};
+
+struct vop2_video_port_data {
+	char id;
+	uint32_t feature;
+	uint16_t gamma_lut_len;
+	uint16_t cubic_lut_len;
+	struct vop_rect max_output;
+	const u8 pre_scan_max_dly[4];
+	const struct vop_intr *intr;
+	const struct vop2_video_port_regs *regs;
+};
+
+struct vop2_layer_regs {
+	struct vop_reg layer_sel;
+};
+
+/**
+ * struct vop2_layer_data - The logic graphic layer in vop2
+ *
+ * The zorder:
+ *   LAYERn
+ *   LAYERn-1
+ *     .
+ *     .
+ *     .
+ *   LAYER5
+ *   LAYER4
+ *   LAYER3
+ *   LAYER2
+ *   LAYER1
+ *   LAYER0
+ *
+ * Each layer can select a unused window as input than feed to
+ * mixer for overlay.
+ *
+ * The pipeline in vop2:
+ *
+ * win-->layer-->mixer-->vp--->connector(RGB/LVDS/HDMI/MIPI)
+ *
+ */
+struct vop2_layer_data {
+	char id;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_ctrl {
+	struct vop_reg cfg_done_en;
+	struct vop_reg wb_cfg_done;
+	struct vop_reg auto_gating_en;
+	struct vop_reg ovl_cfg_done_port;
+	struct vop_reg ovl_port_mux_cfg_done_imd;
+	struct vop_reg ovl_port_mux_cfg;
+	struct vop_reg if_ctrl_cfg_done_imd;
+	struct vop_reg version;
+	struct vop_reg standby;
+	struct vop_reg dma_stop;
+	struct vop_reg lut_dma_en;
+	struct vop_reg axi_outstanding_max_num;
+	struct vop_reg axi_max_outstanding_en;
+	struct vop_reg hdmi_dclk_out_en;
+	struct vop_reg rgb_en;
+	struct vop_reg hdmi0_en;
+	struct vop_reg hdmi1_en;
+	struct vop_reg dp0_en;
+	struct vop_reg dp1_en;
+	struct vop_reg edp0_en;
+	struct vop_reg edp1_en;
+	struct vop_reg mipi0_en;
+	struct vop_reg mipi1_en;
+	struct vop_reg lvds0_en;
+	struct vop_reg lvds1_en;
+	struct vop_reg bt656_en;
+	struct vop_reg bt1120_en;
+	struct vop_reg dclk_pol;
+	struct vop_reg pin_pol;
+	struct vop_reg rgb_dclk_pol;
+	struct vop_reg rgb_pin_pol;
+	struct vop_reg lvds_dclk_pol;
+	struct vop_reg lvds_pin_pol;
+	struct vop_reg hdmi_dclk_pol;
+	struct vop_reg hdmi_pin_pol;
+	struct vop_reg edp_dclk_pol;
+	struct vop_reg edp_pin_pol;
+	struct vop_reg mipi_dclk_pol;
+	struct vop_reg mipi_pin_pol;
+	struct vop_reg dp_dclk_pol;
+	struct vop_reg dp_pin_pol;
+
+	struct vop_reg win_vp_id[8];
+	struct vop_reg win_dly[8];
+
+	/* connector mux */
+	struct vop_reg rgb_mux;
+	struct vop_reg hdmi0_mux;
+	struct vop_reg hdmi1_mux;
+	struct vop_reg dp0_mux;
+	struct vop_reg dp1_mux;
+	struct vop_reg edp0_mux;
+	struct vop_reg edp1_mux;
+	struct vop_reg mipi0_mux;
+	struct vop_reg mipi1_mux;
+	struct vop_reg lvds0_mux;
+	struct vop_reg lvds1_mux;
+
+	struct vop_reg lvds_dual_en;
+	struct vop_reg lvds_dual_mode;
+	struct vop_reg lvds_dual_channel_swap;
+
+	struct vop_reg cluster0_src_color_ctrl;
+	struct vop_reg cluster0_dst_color_ctrl;
+	struct vop_reg cluster0_src_alpha_ctrl;
+	struct vop_reg cluster0_dst_alpha_ctrl;
+	struct vop_reg src_color_ctrl;
+	struct vop_reg dst_color_ctrl;
+	struct vop_reg src_alpha_ctrl;
+	struct vop_reg dst_alpha_ctrl;
+
+	struct vop_reg bt1120_yc_swap;
+	struct vop_reg bt656_yc_swap;
+	struct vop_reg gamma_port_sel;
+
+	struct vop_reg otp_en;
+	struct vop_reg reg_done_frm;
+	struct vop_reg cfg_done;
+};
+
+/**
+ * VOP2 data struct
+ *
+ * @version: VOP IP version
+ * @win_size: hardware win number
+ */
+struct vop2_data {
+	uint8_t nr_vps;
+	uint8_t nr_mixers;
+	uint8_t nr_layers;
+	uint8_t nr_axi_intr;
+	uint8_t nr_gammas;
+	const struct vop_intr *axi_intr;
+	const struct vop2_ctrl *ctrl;
+	const struct vop2_win_data *win;
+	const struct vop2_video_port_data *vp;
+	const struct vop2_wb_data *wb;
+	const struct vop2_layer_data *layer;
+	const struct vop_csc_table *csc_table;
+	const struct vop_grf_ctrl *grf_ctrl;
+	struct vop_rect max_input;
+	struct vop_rect max_output;
+
+	unsigned int win_size;
+	unsigned int soc_id;
+};
+
+#define RK3568_GRF_VO_CON1			0x0364
+/* System registers definition */
+#define RK3568_REG_CFG_DONE			0x000
+#define RK3568_VOP2_WB_CFG_DONE			BIT(14)
+#define RK3568_VOP2_GLB_CFG_DONE_EN		BIT(15)
+#define RK3568_VERSION_INFO			0x004
+#define RK3568_SYS_AUTO_GATING_CTRL		0x008
+#define RK3568_SYS_AXI_LUT_CTRL			0x024
+#define RK3568_DSP_IF_EN			0x028
+#define RK3568_DSP_IF_CTRL			0x02c
+#define RK3568_DSP_IF_POL			0x030
+#define RK3568_WB_CTRL				0x40
+#define RK3568_WB_XSCAL_FACTOR			0x44
+#define RK3568_WB_YRGB_MST			0x48
+#define RK3568_WB_CBR_MST			0x4C
+#define RK3568_OTP_WIN_EN			0x050
+#define RK3568_LUT_PORT_SEL			0x058
+#define RK3568_SYS_STATUS0			0x060
+#define RK3568_VP0_LINE_FLAG			0x70
+#define RK3568_VP1_LINE_FLAG			0x74
+#define RK3568_VP2_LINE_FLAG			0x78
+#define RK3568_SYS0_INT_EN			0x80
+#define RK3568_SYS0_INT_CLR			0x84
+#define RK3568_SYS0_INT_STATUS			0x88
+#define RK3568_SYS1_INT_EN			0x90
+#define RK3568_SYS1_INT_CLR			0x94
+#define RK3568_SYS1_INT_STATUS			0x98
+#define RK3568_VP0_INT_EN			0xA0
+#define RK3568_VP0_INT_CLR			0xA4
+#define RK3568_VP0_INT_STATUS			0xA8
+#define RK3568_VP0_INT_RAW_STATUS		0xAC
+#define RK3568_VP1_INT_EN			0xB0
+#define RK3568_VP1_INT_CLR			0xB4
+#define RK3568_VP1_INT_STATUS			0xB8
+#define RK3568_VP1_INT_RAW_STATUS		0xBC
+#define RK3568_VP2_INT_EN			0xC0
+#define RK3568_VP2_INT_CLR			0xC4
+#define RK3568_VP2_INT_STATUS			0xC8
+#define RK3568_VP2_INT_RAW_STATUS		0xCC
+
+/* Video Port registers definition */
+#define RK3568_VP0_DSP_CTRL			0xC00
+#define RK3568_VP0_MIPI_CTRL			0xC04
+#define RK3568_VP0_COLOR_BAR_CTRL		0xC08
+#define RK3568_VP0_3D_LUT_CTRL			0xC10
+#define RK3568_VP0_3D_LUT_MST			0xC20
+#define RK3568_VP0_DSP_BG			0xC2C
+#define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
+#define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
+#define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
+#define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
+#define RK3568_VP0_POST_SCL_CTRL		0xC40
+#define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
+#define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
+#define RK3568_VP0_DSP_HACT_ST_END		0xC4C
+#define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
+#define RK3568_VP0_DSP_VACT_ST_END		0xC54
+#define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
+#define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
+#define RK3568_VP0_BCSH_CTRL			0xC60
+#define RK3568_VP0_BCSH_BCS			0xC64
+#define RK3568_VP0_BCSH_H			0xC68
+#define RK3568_VP0_BCSH_COLOR_BAR		0xC6C
+
+#define RK3568_VP1_DSP_CTRL			0xD00
+#define RK3568_VP1_MIPI_CTRL			0xD04
+#define RK3568_VP1_COLOR_BAR_CTRL		0xD08
+#define RK3568_VP1_DSP_BG			0xD2C
+#define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
+#define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
+#define RK3568_VP1_POST_SCL_CTRL		0xD40
+#define RK3568_VP1_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
+#define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
+#define RK3568_VP1_DSP_HACT_ST_END		0xD4C
+#define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
+#define RK3568_VP1_DSP_VACT_ST_END		0xD54
+#define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
+#define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
+#define RK3568_VP1_BCSH_CTRL			0xD60
+#define RK3568_VP1_BCSH_BCS			0xD64
+#define RK3568_VP1_BCSH_H			0xD68
+#define RK3568_VP1_BCSH_COLOR_BAR		0xD6C
+
+#define RK3568_VP2_DSP_CTRL			0xE00
+#define RK3568_VP2_MIPI_CTRL			0xE04
+#define RK3568_VP2_COLOR_BAR_CTRL		0xE08
+#define RK3568_VP2_DSP_BG			0xE2C
+#define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
+#define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
+#define RK3568_VP2_POST_SCL_CTRL		0xE40
+#define RK3568_VP2_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
+#define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
+#define RK3568_VP2_DSP_HACT_ST_END		0xE4C
+#define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
+#define RK3568_VP2_DSP_VACT_ST_END		0xE54
+#define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
+#define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
+#define RK3568_VP2_BCSH_CTRL			0xE60
+#define RK3568_VP2_BCSH_BCS			0xE64
+#define RK3568_VP2_BCSH_H			0xE68
+#define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
+
+/* Overlay registers definition    */
+#define RK3568_OVL_CTRL				0x600
+#define RK3568_OVL_LAYER_SEL			0x604
+#define RK3568_OVL_PORT_SEL			0x608
+#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
+#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
+#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
+#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
+#define RK3568_MIX0_SRC_COLOR_CTRL		0x650
+#define RK3568_MIX0_DST_COLOR_CTRL		0x654
+#define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
+#define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
+#define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
+#define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
+#define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
+#define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
+#define RK3568_VP0_BG_MIX_CTRL			0x6E0
+#define RK3568_VP1_BG_MIX_CTRL			0x6E4
+#define RK3568_VP2_BG_MIX_CTRL			0x6E8
+#define RK3568_CLUSTER_DLY_NUM			0x6F0
+#define RK3568_SMART_DLY_NUM			0x6F8
+
+/* Cluster register definition, offset relative to window base */
+#define RK3568_CLUSTER_WIN_CTRL0		0x00
+#define RK3568_CLUSTER_WIN_CTRL1		0x04
+#define RK3568_CLUSTER_WIN_YRGB_MST		0x10
+#define RK3568_CLUSTER_WIN_CBR_MST		0x14
+#define RK3568_CLUSTER_WIN_VIR			0x18
+#define RK3568_CLUSTER_WIN_ACT_INFO		0x20
+#define RK3568_CLUSTER_WIN_DSP_INFO		0x24
+#define RK3568_CLUSTER_WIN_DSP_ST		0x28
+#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB	0x30
+#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET	0x3C
+#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL	0x50
+#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE	0x54
+#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR	0x58
+#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH	0x5C
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE	0x60
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET	0x64
+#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET	0x68
+#define RK3568_CLUSTER_WIN_AFBCD_CTRL		0x6C
+
+#define RK3568_CLUSTER_CTRL			0x100
+
+/* (E)smart register definition, offset relative to window base */
+#define RK3568_SMART_CTRL0			0x00
+#define RK3568_SMART_CTRL1			0x04
+#define RK3568_SMART_REGION0_CTRL		0x10
+#define RK3568_SMART_REGION0_YRGB_MST		0x14
+#define RK3568_SMART_REGION0_CBR_MST		0x18
+#define RK3568_SMART_REGION0_VIR		0x1C
+#define RK3568_SMART_REGION0_ACT_INFO		0x20
+#define RK3568_SMART_REGION0_DSP_INFO		0x24
+#define RK3568_SMART_REGION0_DSP_ST		0x28
+#define RK3568_SMART_REGION0_SCL_CTRL		0x30
+#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB	0x34
+#define RK3568_SMART_REGION0_SCL_FACTOR_CBR	0x38
+#define RK3568_SMART_REGION0_SCL_OFFSET		0x3C
+#define RK3568_SMART_REGION1_CTRL		0x40
+#define RK3568_SMART_REGION1_YRGB_MST		0x44
+#define RK3568_SMART_REGION1_CBR_MST		0x48
+#define RK3568_SMART_REGION1_VIR		0x4C
+#define RK3568_SMART_REGION1_ACT_INFO		0x50
+#define RK3568_SMART_REGION1_DSP_INFO		0x54
+#define RK3568_SMART_REGION1_DSP_ST		0x58
+#define RK3568_SMART_REGION1_SCL_CTRL		0x60
+#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB	0x64
+#define RK3568_SMART_REGION1_SCL_FACTOR_CBR	0x68
+#define RK3568_SMART_REGION1_SCL_OFFSET		0x6C
+#define RK3568_SMART_REGION2_CTRL		0x70
+#define RK3568_SMART_REGION2_YRGB_MST		0x74
+#define RK3568_SMART_REGION2_CBR_MST		0x78
+#define RK3568_SMART_REGION2_VIR		0x7C
+#define RK3568_SMART_REGION2_ACT_INFO		0x80
+#define RK3568_SMART_REGION2_DSP_INFO		0x84
+#define RK3568_SMART_REGION2_DSP_ST		0x88
+#define RK3568_SMART_REGION2_SCL_CTRL		0x90
+#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB	0x94
+#define RK3568_SMART_REGION2_SCL_FACTOR_CBR	0x98
+#define RK3568_SMART_REGION2_SCL_OFFSET		0x9C
+#define RK3568_SMART_REGION3_CTRL		0xA0
+#define RK3568_SMART_REGION3_YRGB_MST		0xA4
+#define RK3568_SMART_REGION3_CBR_MST		0xA8
+#define RK3568_SMART_REGION3_VIR		0xAC
+#define RK3568_SMART_REGION3_ACT_INFO		0xB0
+#define RK3568_SMART_REGION3_DSP_INFO		0xB4
+#define RK3568_SMART_REGION3_DSP_ST		0xB8
+#define RK3568_SMART_REGION3_SCL_CTRL		0xC0
+#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB	0xC4
+#define RK3568_SMART_REGION3_SCL_FACTOR_CBR	0xC8
+#define RK3568_SMART_REGION3_SCL_OFFSET		0xCC
+#define RK3568_SMART_COLOR_KEY_CTRL		0xD0
+
+/* HDR register definition */
+#define RK3568_HDR_LUT_CTRL				0x2000
+#define RK3568_HDR_LUT_MST				0x2004
+#define RK3568_SDR2HDR_CTRL				0x2010
+#define RK3568_HDR2SDR_CTRL				0x2020
+#define RK3568_HDR2SDR_SRC_RANGE			0x2024
+#define RK3568_HDR2SDR_NORMFACEETF			0x2028
+#define RK3568_HDR2SDR_DST_RANGE			0x202C
+#define RK3568_HDR2SDR_NORMFACCGAMMA			0x2030
+#define RK3568_HDR_EETF_OETF_Y0				0x203C
+#define RK3568_HDR_SAT_Y0				0x20C0
+#define RK3568_HDR_EOTF_OETF_Y0				0x20F0
+#define RK3568_HDR_OETF_DX_POW1				0x2200
+#define RK3568_HDR_OETF_XN1				0x2300
+
+enum vop2_layer_phy_id {
+	ROCKCHIP_VOP2_CLUSTER0 = 0,
+	ROCKCHIP_VOP2_CLUSTER1,
+	ROCKCHIP_VOP2_ESMART0,
+	ROCKCHIP_VOP2_ESMART1,
+	ROCKCHIP_VOP2_SMART0,
+	ROCKCHIP_VOP2_SMART1,
+	ROCKCHIP_VOP2_CLUSTER2,
+	ROCKCHIP_VOP2_CLUSTER3,
+	ROCKCHIP_VOP2_ESMART2,
+	ROCKCHIP_VOP2_ESMART3,
+	ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
+};
+
+extern const struct component_ops vop2_component_ops;
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
new file mode 100644
index 0000000000000..60fa529718810
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -0,0 +1,3611 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+#include <drm/drm.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_writeback.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_atomic_uapi.h>
+
+#include <linux/debugfs.h>
+#include <linux/fixp-arith.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <linux/component.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/swab.h>
+#include <linux/sort.h>
+#include <drm/drm_debugfs.h>
+#include <uapi/linux/videodev2.h>
+#include <drm/drm_vblank.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_gem.h"
+#include "rockchip_drm_fb.h"
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define VOP2_SYS_AXI_BUS_NUM 2
+
+#define VOP2_CLUSTER_YUV444_10 0x12
+
+#define VOP2_COLOR_KEY_MASK		(1 << 31)
+
+#define DSP_BG_SWAP             0x1
+#define DSP_RB_SWAP             0x2
+#define DSP_RG_SWAP             0x4
+#define DSP_DELTA_SWAP          0x8
+
+enum vop2_data_format {
+	VOP2_FMT_ARGB8888 = 0,
+	VOP2_FMT_RGB888,
+	VOP2_FMT_RGB565,
+	VOP2_FMT_XRGB101010,
+	VOP2_FMT_YUV420SP,
+	VOP2_FMT_YUV422SP,
+	VOP2_FMT_YUV444SP,
+	VOP2_FMT_YUYV422 = 8,
+	VOP2_FMT_YUYV420,
+	VOP2_FMT_VYUY422,
+	VOP2_FMT_VYUY420,
+	VOP2_FMT_YUV420SP_TILE_8x4 = 0x10,
+	VOP2_FMT_YUV420SP_TILE_16x2,
+	VOP2_FMT_YUV422SP_TILE_8x4,
+	VOP2_FMT_YUV422SP_TILE_16x2,
+	VOP2_FMT_YUV420SP_10,
+	VOP2_FMT_YUV422SP_10,
+	VOP2_FMT_YUV444SP_10,
+};
+
+enum vop2_afbc_format {
+	VOP2_AFBC_FMT_RGB565,
+	VOP2_AFBC_FMT_ARGB2101010 = 2,
+	VOP2_AFBC_FMT_YUV420_10BIT,
+	VOP2_AFBC_FMT_RGB888,
+	VOP2_AFBC_FMT_ARGB8888,
+	VOP2_AFBC_FMT_YUV420 = 9,
+	VOP2_AFBC_FMT_YUV422 = 0xb,
+	VOP2_AFBC_FMT_YUV422_10BIT = 0xe,
+	VOP2_AFBC_FMT_INVALID = -1,
+};
+
+enum vop2_hdr_lut_mode {
+	VOP2_HDR_LUT_MODE_AXI,
+	VOP2_HDR_LUT_MODE_AHB,
+};
+
+enum vop2_pending {
+	VOP_PENDING_FB_UNREF,
+};
+
+struct vop2_zpos {
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	int zpos;
+};
+
+union vop2_alpha_ctrl {
+	uint32_t val;
+	struct {
+		/* [0:1] */
+		uint32_t color_mode:1;
+		uint32_t alpha_mode:1;
+		/* [2:3] */
+		uint32_t blend_mode:2;
+		uint32_t alpha_cal_mode:1;
+		/* [5:7] */
+		uint32_t factor_mode:3;
+		/* [8:9] */
+		uint32_t alpha_en:1;
+		uint32_t src_dst_swap:1;
+		uint32_t reserved:6;
+		/* [16:23] */
+		uint32_t glb_alpha:8;
+	} bits;
+};
+
+struct vop2_alpha {
+	union vop2_alpha_ctrl src_color_ctrl;
+	union vop2_alpha_ctrl dst_color_ctrl;
+	union vop2_alpha_ctrl src_alpha_ctrl;
+	union vop2_alpha_ctrl dst_alpha_ctrl;
+};
+
+struct vop2_alpha_config {
+	bool src_premulti_en;
+	bool dst_premulti_en;
+	bool src_pixel_alpha_en;
+	bool dst_pixel_alpha_en;
+	uint16_t src_glb_alpha_value;
+	uint16_t dst_glb_alpha_value;
+};
+
+struct vop2_win {
+	const char *name;
+	struct vop2 *vop2;
+	struct drm_plane base;
+	const struct vop2_win_data *data;
+
+	/*
+	 * This is for cluster window
+	 *
+	 * A cluster window can split as two windows:
+	 * a main window and a sub window.
+	 */
+	bool two_win_mode;
+
+	/**
+	 * @win_id: graphic window id, a cluster maybe split into two
+	 * graphics windows.
+	 */
+	uint8_t win_id;
+	/**
+	 * @plane_id: unique plane id.
+	 */
+	uint8_t plane_id;
+	/**
+	 * @layer_id: id of the layer which the window attached to
+	 */
+	uint8_t layer_id;
+	int layer_sel_id;
+	/**
+	 * @vp_mask: Bitmask of video_port0/1/2 this win attached to,
+	 * one win can only attach to one vp at the one time.
+	 */
+	uint8_t vp_mask;
+	/**
+	 * @old_vp_mask: Bitmask of video_port0/1/2 this win attached of last commit,
+	 * this is used for trackng the change of VOP2_PORT_SEL register.
+	 */
+	uint8_t old_vp_mask;
+	uint8_t zpos;
+	uint32_t offset;
+	enum drm_plane_type type;
+
+	const struct vop2_win_regs *regs;
+};
+
+struct vop2_cluster {
+	struct vop2_win *main;
+	struct vop2_win *sub;
+};
+
+struct vop2_layer {
+	uint8_t id;
+	struct vop2_win *win;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_video_port {
+	struct drm_crtc crtc;
+	struct vop2 *vop2;
+	struct clk *dclk;
+	uint8_t id;
+	bool layer_sel_update;
+	const struct vop2_video_port_regs *regs;
+
+	struct completion dsp_hold_completion;
+	struct completion line_flag_completion;
+
+	/* protected by dev->event_lock */
+	struct drm_pending_vblank_event *event;
+
+	struct drm_flip_work fb_unref_work;
+	unsigned long pending;
+
+	struct vop2_zpos *zpos;
+	int nr_layers;
+
+	/**
+	 * @skip_vsync: skip on vsync when port_mux changed on this vp.
+	 * a win move from one VP to another need wait one vsync until
+	 * port_mut take effect before this win can be enabled.
+	 *
+	 */
+	bool skip_vsync;
+
+	/**
+	 * @bg_ovl_dly: The timing delay from background layer
+	 * to overlay module.
+	 */
+	uint8_t bg_ovl_dly;
+
+	/**
+	 * @win_mask: Bitmask of wins attached to the video port;
+	 */
+	uint32_t win_mask;
+
+	/**
+	 * @gamma_lut_len: gamma look up table size
+	 */
+	uint32_t gamma_lut_len;
+
+	/**
+	 * @gamma_lut_active: gamma states
+	 */
+	bool gamma_lut_active;
+
+	struct vop2_win *primary_plane;
+};
+
+struct vop2 {
+	struct device *dev;
+	struct drm_device *drm;
+	struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
+
+	const struct vop2_data *data;
+	/* Number of win that registered as plane,
+	 * maybe less than the total number of hardware
+	 * win.
+	 */
+	uint32_t registered_num_wins;
+	uint8_t used_mixers;
+
+	uint16_t port_mux_cfg;
+
+	uint32_t *regsbak;
+	void __iomem *regs;
+	struct regmap *grf;
+
+	/* physical map length of vop2 register */
+	uint32_t len;
+
+	void __iomem *lut_regs;
+	/* one time only one process allowed to config the register */
+	spinlock_t reg_lock;
+	/* lock vop2 irq reg */
+	spinlock_t irq_lock;
+	/* protects crtc enable/disable */
+	struct mutex vop2_lock;
+
+	int irq;
+
+	/*
+	 * Some globle resource are shared between all
+	 * the vidoe ports(crtcs), so we need a ref counter here.
+	 */
+	unsigned int enable_count;
+	struct clk *hclk;
+	struct clk *aclk;
+
+	struct vop2_layer layers[ROCKCHIP_MAX_LAYER];
+	/* must put at the end of the struct */
+	struct vop2_win win[];
+};
+
+static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct vop2_video_port, crtc);
+}
+
+static inline struct vop2_win *to_vop2_win(struct drm_plane *p)
+{
+	return container_of(p, struct vop2_win, base);
+}
+
+static void vop2_lock(struct vop2 *vop2)
+{
+	mutex_lock(&vop2->vop2_lock);
+}
+
+static void vop2_unlock(struct vop2 *vop2)
+{
+	mutex_unlock(&vop2->vop2_lock);
+}
+
+static inline void vop2_grf_writel(struct vop2 *vop2, struct vop_reg reg, uint32_t v)
+{
+	uint32_t val = 0;
+
+	if (IS_ERR_OR_NULL(vop2->grf))
+		return;
+
+	if (reg.mask) {
+		val = (v << reg.shift) | (reg.mask << (reg.shift + 16));
+		regmap_write(vop2->grf, reg.offset, val);
+	}
+}
+
+static void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v)
+{
+	writel(v, vop2->regs + offset);
+	vop2->regsbak[offset >> 2] = v;
+}
+
+static uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset)
+{
+	return readl(vop2->regs + offset);
+}
+
+static uint32_t vop2_read_reg(struct vop2 *vop2, uint32_t offset,
+			      const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, offset + reg->offset) >> reg->shift) & reg->mask;
+}
+
+static inline uint32_t vop2_read(struct vop2 *vop2, const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, reg->offset) >> reg->shift) & reg->mask;
+}
+
+static void vop2_write_reg(struct vop2 *vop2, uint32_t offset, const struct vop_reg *reg,
+				   uint32_t v, bool relaxed)
+{
+	uint32_t mask = reg->mask;
+	uint32_t shift = reg->shift;
+
+	if (!mask)
+		return;
+
+	offset += reg->offset;
+
+	if (reg->write_mask) {
+		v = ((v & mask) << shift) | (mask << (shift + 16));
+	} else {
+		/*
+		 * Several registers in the VOP2 are double buffered and read back
+		 * the new values only after config_done bits have been set. As we
+		 * read-modify-write the hardware registers we need to cache the values
+		 * in memory to make sure we do not overwrite previous values when a
+		 * hardware register is modified multiple times before config_done is
+		 * set.
+		 */
+		uint32_t cached_val = vop2->regsbak[offset >> 2];
+
+		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
+		vop2->regsbak[offset >> 2] = v;
+	}
+
+	if (relaxed)
+		writel_relaxed(v, vop2->regs + offset);
+	else
+		writel(v, vop2->regs + offset);
+}
+
+static void vop2_write(struct vop2 *vop2, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(vop2, 0, reg, v, false);
+}
+
+static void vop2_win_write(const struct vop2_win *win, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(win->vop2, win->offset, reg, v, true);
+}
+
+static uint32_t vop2_win_read(const struct vop2_win *win, const struct vop_reg *reg)
+{
+	return vop2_read_reg(win->vop2, win->offset, reg);
+}
+
+
+static void vop2_intr_set_type(struct vop2 *vop2, const struct vop_intr *intr,
+			       const struct vop_reg *reg, uint32_t type, bool enable)
+{
+	uint32_t v = 0, mask = 0;
+	int i;
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if (intr->intrs[i] & type) {
+			if (enable)
+				v |= 1 << i;
+			mask |= 1 << i;
+		}
+	}
+
+	writel(v | (mask << 16), vop2->regs + reg->offset);
+}
+
+static inline uint32_t vop2_line_to_time(struct drm_display_mode *mode, int line)
+{
+	u64 val = 1000000000ULL * mode->crtc_htotal * line;
+
+	do_div(val, mode->crtc_clock);
+	do_div(val, 1000000);
+
+	return val; /* us */
+}
+
+static inline uint32_t vop2_get_intr_type(struct vop2 *vop2, const struct vop_intr *intr,
+					  const struct vop_reg *reg, int type)
+{
+	uint32_t val, i;
+	uint32_t ret = 0;
+
+	val = vop2_read_reg(vop2, 0, reg);
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if ((type & intr->intrs[i]) && (val & 1 << i))
+			ret |= intr->intrs[i];
+	}
+
+	return ret;
+}
+
+/*
+ * phys_id is used to identify a main window(Cluster Win/Smart Win, not
+ * include the sub win of a cluster or the multi area) that can do
+ * overlay in main overlay stage.
+ */
+static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys_id)
+{
+	struct vop2_win *win;
+	int i;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+		if (win->data->phys_id == phys_id)
+			return win;
+	}
+
+	return NULL;
+}
+
+static bool vop2_fs_irq_is_pending(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	return vop2_get_intr_type(vop2, intr, &intr->status, FS_FIELD_INTR);
+}
+
+static uint32_t vop2_read_vcnt(struct vop2_video_port *vp)
+{
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint32_t offset = RK3568_SYS_STATUS0 + (vp->id << 2);
+	uint32_t vcnt;
+
+	vcnt = vop2_readl(vp->vop2, offset) >> 16;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vcnt >>= 1;
+
+	return vcnt;
+}
+
+static void vop2_wait_for_irq_handler(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	bool pending;
+	int ret;
+
+	/*
+	 * Spin until frame start interrupt status bit goes low, which means
+	 * that interrupt handler was invoked and cleared it. The timeout of
+	 * 10 msecs is really too long, but it is just a safety measure if
+	 * something goes really wrong. The wait will only happen in the very
+	 * unlikely case of a vblank happening exactly at the same time and
+	 * shouldn't exceed microseconds range.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_fs_irq_is_pending, vp, pending,
+					!pending, 0, 10 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "VOP vblank IRQ stuck for 10 ms\n");
+
+	synchronize_irq(vop2->irq);
+}
+
+static bool vop2_vp_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & BIT(vp->id);
+
+	/*
+	 * When done bit is 0, indicate current frame is take effect.
+	 */
+	return done_bits == 0 ? true : false;
+}
+
+static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	bool done_bit;
+	int ret;
+
+	ret = readx_poll_timeout_atomic(vop2_vp_done_bit_status, vp, done_bit,
+					done_bit, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait vp%d done bit status timeout, vcnt: %d\n",
+			      vp->id, vop2_read_vcnt(vp));
+}
+
+static uint16_t vop2_read_port_mux(struct vop2 *vop2)
+{
+	return vop2_readl(vop2, RK3568_OVL_PORT_SEL) & 0xffff;
+}
+
+static void vop2_wait_for_port_mux_done(struct vop2 *vop2)
+{
+	uint16_t port_mux_cfg;
+	int ret;
+
+	/*
+	 * Spin until the previous port_mux figuration
+	 * is done.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_read_port_mux, vop2, port_mux_cfg,
+					port_mux_cfg == vop2->port_mux_cfg, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait port_mux done timeout: 0x%x--0x%x\n",
+			      port_mux_cfg, vop2->port_mux_cfg);
+}
+
+
+static int32_t vop2_pending_done_bits(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *adjusted_mode;
+	struct vop2_video_port *done_vp;
+	uint32_t done_bits, done_bits_bak;
+	uint32_t vp_id;
+	uint32_t vcnt;
+	struct drm_display_mode *first_mode, *second_mode;
+	struct vop2_video_port *first_done_vp, *second_done_vp, *wait_vp;
+	uint32_t first_vp_id, second_vp_id;
+	uint32_t first_vp_vcnt, second_vp_vcnt;
+	uint32_t first_vp_left_vcnt, second_vp_left_vcnt;
+	uint32_t first_vp_left_time, second_vp_left_time;
+	uint32_t first_vp_safe_time, second_vp_safe_time;
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	done_bits_bak = done_bits;
+
+	done_bits &= ~BIT(vp->id);
+
+	/* no done bit, so no need to wait config done take effect */
+	if (done_bits == 0)
+		return 0;
+
+	/* have the other one different vp, wait for config done take effect */
+	if (hweight32(done_bits) == 1) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		adjusted_mode = &done_vp->crtc.state->adjusted_mode;
+		vcnt = vop2_read_vcnt(done_vp);
+
+		/* if close to the last 1/8 frame, wait to next frame */
+		if (vcnt > (adjusted_mode->crtc_vtotal * 7 >> 3)) {
+			vop2_wait_for_fs_by_done_bit_status(done_vp);
+			return 0;
+		}
+		return done_bits;
+	}
+
+	first_vp_id = ffs(done_bits) - 1;
+	first_done_vp = &vop2->vps[first_vp_id];
+	first_mode = &first_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	first_vp_safe_time = 1000000 / drm_mode_vrefresh(first_mode) >> 3;
+
+	done_bits &= ~BIT(first_vp_id);
+	second_vp_id = ffs(done_bits) - 1;
+	second_done_vp = &vop2->vps[second_vp_id];
+	second_mode = &second_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	second_vp_safe_time = 1000000 / drm_mode_vrefresh(second_mode) >> 3;
+
+	first_vp_vcnt = vop2_read_vcnt(first_done_vp);
+
+	second_vp_vcnt = vop2_read_vcnt(second_done_vp);
+
+	first_vp_left_vcnt = first_mode->crtc_vtotal - first_vp_vcnt;
+	second_vp_left_vcnt = second_mode->crtc_vtotal - second_vp_vcnt;
+	first_vp_left_time = vop2_line_to_time(first_mode, first_vp_left_vcnt);
+	second_vp_left_time = vop2_line_to_time(second_mode, second_vp_left_vcnt);
+
+	/* if the two vp both at safe section, no need to wait */
+	if (first_vp_left_time > first_vp_safe_time &&
+	    second_vp_left_time > second_vp_safe_time)
+		return done_bits_bak;
+
+	if (first_vp_left_time > second_vp_left_time)
+		wait_vp = first_done_vp;
+	else
+		wait_vp = second_done_vp;
+
+	vop2_wait_for_fs_by_done_bit_status(wait_vp);
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	if (done_bits) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		vop2_wait_for_fs_by_done_bit_status(done_vp);
+	}
+	return 0;
+}
+
+static inline void vop2_cfg_done(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits;
+	uint32_t val;
+	uint32_t old_layer_sel_val, cfg_layer_sel_val;
+	struct vop2_layer *layer = &vop2->layers[0];
+	uint32_t layer_sel_offset = layer->regs->layer_sel.offset;
+
+	/*
+	 * This is a workaround, the config done bits of VP0,
+	 * VP1, VP2 on RK3568 stands on the first three bits
+	 * on REG_CFG_DONE register without mask bit.
+	 * If two or three config done events happens one after
+	 * another in a very shot time, the flowing config done
+	 * write may override the previous config done bit before
+	 * it take effect:
+	 * 1: config done 0x8001 for VP0
+	 * 2: config done 0x8002 for VP1
+	 *
+	 * 0x8002 may override 0x8001 before it take effect.
+	 *
+	 * So we do a read | write here.
+	 *
+	 */
+	done_bits = vop2_pending_done_bits(vp);
+	old_layer_sel_val = vop2_readl(vop2, layer_sel_offset);
+	cfg_layer_sel_val = vop2->regsbak[layer_sel_offset >> 2];
+	/**
+	 * This is rather low probability for miss some done bit.
+	 */
+	val = RK3568_VOP2_GLB_CFG_DONE_EN | BIT(vp->id) | done_bits |
+		(vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7);
+	vop2_writel(vop2, 0, val);
+
+	/**
+	 * Make sure the layer sel is take effect when it's updated.
+	 */
+	if (old_layer_sel_val != cfg_layer_sel_val) {
+		vp->layer_sel_update = true;
+		vop2_wait_for_fs_by_done_bit_status(vp);
+		drm_dbg(vop2->drm, "vp%d need to wait fs as old layer_sel val[0x%x] != new val[0x%x]\n",
+			      vp->id, old_layer_sel_val, cfg_layer_sel_val);
+	}
+}
+
+static void vop2_win_disable(struct vop2_win *win)
+{
+	struct vop2 *vop2 = win->vop2;
+
+	vop2_win_write(win, &win->regs->enable, 0);
+	if (win->data->feature & WIN_FEATURE_CLUSTER_MAIN) {
+		struct vop2_win *sub_win;
+		int i = 0;
+
+		for (i = 0; i < vop2->registered_num_wins; i++) {
+			sub_win = &vop2->win[i];
+
+			if ((sub_win->data->phys_id == win->data->phys_id) &&
+			    (sub_win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+				vop2_win_write(sub_win, &sub_win->regs->enable, 0);
+		}
+
+		vop2_win_write(win, &win->regs->cluster->enable, 0);
+	}
+}
+
+static enum vop2_data_format vop2_convert_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_FMT_YUV420SP;
+	case DRM_FORMAT_NV16:
+		return VOP2_FMT_YUV422SP;
+	case DRM_FORMAT_NV24:
+		return VOP2_FMT_YUV444SP;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return VOP2_FMT_VYUY422;
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_UYVY:
+		return VOP2_FMT_YUYV422;
+	default:
+		DRM_ERROR("unsupported format[%08x]\n", format);
+		return -EINVAL;
+	}
+}
+
+static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_AFBC_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_AFBC_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_AFBC_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_AFBC_FMT_YUV420;
+	case DRM_FORMAT_NV16:
+		return VOP2_AFBC_FMT_YUV422;
+
+		/* either of the below should not be reachable */
+	default:
+		DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
+		return VOP2_AFBC_FMT_INVALID;
+	}
+
+	return VOP2_AFBC_FMT_INVALID;
+}
+
+static bool vop2_win_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_BGR565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_dither_up(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode)
+{
+	/*
+	 * FIXME:
+	 *
+	 * There is no media type for YUV444 output,
+	 * so when out_mode is AAAA or P888, assume output is YUV444 on
+	 * yuv format.
+	 *
+	 * From H/W testing, YUV444 mode need a rb swap.
+	 */
+	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
+	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
+	      bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
+	     (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
+	      output_mode == ROCKCHIP_OUT_MODE_P888)))
+		return true;
+	else
+		return false;
+}
+
+static bool vop2_output_yc_swap(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_output(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_alpha_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
+{
+	int i;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return false;
+
+	for (i = 0 ; i < plane->modifier_count; i++)
+		if (plane->modifiers[i] == modifier)
+			break;
+
+	return (i < plane->modifier_count) ? true : false;
+
+}
+
+static bool rockchip_vop2_mod_supported(struct drm_plane *plane, uint32_t format, u64 modifier)
+{
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	if (modifier == DRM_FORMAT_MOD_INVALID)
+		return false;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return true;
+
+	if (!rockchip_afbc(plane, modifier)) {
+		drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", modifier);
+
+		return false;
+	}
+
+	return vop2_convert_afbc_format(format) >= 0;
+}
+
+static inline bool vop2_cluster_window(struct vop2_win *win)
+{
+	return  (win->data->feature & (WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_CLUSTER_SUB));
+}
+
+static int vop2_afbc_half_block_enable(struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 0;
+	else
+		return 1;
+}
+
+static uint32_t vop2_afbc_transform_offset(struct drm_plane_state *pstate,
+					   bool afbc_half_block_en)
+{
+	struct drm_rect *src = &pstate->src;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t vir_width = (fb->pitches[0] << 3) / bpp;
+	uint32_t width = drm_rect_width(src) >> 16;
+	uint32_t height = drm_rect_height(src) >> 16;
+	uint32_t act_xoffset = src->x1 >> 16;
+	uint32_t act_yoffset = src->y1 >> 16;
+	uint32_t align16_crop = 0;
+	uint32_t align64_crop = 0;
+	uint32_t height_tmp = 0;
+	uint32_t transform_tmp = 0;
+	uint8_t transform_xoffset = 0;
+	uint8_t transform_yoffset = 0;
+	uint8_t top_crop = 0;
+	uint8_t top_crop_line_num = 0;
+	uint8_t bottom_crop_line_num = 0;
+
+	/* 16 pixel align */
+	if (height & 0xf)
+		align16_crop = 16 - (height & 0xf);
+
+	height_tmp = height + align16_crop;
+
+	/* 64 pixel align */
+	if (height_tmp & 0x3f)
+		align64_crop = 64 - (height_tmp & 0x3f);
+
+	top_crop_line_num = top_crop << 2;
+	if (top_crop == 0)
+		bottom_crop_line_num = align16_crop + align64_crop;
+	else if (top_crop == 1)
+		bottom_crop_line_num = align16_crop + align64_crop + 12;
+	else if (top_crop == 2)
+		bottom_crop_line_num = align16_crop + align64_crop + 8;
+
+	switch (pstate->rotation &
+		(DRM_MODE_REFLECT_X |
+		 DRM_MODE_REFLECT_Y |
+		 DRM_MODE_ROTATE_90 |
+		 DRM_MODE_ROTATE_270)) {
+	case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = (transform_tmp & 0xf);
+
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case 0:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	}
+
+	return (transform_xoffset & 0xf) | ((transform_yoffset & 0xf) << 16);
+}
+
+/*
+ * A Cluster window has 2048 x 16 line buffer, which can
+ * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
+ * for Cluster_lb_mode register:
+ * 0: half mode, for plane input width range 2048 ~ 4096
+ * 1: half mode, for cluster work at 2 * 2048 plane mode
+ * 2: half mode, for rotate_90/270 mode
+ *
+ */
+static int vop2_get_cluster_lb_mode(struct vop2_win *win, struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 2;
+	else if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * bli_sd_factor = (src - 1) / (dst - 1) << 12;
+ * avg_sd_factor:
+ * bli_su_factor:
+ * bic_su_factor:
+ * = (src - 1) / (dst - 1) << 16;
+ *
+ * gt2 enable: dst get one line from two line of the src
+ * gt4 enable: dst get one line from four line of the src.
+ *
+ */
+
+static uint16_t vop2_scale_factor(enum scale_mode mode,
+				  int32_t filter_mode,
+				  uint32_t src, uint32_t dst)
+{
+	uint32_t fac;
+	int i;
+
+	if (mode == SCALE_NONE)
+		return 0;
+
+	/*
+	 * A workaround to avoid zero div.
+	 */
+	if ((dst == 1) || (src == 1)) {
+		dst = dst + 1;
+		src = src + 1;
+	}
+
+	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
+		fac = ((src - 1) << 12) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 12 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	} else {
+		fac = ((src - 1) << 16) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 16 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	}
+
+	return fac;
+}
+
+static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
+			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+			     uint32_t dst_h, uint32_t pixel_format)
+{
+	const struct vop2_win_data *win_data = win->data;
+	const struct drm_format_info *info;
+	uint16_t cbcr_src_w;
+	uint16_t cbcr_src_h;
+	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
+	uint16_t cbcr_hor_scl_mode, cbcr_ver_scl_mode;
+	uint16_t hscl_filter_mode, vscl_filter_mode;
+	uint8_t gt2 = 0;
+	uint8_t gt4 = 0;
+	uint32_t val;
+
+	info = drm_format_info(pixel_format);
+
+	cbcr_src_w = src_w / info->hsub;
+	cbcr_src_h = src_h / info->vsub;
+
+	if (src_h >= (4 * dst_h)) {
+		gt4 = 1;
+		src_h >>= 2;
+	} else if (src_h >= (2 * dst_h)) {
+		gt2 = 1;
+		src_h >>= 1;
+	}
+
+	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
+	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
+
+	if (yrgb_hor_scl_mode == SCALE_UP)
+		hscl_filter_mode = win_data->hsu_filter_mode;
+	else
+		hscl_filter_mode = win_data->hsd_filter_mode;
+
+	if (yrgb_ver_scl_mode == SCALE_UP)
+		vscl_filter_mode = win_data->vsu_filter_mode;
+	else
+		vscl_filter_mode = win_data->vsd_filter_mode;
+
+	/*
+	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
+	 * at scale down mode
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
+			drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", win->data->name, dst_w);
+			dst_w += 1;
+		}
+	}
+
+	val = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode,
+				src_w, dst_w);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_x, val);
+	val = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode,
+				src_h, dst_h);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_y, val);
+
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt4, gt4);
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt2, gt2);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hscl_filter_mode, hscl_filter_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_vscl_filter_mode, vscl_filter_mode);
+
+	if (info->is_yuv) {
+		gt4 = gt2 = 0;
+
+		if (cbcr_src_h >= (4 * dst_h))
+			gt4 = 1;
+		else if (cbcr_src_h >= (2 * dst_h))
+			gt2 = 1;
+
+		if (gt4)
+			cbcr_src_h >>= 2;
+		else if (gt2)
+			cbcr_src_h >>= 1;
+
+		cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
+		cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
+
+		val = vop2_scale_factor(cbcr_hor_scl_mode, hscl_filter_mode,
+					cbcr_src_w, dst_w);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_x, val);
+		val = vop2_scale_factor(cbcr_ver_scl_mode, vscl_filter_mode,
+					cbcr_src_h, dst_h);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_y, val);
+
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt4, gt4);
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt2, gt2);
+		vop2_win_write(win, &win->regs->scl->cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_hscl_filter_mode, hscl_filter_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_vscl_filter_mode, vscl_filter_mode);
+	}
+}
+
+static int vop2_convert_csc_mode(int csc_mode)
+{
+	switch (csc_mode) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return CSC_BT601L;
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SMPTE240M:
+	case V4L2_COLORSPACE_DEFAULT:
+		return CSC_BT709L;
+	case V4L2_COLORSPACE_JPEG:
+		return CSC_BT601F;
+	case V4L2_COLORSPACE_BT2020:
+		return CSC_BT2020;
+	default:
+		return CSC_BT709L;
+	}
+}
+
+static bool vop2_is_allwin_disabled(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	unsigned long win_mask = vp->win_mask;
+	struct vop2_win *win;
+	int phys_id;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		if (vop2_win_read(win, &win->regs->enable) != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void vop2_disable_all_planes_for_crtc(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct vop2_win *win;
+	unsigned long win_mask = vp->win_mask;
+	int phys_id, ret;
+	bool active, need_wait_win_disabled = false;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		need_wait_win_disabled |= vop2_win_read(win, &win->regs->enable);
+		vop2_win_disable(win);
+	}
+
+	if (need_wait_win_disabled) {
+		vop2_cfg_done(vp);
+		ret = readx_poll_timeout_atomic(vop2_is_allwin_disabled, vp,
+						active, active, 0, 500 * 1000);
+		if (ret)
+			drm_err(vop2->drm, "wait win close timeout\n");
+	}
+}
+
+/*
+ * colorspace path:
+ *      Input        Win csc                     Output
+ * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
+ *    RGB        --> R2Y(601)             __/
+ *
+ * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
+ *    RGB        --> bypass               __/
+ *
+ * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
+ *
+ * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
+ *
+ * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
+ *
+ * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
+ */
+
+static void vop2_setup_csc_mode(struct vop2_video_port *vp,
+				struct vop2_win *win,
+				struct drm_plane_state *pstate)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
+	int is_input_yuv = is_yuv_support(pstate->fb->format->format);
+	int is_output_yuv = is_yuv_output(vcstate->bus_format);
+	int input_csc = V4L2_COLORSPACE_DEFAULT;
+	int output_csc = vcstate->color_space;
+	bool r2y_en, y2r_en;
+	int csc_mode;
+
+	if (is_input_yuv && !is_output_yuv) {
+		y2r_en = 1;
+		r2y_en = 0;
+		csc_mode = vop2_convert_csc_mode(input_csc);
+	} else if (!is_input_yuv && is_output_yuv) {
+		y2r_en = 0;
+		r2y_en = 1;
+		csc_mode = vop2_convert_csc_mode(output_csc);
+	} else {
+		y2r_en = 0;
+		r2y_en = 0;
+		csc_mode = 0;
+	}
+
+	vop2_win_write(win, &win->regs->y2r_en, y2r_en);
+	vop2_win_write(win, &win->regs->r2y_en, r2y_en);
+	vop2_win_write(win, &win->regs->csc_mode, csc_mode);
+}
+
+static void vop2_axi_irqs_enable(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr;
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t i;
+
+	for (i = 0; i < vop2_data->nr_axi_intr; i++) {
+		intr = &vop2_data->axi_intr[i];
+		vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+		vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+	}
+}
+
+static uint32_t vop2_read_and_clear_axi_irqs(struct vop2 *vop2, int index)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr = &vop2_data->axi_intr[index];
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t val;
+
+	val = vop2_get_intr_type(vop2, intr, &intr->status, irqs);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+
+	return val;
+}
+
+static void vop2_dsp_hold_valid_irq_enable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, DSP_HOLD_VALID_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_dsp_hold_valid_irq_disable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_debug_irq_enable(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	uint32_t irqs = POST_BUF_EMPTY_INTR;
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+}
+
+static bool vop2_dsp_lut_is_enabled(struct vop2_video_port *vp)
+{
+	return vop2_read(vp->vop2, &vp->regs->dsp_lut_en);
+}
+
+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ *     the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
+ *      to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG -------------------------------+
+ * FRAME_SYNC ----+                         |
+ *                |                         |
+ *                v                         v
+ *                | Vsync | Vbp |  Vactive  | Vfp |
+ *                        ^     ^           ^     ^
+ *                        |     |           |     |
+ *                        |     |           |     |
+ * dsp_vs_end ------------+     |           |     |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --------------+           |     |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end ----------------------------+     |   VOP_DSP_VACT_ST_END
+ * dsp_total -------------------------------------+   VOP_DSP_VTOTAL_VS_END
+ */
+
+static void vop2_crtc_load_lut(struct drm_crtc *crtc, struct drm_color_lut *lut)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int dle = 0, i = 0;
+	uint8_t vp_enable_gamma_nr = 0;
+
+	for (i = 0; i < vop2->data->nr_vps; i++) {
+		struct vop2_video_port *vp = &vop2->vps[i];
+
+		if (i == vp->id)
+			continue;
+
+		if (vp->gamma_lut_active)
+			vp_enable_gamma_nr++;
+	}
+
+	if (vp_enable_gamma_nr >= vop2->data->nr_gammas) {
+		drm_info(vop2->drm, "only support %d gamma\n", vop2->data->nr_gammas);
+		return;
+	}
+
+	spin_lock(&vop2->reg_lock);
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 0);
+	vop2_cfg_done(vp);
+	spin_unlock(&vop2->reg_lock);
+
+	readx_poll_timeout(vop2_dsp_lut_is_enabled, vp, dle, !dle, 5, 33333);
+
+	for (i = 0; i < vp->gamma_lut_len; i++) {
+		uint32_t r, g, b;
+		uint32_t ll = vp->gamma_lut_len;
+
+		r = lut[i].red * (ll - 1) / 0xffff;
+		g = lut[i].green * (ll - 1) / 0xffff;
+		b = lut[i].blue * (ll - 1) / 0xffff;
+		writel(b * ll * ll + g * ll + r, vop2->lut_regs + (i << 2));
+	}
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 1);
+	vop2_write(vop2, &vop2->data->ctrl->gamma_port_sel, vp->id);
+	vop2_cfg_done(vp);
+	vp->gamma_lut_active = true;
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = clk_prepare_enable(vop2->hclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable hclk - %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vop2->aclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable aclk - %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	clk_disable_unprepare(vop2->hclk);
+
+	return ret;
+}
+
+/*
+ * VOP2 architecture
+ *
+ +----------+   +-------------+                                                        +-----------+
+ |  Cluster |   | Sel 1 from 6|                                                        | 1 from 3  |
+ |  window0 |   |    Layer0   |                                                        |    RGB    |
+ +----------+   +-------------+              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 layers|    |             |
+ |  Cluster |   | Sel 1 from 6|              |   Overlay0    +--->| Video Port0 |      +-----------+
+ |  window1 |   |    Layer1   |              |               |    |             |      | 1 from 3  |
+ +----------+   +-------------+              +---------------+    +-------------+      |   LVDS    |
+ +----------+   +-------------+                                                        +-----------+
+ |  Esmart  |   | Sel 1 from 6|
+ |  window0 |   |   Layer2    |              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 Layers|    |             | +--> | 1 from 3  |
+ +----------+   +-------------+   -------->  |   Overlay1    +--->| Video Port1 |      |   MIPI    |
+ |  Esmart  |   | Sel 1 from 6|   -------->  |               |    |             |      +-----------+
+ |  Window1 |   |   Layer3    |              +---------------+    +-------------+
+ +----------+   +-------------+                                                        +-----------+
+ +----------+   +-------------+                                                        | 1 from 3  |
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |   HDMI    |
+ |  Window0 |   |    Layer4   |              |N from 6 Layers|    |             |      +-----------+
+ +----------+   +-------------+              |   Overlay2    +--->| Video Port2 |
+ +----------+   +-------------+              |               |    |             |      +-----------+
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |  1 from 3 |
+ |  Window1 |   |    Layer5   |                                                        |    eDP    |
+ +----------+   +-------------+                                                        +-----------+
+ *
+ */
+
+static void vop2_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(vop2->dev);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
+		return;
+	}
+
+	ret = vop2_core_clks_prepare_enable(vop2);
+	if (ret) {
+		pm_runtime_put_sync(vop2->dev);
+		return;
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 0);
+
+	if (vop2->data->soc_id == 3566)
+		vop2_write(vop2, &vop2->data->ctrl->otp_en, 1);
+
+	memcpy(vop2->regsbak, vop2->regs, vop2->len);
+
+	vop2_write(vop2, &vop2->data->ctrl->cfg_done_en, 1);
+	/*
+	 * Disable auto gating, this is a workaround to
+	 * avoid display image shift when a window enabled.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->auto_gating_en, 0);
+	/*
+	 * Register OVERLAY_LAYER_SEL and OVERLAY_PORT_SEL should take effect immediately,
+	 * than windows configuration(CLUSTER/ESMART/SMART) can take effect according the
+	 * video port mux configuration as we wished.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 1);
+	/*
+	 * Let SYS_DSP_INFACE_EN/SYS_DSP_INFACE_CTRL/SYS_DSP_INFACE_POL take effect
+	 * immediately.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->if_ctrl_cfg_done_imd, 1);
+
+	vop2_axi_irqs_enable(vop2);
+}
+
+static void vop2_disable(struct vop2 *vop2)
+{
+	/*
+	 * vop2 standby complete, so iommu detach is safe.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 1);
+
+	pm_runtime_put_sync(vop2->dev);
+
+	clk_disable_unprepare(vop2->aclk);
+	clk_disable_unprepare(vop2->hclk);
+}
+
+static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
+				     struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int ret;
+
+	WARN_ON(vp->event);
+	vop2_lock(vop2);
+
+	drm_crtc_vblank_off(crtc);
+	vop2_disable_all_planes_for_crtc(vp);
+
+	/*
+	 * Vop standby will take effect at end of current frame,
+	 * if dsp hold valid irq happen, it means standby complete.
+	 *
+	 * we must wait standby complete when we want to disable aclk,
+	 * if not, memory bus maybe dead.
+	 */
+	reinit_completion(&vp->dsp_hold_completion);
+	vop2_dsp_hold_valid_irq_enable(crtc);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->standby, 1);
+
+	spin_unlock(&vop2->reg_lock);
+
+	ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50));
+	if (!ret)
+		drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id);
+
+	vop2_dsp_hold_valid_irq_disable(crtc);
+
+	clk_disable_unprepare(vp->dclk);
+
+	vop2->enable_count--;
+
+	if (!vop2->enable_count)
+		vop2_disable(vop2);
+
+	vop2_unlock(vop2);
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *astate)
+{
+	struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct drm_framebuffer *fb = pstate->fb;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct drm_crtc_state *cstate;
+	struct vop2_video_port *vp;
+	struct vop2 *vop2;
+	const struct vop2_data *vop2_data;
+	struct drm_rect *dest = &pstate->dst;
+	struct drm_rect *src = &pstate->src;
+	int min_scale = win->regs->scl ? FRAC_16_16(1, 8) : DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = win->regs->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING;
+	int format;
+	int ret;
+
+	if (!crtc)
+		return 0;
+
+	vp = to_vop2_video_port(crtc);
+	vop2 = vp->vop2;
+	vop2_data = vop2->data;
+
+	cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc);
+	if (WARN_ON(!cstate))
+		return -EINVAL;
+
+	ret = drm_atomic_helper_check_plane_state(pstate, cstate,
+						  min_scale, max_scale,
+						  true, true);
+	if (ret)
+		return ret;
+
+	if (!pstate->visible)
+		return 0;
+
+	format = vop2_convert_format(fb->format->format);
+	if (format < 0)
+		return format;
+
+	if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
+	    drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
+		drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n",
+			  drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
+			  drm_rect_width(dest), drm_rect_height(dest));
+		pstate->visible = false;
+		return 0;
+	}
+
+	if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
+	    drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
+		drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n",
+			  drm_rect_width(src) >> 16,
+			  drm_rect_height(src) >> 16,
+			  vop2_data->max_input.width,
+			  vop2_data->max_input.height);
+		return -EINVAL;
+	}
+
+	/*
+	 * Src.x1 can be odd when do clip, but yuv plane start point
+	 * need align with 2 pixel.
+	 */
+	if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) {
+		drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	drm_dbg(vop2->drm, "%s disable\n", win->data->name);
+
+	if (!old_pstate->crtc)
+		return;
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_win_disable(win);
+	vop2_win_write(win, &win->regs->yuv_clip, 0);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * The color key is 10 bit, so all format should
+ * convert to 10 bit here.
+ */
+static void vop2_plane_setup_color_key(struct drm_plane *plane, uint32_t color_key)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_framebuffer *fb = pstate->fb;
+	struct vop2_win *win = to_vop2_win(plane);
+	uint32_t color_key_en = 0;
+	uint32_t r = 0;
+	uint32_t g = 0;
+	uint32_t b = 0;
+
+	if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->color_key_en, 0);
+		return;
+	}
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		r = (color_key & 0xf800) >> 11;
+		g = (color_key & 0x7e0) >> 5;
+		b = (color_key & 0x1f);
+		r <<= 5;
+		g <<= 4;
+		b <<= 5;
+		color_key_en = 1;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		r = (color_key & 0xff0000) >> 16;
+		g = (color_key & 0xff00) >> 8;
+		b = (color_key & 0xff);
+		r <<= 2;
+		g <<= 2;
+		b <<= 2;
+		color_key_en = 1;
+		break;
+	}
+
+	vop2_win_write(win, &win->regs->color_key_en, color_key_en);
+	vop2_win_write(win, &win->regs->color_key, (r << 20) | (g << 10) | b);
+}
+
+static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = win->vop2;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t actual_w, actual_h, dsp_w, dsp_h;
+	uint32_t act_info, dsp_info;
+	uint32_t format;
+	uint32_t afbc_format;
+	uint32_t rb_swap;
+	uint32_t uv_swap;
+	struct drm_rect *src = &pstate->src;
+	struct drm_rect *dest = &pstate->dst;
+	uint32_t afbc_tile_num;
+	uint32_t afbc_half_block_en;
+	uint32_t transform_offset;
+	bool dither_up;
+	bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X;
+	bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y;
+	bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270;
+	bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
+	struct rockchip_gem_object *rk_obj;
+	unsigned long offset;
+	bool afbc_en;
+	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
+
+	/*
+	 * can't update plane when vop2 is disabled.
+	 */
+	if (WARN_ON(!crtc))
+		return;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	if (!pstate->visible) {
+		vop2_plane_atomic_disable(plane, state);
+		return;
+	}
+
+	/*
+	 * This means this window is moved from another vp
+	 * so the VOP2_PORT_SEL register is changed and
+	 * take effect by vop2_wait_for_port_mux_done
+	 * in this commit. so we can continue configure
+	 * the window and report vsync
+	 */
+	if (win->old_vp_mask != win->vp_mask) {
+		win->old_vp_mask = win->vp_mask;
+		vp->skip_vsync = false;
+	}
+
+	afbc_en = rockchip_afbc(plane, fb->modifier);
+
+	offset = (src->x1 >> 16) * fb->format->cpp[0];
+
+	/*
+	 * AFBC HDR_PTR must set to the zero offset of the framebuffer.
+	 */
+	if (afbc_en)
+		offset = 0;
+	else if (pstate->rotation & DRM_MODE_REFLECT_Y)
+		offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
+	else
+		offset += (src->y1 >> 16) * fb->pitches[0];
+
+	rk_obj = to_rockchip_obj(fb->obj[0]);
+
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	if (fb->format->is_yuv) {
+		int hsub = fb->format->hsub;
+		int vsub = fb->format->vsub;
+
+		offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
+		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
+
+		if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en)
+			offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2)  / vsub;
+
+		rk_obj = to_rockchip_obj(fb->obj[0]);
+		uv_mst = rk_obj->dma_addr + offset + fb->offsets[1];
+	}
+
+	actual_w = drm_rect_width(src) >> 16;
+	actual_h = drm_rect_height(src) >> 16;
+	dsp_w = drm_rect_width(dest);
+
+	if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
+			  vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
+		dsp_w = adjusted_mode->hdisplay - dest->x1;
+		if (dsp_w < 4)
+			dsp_w = 4;
+		actual_w = dsp_w * actual_w / drm_rect_width(dest);
+	}
+
+	dsp_h = drm_rect_height(dest);
+
+	if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
+			  vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
+		dsp_h = adjusted_mode->vdisplay - dest->y1;
+		if (dsp_h < 4)
+			dsp_h = 4;
+		actual_h = dsp_h * actual_h / drm_rect_height(dest);
+	}
+
+	/*
+	 * This is workaround solution for IC design:
+	 * esmart can't support scale down when actual_w % 16 == 1.
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
+			drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->data->name, actual_w);
+			actual_w -= 1;
+		}
+	}
+
+	if (afbc_en && actual_w % 4) {
+		drm_err(vop2->drm, "vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
+			  vp->id, win->data->name, actual_w);
+		actual_w = ALIGN_DOWN(actual_w, 4);
+	}
+
+	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
+	dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
+
+	format = vop2_convert_format(fb->format->format);
+
+	spin_lock(&vop2->reg_lock);
+	drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
+		      vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
+		      dest->x1, dest->y1,
+		      &fb->format->format,
+		      afbc_en ? "AFBC" : "", &yrgb_mst);
+
+	if (afbc_en) {
+		uint32_t stride;
+
+		/* the afbc superblock is 16 x 16 */
+		afbc_format = vop2_convert_afbc_format(fb->format->format);
+
+		/* Enable color transform for YTR */
+		if (fb->modifier & AFBC_FORMAT_MOD_YTR)
+			afbc_format |= (1 << 4);
+
+		afbc_tile_num = ALIGN(actual_w, 16) >> 4;
+
+		/*
+		 * AFBC pic_vir_width is count by pixel, this is different
+		 * with WIN_VIR_STRIDE.
+		 */
+		stride = (fb->pitches[0] << 3) / bpp;
+		if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270))
+			drm_err(vop2->drm, "vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n",
+				  vp->id, win->data->name, stride, pstate->rotation);
+
+		rb_swap = vop2_afbc_rb_swap(fb->format->format);
+		uv_swap = vop2_afbc_uv_swap(fb->format->format);
+		/*
+		 * This is a workaround for crazy IC design, Cluster
+		 * and Esmart/Smart use different format configuration map:
+		 * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
+		 *
+		 * This is one thing we can make the convert simple:
+		 * AFBCD decode all the YUV data to YUV444. So we just
+		 * set all the yuv 10 bit to YUV444_10.
+		 */
+		if (fb->format->is_yuv && (bpp == 10))
+			format = VOP2_CLUSTER_YUV444_10;
+
+		afbc_half_block_en = vop2_afbc_half_block_enable(pstate);
+		transform_offset = vop2_afbc_transform_offset(pstate, afbc_half_block_en);
+		if (vop2_cluster_window(win))
+			vop2_win_write(win, &win->regs->cluster->afbc_enable, 1);
+		vop2_win_write(win, &win->regs->afbc->format, afbc_format);
+		vop2_win_write(win, &win->regs->afbc->rb_swap, rb_swap);
+		vop2_win_write(win, &win->regs->afbc->uv_swap, uv_swap);
+		vop2_win_write(win, &win->regs->afbc->auto_gating_en, 0);
+		vop2_win_write(win, &win->regs->afbc->block_split_en, 0);
+		vop2_win_write(win, &win->regs->afbc->half_block_en, afbc_half_block_en);
+		vop2_win_write(win, &win->regs->afbc->hdr_ptr, yrgb_mst);
+		vop2_win_write(win, &win->regs->afbc->pic_size, act_info);
+		vop2_win_write(win, &win->regs->afbc->transform_offset, transform_offset);
+		vop2_win_write(win, &win->regs->afbc->pic_offset, ((src->x1 >> 16) | src->y1));
+		vop2_win_write(win, &win->regs->afbc->dsp_offset, (dest->x1 | (dest->y1 << 16)));
+		vop2_win_write(win, &win->regs->afbc->pic_vir_width, stride);
+		vop2_win_write(win, &win->regs->afbc->tile_num, afbc_tile_num);
+		vop2_win_write(win, &win->regs->afbc->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->afbc->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->afbc->rotate_270, rotate_270);
+		vop2_win_write(win, &win->regs->afbc->rotate_90, rotate_90);
+	} else {
+		if (win->regs->afbc)
+			vop2_win_write(win, &win->regs->afbc->enable, 0);
+		vop2_win_write(win, &win->regs->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
+	}
+
+	if (rotate_90 || rotate_270) {
+		act_info = swahw32(act_info);
+		actual_w = drm_rect_height(src) >> 16;
+		actual_h = drm_rect_width(src) >> 16;
+	}
+
+	vop2_win_write(win, &win->regs->format, format);
+	vop2_win_write(win, &win->regs->yrgb_mst, yrgb_mst);
+
+	rb_swap = vop2_win_rb_swap(fb->format->format);
+	uv_swap = vop2_win_uv_swap(fb->format->format);
+	vop2_win_write(win, &win->regs->rb_swap, rb_swap);
+	vop2_win_write(win, &win->regs->uv_swap, uv_swap);
+
+	if (fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->uv_vir, DIV_ROUND_UP(fb->pitches[1], 4));
+		vop2_win_write(win, &win->regs->uv_mst, uv_mst);
+	}
+
+	vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format);
+	vop2_plane_setup_color_key(plane, 0);
+	vop2_win_write(win, &win->regs->act_info, act_info);
+	vop2_win_write(win, &win->regs->dsp_info, dsp_info);
+	vop2_win_write(win, &win->regs->dsp_st, dest->y1 << 16 | (dest->x1 & 0xffff));
+
+	vop2_setup_csc_mode(vp, win, pstate);
+
+	dither_up = vop2_win_dither_up(fb->format->format);
+	vop2_win_write(win, &win->regs->dither_up, dither_up);
+
+	vop2_win_write(win, &win->regs->enable, 1);
+
+	if (vop2_cluster_window(win)) {
+		int lb_mode = vop2_get_cluster_lb_mode(win, pstate);
+
+		vop2_win_write(win, &win->regs->cluster->lb_mode, lb_mode);
+		vop2_win_write(win, &win->regs->cluster->enable, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120 ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		vop2_win_write(win, &win->regs->yuv_clip, 1);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
+	.atomic_check = vop2_plane_atomic_check,
+	.atomic_update = vop2_plane_atomic_update,
+	.atomic_disable = vop2_plane_atomic_disable,
+};
+
+static const struct drm_plane_funcs vop2_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.format_mod_supported = rockchip_vop2_mod_supported,
+};
+
+static int vop2_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return -EPERM;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, FS_FIELD_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	return 0;
+}
+
+static void vop2_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adj_mode)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		adj_mode->crtc_clock *= 2;
+
+	adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
+							   adj_mode->crtc_clock * 1000), 1000);
+
+	return true;
+}
+
+static void vop2_dither_setup(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+
+	switch (vcstate->bus_format) {
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB565);
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB666);
+		break;
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 1);
+		break;
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	case MEDIA_BUS_FMT_SRGB888_3X8:
+	case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	default:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	}
+
+	vop2_write(vop2, &vp->regs->pre_dither_down_en,
+		       vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA ? 0 : 1);
+	vop2_write(vop2, &vp->regs->dither_down_sel, DITHER_DOWN_ALLEGRO);
+}
+
+static void vop2_post_config(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate =
+			to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint32_t left_margin = 100, right_margin = 100, top_margin = 100, bottom_margin = 100;
+	uint16_t hsize = hdisplay * (left_margin + right_margin) / 200;
+	uint16_t vsize = vdisplay * (top_margin + bottom_margin) / 200;
+	uint16_t hact_end, vact_end;
+	uint32_t val;
+
+	vsize = rounddown(vsize, 2);
+	hsize = rounddown(hsize, 2);
+	hact_st += hdisplay * (100 - left_margin) / 200;
+	hact_end = hact_st + hsize;
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hpost_st_end, val);
+	vact_st += vdisplay * (100 - top_margin) / 200;
+	vact_end = vact_st + vsize;
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vpost_st_end, val);
+	val = scl_cal_scale2(vdisplay, vsize) << 16;
+	val |= scl_cal_scale2(hdisplay, hsize);
+	vop2_write(vop2, &vp->regs->post_scl_factor, val);
+
+#define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
+#define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
+	vop2_write(vop2, &vp->regs->post_scl_ctrl,
+		       POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
+		       POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vsize;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vpost_st_end_f1, val);
+	}
+	vop2_write(vop2, &vp->regs->post_dsp_out_r2y,
+		       is_yuv_output(vcstate->bus_format));
+}
+
+/*
+ * if adjusted mode update, return true, else return false
+ */
+static bool vop2_crtc_mode_update(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	uint32_t htotal_sync = htotal << 16 | hsync_len;
+	uint32_t hactive_st_end = hact_st << 16 | hact_end;
+	uint32_t vtotal_sync = vtotal << 16 | vsync_len;
+	uint32_t vactive_st_end = vact_st << 16 | vact_end;
+	uint32_t crtc_clock = mode->crtc_clock * 100;
+
+	if (htotal_sync != vop2_read(vop2, &vp->regs->htotal_pw) ||
+	    hactive_st_end != vop2_read(vop2, &vp->regs->hact_st_end) ||
+	    vtotal_sync != vop2_read(vop2, &vp->regs->vtotal_pw) ||
+	    vactive_st_end != vop2_read(vop2, &vp->regs->vact_st_end) ||
+	    crtc_clock != clk_get_rate(vp->dclk))
+		return true;
+
+	return false;
+}
+
+static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	uint8_t out_mode;
+	bool dclk_inv, yc_swap;
+	int act_end;
+	uint32_t val;
+	int ret;
+
+	vop2_lock(vop2);
+
+	drm_info(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d, output 0x%08x %s %s\n",
+		     hdisplay, vdisplay, interlaced ? "i" : "p",
+		     drm_mode_vrefresh(mode), vcstate->output_type, vp->id,
+		     vcstate->output_if,
+		     vcstate->output_if & VOP_OUTPUT_IF_MIPI0 ? "MIPI0" : "",
+		     vcstate->output_if & VOP_OUTPUT_IF_HDMI0 ? "HDMI0" : ""
+		);
+
+	ret = clk_prepare_enable(vp->dclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n",
+			      vp->id, ret);
+		return;
+	}
+
+	if (!vop2->enable_count)
+		vop2_enable(vop2);
+
+	vop2->enable_count++;
+
+	vop2_debug_irq_enable(vp);
+
+	if (vop2_crtc_mode_update(vp))
+		vop2_disable_all_planes_for_crtc(vp);
+
+	dclk_inv = (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
+	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
+	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_RGB) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_dclk_inv, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt1120_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT656) {
+		vop2_write(vop2, &vop2->data->ctrl->bt656_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt656_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt656_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS0) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS1) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
+	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_mode, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
+		vop2_write(vop2, &vp->regs->mipi_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vp->regs->mipi_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
+		vop2_write(vop2, &vop2->data->ctrl->edp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) {
+		vop2_write(vop2, &vop2->data->ctrl->edp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP0) {
+		vop2_write(vop2, &vop2->data->ctrl->dp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP1) {
+		vop2_write(vop2, &vop2->data->ctrl->dp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
+	     !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		out_mode = ROCKCHIP_OUT_MODE_P888;
+	else
+		out_mode = vcstate->output_mode;
+
+	vop2_write(vop2, &vp->regs->out_mode, out_mode);
+
+	if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
+		vop2_write(vop2, &vp->regs->dsp_data_swap, DSP_RB_SWAP);
+	else
+		vop2_write(vop2, &vp->regs->dsp_data_swap, 0);
+
+	vop2_dither_setup(crtc);
+
+	vop2_write(vop2, &vp->regs->htotal_pw, (htotal << 16) | hsync_len);
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hact_st_end, val);
+
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vact_st_end, val);
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vdisplay;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vact_st_end_f1, val);
+
+		val = vtotal << 16 | (vtotal + vsync_len);
+		vop2_write(vop2, &vp->regs->vs_st_end_f1, val);
+		vop2_write(vop2, &vp->regs->dsp_interlace, 1);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 1);
+		vop2_write(vop2, &vp->regs->p2i_en, 1);
+		vtotal += vtotal + 1;
+		act_end = vact_end_f1;
+	} else {
+		vop2_write(vop2, &vp->regs->dsp_interlace, 0);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 0);
+		vop2_write(vop2, &vp->regs->p2i_en, 0);
+		act_end = vact_end;
+	}
+
+	vop2_write(vop2, &intr->line_flag_num[0], act_end);
+	vop2_write(vop2, &intr->line_flag_num[1],
+		     act_end - us_to_vertical_line(mode, 0));
+
+	vop2_write(vop2, &vp->regs->vtotal_pw, vtotal << 16 | vsync_len);
+
+	vop2_write(vop2, &vp->regs->core_dclk_div, !!(mode->flags & DRM_MODE_FLAG_DBLCLK));
+	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
+		vop2_write(vop2, &vp->regs->dclk_div2, 1);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 1);
+	} else {
+		vop2_write(vop2, &vp->regs->dclk_div2, 0);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 0);
+	}
+
+	clk_set_rate(vp->dclk, mode->crtc_clock * 1000);
+
+	vop2_post_config(crtc);
+
+	vop2_cfg_done(vp);
+
+	/*
+	 * when clear standby bits, it will take effect immediately,
+	 * This means the vp will start scan out immediately with
+	 * the timing it been configured before.
+	 * So we must make sure release standby after the display
+	 * timing is correctly configured.
+	 * This is important when switch resolution, such as
+	 * 4K-->720P:
+	 * if we release standby before 720P timing is configured,
+	 * the VP will start scan out immediately with 4K timing,
+	 * when we switch dclk to 74.25MHZ, VP timing is still 4K,
+	 * so VP scan out with 4K timing at 74.25MHZ dclk, this is
+	 * very slow, than this will trigger vblank timeout.
+	 *
+	 */
+	vop2_write(vop2, &vp->regs->standby, 0);
+
+	drm_crtc_vblank_on(crtc);
+
+	vop2_unlock(vop2);
+}
+
+static int vop2_zpos_cmp(const void *a, const void *b)
+{
+	struct vop2_zpos *pa = (struct vop2_zpos *)a;
+	struct vop2_zpos *pb = (struct vop2_zpos *)b;
+
+	if (pa->zpos != pb->zpos)
+		return pa->zpos - pb->zpos;
+	else
+		return pa->plane->base.id - pb->plane->base.id;
+}
+
+static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+
+		if (abs(main_win->base.state->zpos - win->base.state->zpos) != 1) {
+			drm_err(vop2->drm, "vp%d Cluster%d win0[zpos:%d] must next to win1[zpos:%d]\n",
+				  vp->id, main_win->data->phys_id,
+				  main_win->base.state->zpos, win->base.state->zpos);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static bool is_opaque(uint16_t alpha)
+{
+	return (alpha >> 8) == 0xff;
+}
+
+static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
+			     struct vop2_alpha *alpha)
+{
+	int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
+	int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
+	int src_color_mode = alpha_config->src_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+	int dst_color_mode = alpha_config->dst_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+
+	alpha->src_color_ctrl.val = 0;
+	alpha->dst_color_ctrl.val = 0;
+	alpha->src_alpha_ctrl.val = 0;
+	alpha->dst_alpha_ctrl.val = 0;
+
+	if (!alpha_config->src_pixel_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+
+	alpha->src_color_ctrl.bits.alpha_en = 1;
+
+	if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	} else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
+	} else {
+		alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	}
+	alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
+	alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+
+	alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
+	alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
+	alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+
+	alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
+	alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
+
+	alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+	alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
+	alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+}
+
+static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, uint8_t port_id)
+{
+	struct vop2_video_port *vp;
+	int used_layer = 0;
+	int i;
+
+	for (i = 0; i < port_id; i++) {
+		vp = &vop2->vps[i];
+		used_layer += hweight32(vp->win_mask);
+	}
+
+	return used_layer;
+}
+
+/*
+ * src: top layer
+ * dst: bottom layer.
+ * Cluster mixer default use win1 as top layer
+ */
+static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_cluster *cluster)
+{
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->cluster0_src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->cluster0_dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->cluster0_src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->cluster0_dst_alpha_ctrl.offset;
+	uint32_t offset = (cluster->main->data->phys_id * 0x10);
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *main_win = cluster->main;
+	struct vop2_win *sub_win = cluster->sub;
+	struct drm_plane *main_plane;
+	struct drm_plane_state *top_win_pstate;
+	struct drm_plane_state *bottom_win_pstate;
+	bool src_pixel_alpha_en = false;
+	uint16_t src_glb_alpha_val, dst_glb_alpha_val;
+	bool premulti_en = false;
+	bool swap = false;
+
+	if (!sub_win) {
+		/* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
+		top_win_pstate = NULL;
+		bottom_win_pstate = main_win->base.state;
+		src_glb_alpha_val = 0;
+		dst_glb_alpha_val = main_win->base.state->alpha;
+	} else {
+		if (main_win->base.state->zpos > sub_win->base.state->zpos) {
+			swap = 1;
+			top_win_pstate = main_plane->state;
+			bottom_win_pstate = sub_win->base.state;
+			src_glb_alpha_val = main_win->base.state->alpha;
+			dst_glb_alpha_val = sub_win->base.state->alpha;
+		} else {
+			swap = 0;
+			top_win_pstate = sub_win->base.state;
+			bottom_win_pstate = main_plane->state;
+			src_glb_alpha_val = sub_win->base.state->alpha;
+			dst_glb_alpha_val = main_win->base.state->alpha;
+		}
+
+		if (!top_win_pstate->fb)
+			return;
+
+		if (top_win_pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = true;
+		else
+			premulti_en = false;
+
+		src_pixel_alpha_en = is_alpha_support(top_win_pstate->fb->format->format);
+	}
+
+	if (!bottom_win_pstate->fb)
+		return;
+
+	alpha_config.src_premulti_en = premulti_en;
+	alpha_config.dst_premulti_en = false;
+	alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	alpha_config.src_glb_alpha_value = src_glb_alpha_val;
+	alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	alpha.src_color_ctrl.bits.src_dst_swap = swap;
+	vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+	vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+	vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+	vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+}
+
+static void vop2_setup_alpha(struct vop2_video_port *vp,
+			     const struct vop2_zpos *vop2_zpos, int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->dst_alpha_ctrl.offset;
+	const struct vop2_zpos *zpos;
+	struct drm_framebuffer *fb;
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *win;
+	struct drm_plane *plane;
+	int pixel_alpha_en;
+	int premulti_en;
+	int mixer_id;
+	uint32_t offset;
+	int i;
+	bool bottom_layer_alpha_en = false;
+	uint32_t dst_global_alpha = 0xffff;
+
+	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (plane->state->zpos == 0 && !is_opaque(plane->state->alpha) &&
+		    !vop2_cluster_window(win)) {
+			/*
+			 * If bottom layer have global alpha effect [except cluster layer,
+			 * because cluster have deal with bottom layer global alpha value
+			 * at cluster mix], bottom layer mix need deal with global alpha.
+			 */
+			bottom_layer_alpha_en = true;
+			dst_global_alpha = plane->state->alpha;
+			break;
+		}
+	}
+
+	mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	for (i = 1; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		fb = plane->state->fb;
+		if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = 1;
+		else
+			premulti_en = 0;
+		pixel_alpha_en = is_alpha_support(fb->format->format);
+
+		alpha_config.src_premulti_en = premulti_en;
+		if (bottom_layer_alpha_en && i == 1) {/* Cd = Cs + (1 - As) * Cd * Agd */
+			alpha_config.dst_premulti_en = false;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = dst_global_alpha;
+		} else if (vop2_cluster_window(win)) {/* Mix output data only have pixel alpha */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = true;
+			alpha_config.src_glb_alpha_value = 0xffff;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		} else {/* Cd = Cs + (1 - As) * Cd */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		}
+		vop2_parse_alpha(&alpha_config, &alpha);
+
+		offset = (mixer_id + i - 1) * 0x10;
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+
+		if (i == 1) {
+			if (bottom_layer_alpha_en) {
+				/* Transfer pixel alpha to hdr mix */
+				alpha_config.src_premulti_en = premulti_en;
+				alpha_config.dst_premulti_en = true;
+				alpha_config.src_pixel_alpha_en = true;
+				alpha_config.src_glb_alpha_value = 0xffff;
+				alpha_config.dst_glb_alpha_value = 0xffff;
+				vop2_parse_alpha(&alpha_config, &alpha);
+
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl,
+					       alpha.src_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_color_ctrl,
+					       alpha.dst_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_src_alpha_ctrl,
+					       alpha.src_alpha_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_alpha_ctrl,
+					       alpha.dst_alpha_ctrl.val);
+			} else {
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl, 0);
+			}
+		}
+	}
+
+	/* Transfer pixel alpha value to next mix */
+	alpha_config.src_premulti_en = true;
+	alpha_config.dst_premulti_en = true;
+	alpha_config.src_pixel_alpha_en = false;
+	alpha_config.src_glb_alpha_value = 0xffff;
+	alpha_config.dst_glb_alpha_value = 0xffff;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	for (; i < hweight32(vp->win_mask); i++) {
+		offset = (mixer_id + i - 1) * 0x10;
+
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+	}
+}
+
+static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp,
+					  const struct vop2_zpos *vop2_zpos,
+					  int nr_layers)
+{
+	struct vop2_video_port *vpt;
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_zpos *zpos;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint16_t port_mux_cfg = 0;
+	uint8_t port_mux;
+	uint8_t used_layers = 0;
+	int i, nlayer;
+
+	for (i = 0; i < vop2_data->nr_vps - 1; i++) {
+		vpt = &vop2->vps[i];
+		used_layers += hweight32(vpt->win_mask);
+
+		if (used_layers == 0)
+			port_mux = 8;
+		else
+			port_mux = used_layers - 1;
+
+		port_mux_cfg |= port_mux << (vpt->id * 4);
+
+		if (port_mux > vop2_data->nr_mixers)
+			vpt->bg_ovl_dly = 0;
+		else
+			vpt->bg_ovl_dly = (vop2_data->nr_mixers - port_mux) << 1;
+	}
+
+	if (vop2_data->nr_vps >= 1)
+		port_mux_cfg |= 7 << (4 * (vop2_data->nr_vps - 1));
+
+	nlayer = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		int j;
+
+		vpt = &vop2->vps[i];
+
+		for (j = 0; j < vpt->nr_layers; j++) {
+			layer = &vop2->layers[nlayer];
+			zpos = &vpt->zpos[j];
+			win = zpos->win;
+
+			vop2_write(vop2, &vop2->data->ctrl->win_vp_id[win->data->phys_id], vpt->id);
+			vop2_write(vop2, &layer->regs->layer_sel, win->data->layer_sel_id);
+			nlayer++;
+		}
+	}
+
+	for (; nlayer < vop2_data->nr_layers; nlayer++) {
+		layer = &vop2->layers[nlayer];
+
+		vop2_write(vop2, &layer->regs->layer_sel, 5);
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->ovl_cfg_done_port, vp->id);
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 0);
+
+	spin_lock(&vop2->reg_lock);
+	if (vop2->port_mux_cfg != port_mux_cfg) {
+		vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg, port_mux_cfg);
+		vp->skip_vsync = true;
+		vop2_cfg_done(vp);
+		vop2->port_mux_cfg = port_mux_cfg;
+		vop2_wait_for_port_mux_done(vop2);
+	}
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * HDR window is fixed(not move in the overlay path with port_mux change)
+ * and is the slowest window. And the bg is the fastest. So other windows
+ * and bg need to add delay number to keep align with the slowest window.
+ * The delay number list in the trm is a relative value for port_mux set at
+ * last level.
+ */
+static void vop2_setup_dly_for_vp(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	uint16_t hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+	uint16_t hdisplay = adjusted_mode->crtc_hdisplay;
+	uint32_t bg_dly = vp_data->pre_scan_max_dly[0];
+	uint32_t pre_scan_dly;
+
+	bg_dly = vp_data->pre_scan_max_dly[3];
+	bg_dly -= vp->bg_ovl_dly;
+
+	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
+	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
+	vop2_write(vop2, &vp->regs->bg_dly, bg_dly);
+	vop2_write(vop2, &vp->regs->pre_scan_htiming, pre_scan_dly);
+}
+
+static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
+				      int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_zpos *zpos;
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	uint32_t dly;
+	int i = 0;
+
+	for (i = 0; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
+
+		if (vop2_cluster_window(win))
+			dly |= dly << 8;
+
+		vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
+	}
+
+}
+static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	struct vop2_zpos *vop2_zpos = vp->zpos;
+	struct vop2_cluster cluster;
+	uint8_t nr_layers = 0;
+
+	/* Process cluster sub windows overlay. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		win->two_win_mode = false;
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+		cluster.main = main_win;
+		cluster.sub = win;
+		win->two_win_mode = true;
+		main_win->two_win_mode = true;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+
+	vp->win_mask = 0;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		/*
+		 * Sub win of a cluster will be handled by pre overlay module automatically
+		 * win in multi area share the same overlay zorder with it's parent.
+		 */
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+		vp->win_mask |=  BIT(win->data->phys_id);
+		win->vp_mask = BIT(vp->id);
+		vop2_zpos[nr_layers].win = win;
+		vop2_zpos[nr_layers].zpos = plane->state->zpos;
+		vop2_zpos[nr_layers].plane = plane;
+		nr_layers++;
+		drm_dbg(vop2->drm, "%s active zpos:%d for vp%d\n",
+			     win->data->name, plane->state->zpos, vp->id);
+	}
+
+	vp->nr_layers = nr_layers;
+
+	drm_dbg(vop2->drm, "vp%d: %d windows, active layers %d\n",
+		      vp->id, hweight32(vp->win_mask), nr_layers);
+	if (nr_layers) {
+		sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
+
+		vop2_setup_layer_mixer_for_vp(vp, vop2_zpos, nr_layers);
+		vop2_setup_alpha(vp, vop2_zpos, nr_layers);
+		vop2_setup_dly_for_vp(vp);
+		vop2_setup_dly_for_window(vp, vop2_zpos, nr_layers);
+	}
+
+	/* The pre alpha overlay of Cluster still need process in one win mode. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_MAIN))
+			continue;
+		if (win->two_win_mode)
+			continue;
+		cluster.main = win;
+		cluster.sub = NULL;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+}
+
+static void vop2_cfg_update(struct drm_crtc *crtc,
+			    struct drm_crtc_state *old_crtc_state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t val;
+	bool yuv_overlay = is_yuv_output(vcstate->bus_format);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->overlay_mode, yuv_overlay);
+
+	if (yuv_overlay)
+		val = 0x20010200;
+	else
+		val = 0;
+
+	vop2_write(vop2, &vp->regs->dsp_background, val);
+
+	vop2_post_config(crtc);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *old_cstate = drm_atomic_get_old_crtc_state(state, crtc);
+	struct drm_atomic_state *old_state = old_cstate->state;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_plane_state *old_pstate;
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	unsigned long flags;
+	int i;
+
+	vop2_cfg_update(crtc, old_cstate);
+
+	if (crtc->state->color_mgmt_changed || crtc->state->active_changed) {
+		if (crtc->state->gamma_lut)
+			vop2_crtc_load_lut(crtc, crtc->state->gamma_lut->data);
+	} else {
+		vop2_write(vop2, &vp->regs->cubic_lut_update_en, 0);
+	}
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	vop2_cfg_done(vp);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	/*
+	 * There is a (rather unlikely) possibility that a vblank interrupt
+	 * fired before we set the cfg_done bit. To avoid spuriously
+	 * signalling flip completion we need to wait for it to finish.
+	 */
+	vop2_wait_for_irq_handler(crtc);
+
+	/*
+	 * move here is to make sure current fs call function is complete,
+	 * so when layer_sel_update is true, we can skip current vblank correctly.
+	 */
+	vp->layer_sel_update = false;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		WARN_ON(vp->event);
+
+		vp->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+
+	for_each_old_plane_in_state(old_state, plane, old_pstate, i) {
+		if (!old_pstate->fb)
+			continue;
+
+		if (old_pstate->fb == plane->state->fb)
+			continue;
+
+		drm_framebuffer_get(old_pstate->fb);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		drm_flip_work_queue(&vp->fb_unref_work, old_pstate->fb);
+		set_bit(VOP_PENDING_FB_UNREF, &vp->pending);
+	}
+}
+
+static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
+	.mode_fixup = vop2_crtc_mode_fixup,
+	.atomic_check = vop2_crtc_atomic_check,
+	.atomic_begin = vop2_crtc_atomic_begin,
+	.atomic_flush = vop2_crtc_atomic_flush,
+	.atomic_enable = vop2_crtc_atomic_enable,
+	.atomic_disable = vop2_crtc_atomic_disable,
+};
+
+static void vop2_crtc_reset(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+
+	if (crtc->state) {
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+		kfree(vcstate);
+	}
+
+	vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return;
+	crtc->state = &vcstate->base;
+	crtc->state->crtc = crtc;
+}
+
+static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate, *old_vcstate;
+
+	old_vcstate = to_rockchip_crtc_state(crtc->state);
+	vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
+
+	return &vcstate->base;
+}
+
+static void vop2_crtc_destroy_state(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
+
+	__drm_atomic_helper_crtc_destroy_state(&vcstate->base);
+	kfree(vcstate);
+}
+
+static const struct drm_crtc_funcs vop2_crtc_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.destroy = drm_crtc_cleanup,
+	.reset = vop2_crtc_reset,
+	.atomic_duplicate_state = vop2_crtc_duplicate_state,
+	.atomic_destroy_state = vop2_crtc_destroy_state,
+	.enable_vblank = vop2_crtc_enable_vblank,
+	.disable_vblank = vop2_crtc_disable_vblank,
+};
+
+static void vop2_fb_unref_worker(struct drm_flip_work *work, void *val)
+{
+	struct vop2_video_port *vp = container_of(work, struct vop2_video_port, fb_unref_work);
+	struct drm_framebuffer *fb = val;
+
+	drm_crtc_vblank_put(&vp->crtc);
+	drm_framebuffer_put(fb);
+}
+
+static void vop2_handle_vblank(struct vop2 *vop2, struct drm_crtc *crtc)
+{
+	struct drm_device *drm = vop2->drm;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	if (vp->event) {
+		drm_crtc_send_vblank_event(crtc, vp->event);
+		drm_crtc_vblank_put(crtc);
+		vp->event = NULL;
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+
+	if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vp->pending))
+		drm_flip_work_commit(&vp->fb_unref_work, system_unbound_wq);
+}
+
+static uint32_t vop2_read_and_clear_active_vp_irqs(struct vop2 *vop2, int vp_id)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	const struct vop_intr *intr;
+	int val;
+
+	vp_data = &vop2_data->vp[vp_id];
+	intr = vp_data->intr;
+	val = vop2_get_intr_type(vop2, intr, &intr->status, VOP2_INTR_MASK);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+	return val;
+}
+
+static irqreturn_t vop2_isr(int irq, void *data)
+{
+	struct vop2 *vop2 = data;
+	struct drm_crtc *crtc;
+	struct vop2_video_port *vp;
+	const struct vop2_data *vop2_data = vop2->data;
+	size_t vp_max = min_t(size_t, vop2_data->nr_vps, ROCKCHIP_MAX_CRTC);
+	size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM);
+	uint32_t vp_irqs[ROCKCHIP_MAX_CRTC];
+	uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM];
+	uint32_t active_irqs;
+	unsigned long flags;
+	int ret = IRQ_NONE;
+	int i;
+
+	/*
+	 * The irq is shared with the iommu. If the runtime-pm state of the
+	 * vop2-device is disabled the irq has to be targeted at the iommu.
+	 */
+	if (!pm_runtime_get_if_in_use(vop2->dev))
+		return IRQ_NONE;
+
+	/*
+	 * interrupt register has interrupt status, enable and clear bits, we
+	 * must hold irq_lock to avoid a race with enable/disable_vblank().
+	 */
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	for (i = 0; i < vp_max; i++)
+		vp_irqs[i] = vop2_read_and_clear_active_vp_irqs(vop2, i);
+	for (i = 0; i < axi_max; i++)
+		axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i);
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	for (i = 0; i < vp_max; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		active_irqs = vp_irqs[i];
+		if (active_irqs & DSP_HOLD_VALID_INTR) {
+			complete(&vp->dsp_hold_completion);
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & FS_FIELD_INTR) {
+			if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) {
+				drm_crtc_handle_vblank(crtc);
+				vop2_handle_vblank(vop2, crtc);
+			}
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & POST_BUF_EMPTY_INTR) {
+			drm_err_ratelimited(vop2->drm,
+					    "POST_BUF_EMPTY irq err at vp%d\n",
+					    vp->id);
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	for (i = 0; i < axi_max; i++) {
+		active_irqs = axi_irqs[i];
+
+		if (active_irqs & BUS_ERROR_INTR) {
+			drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n");
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	pm_runtime_put(vop2->dev);
+
+	return ret;
+}
+
+static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs)
+{
+	const struct vop2_win_data *win_data = win->data;
+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) |
+				  BIT(DRM_MODE_BLEND_COVERAGE);
+	int ret;
+
+	ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs,
+				       &vop2_plane_funcs, win_data->formats, win_data->nformats,
+				       win_data->format_modifiers, win_data->type, win_data->name);
+	if (ret) {
+		drm_err(vop2->drm, "failed to initialize plane %d\n", ret);
+		return ret;
+	}
+
+	drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs);
+
+	if (win->data->supported_rotations)
+		drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
+						   DRM_MODE_ROTATE_0 | win->data->supported_rotations);
+	drm_plane_create_alpha_property(&win->base);
+	drm_plane_create_blend_mode_property(&win->base, blend_caps);
+	drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop2->registered_num_wins - 1);
+
+	return 0;
+}
+
+static int vop2_gamma_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	struct vop2_video_port *vp;
+	struct drm_crtc *crtc;
+	int i = 0;
+	uint32_t lut_len = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		if (!crtc->dev)
+			continue;
+		vp_data = &vop2_data->vp[vp->id];
+		lut_len = vp_data->gamma_lut_len;
+		vp->gamma_lut_len = vp_data->gamma_lut_len;
+
+		drm_mode_crtc_set_gamma_size(crtc, lut_len);
+		drm_crtc_enable_color_mgmt(crtc, 0, false, lut_len);
+	}
+
+	return 0;
+}
+
+static int vop2_create_crtc(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	struct drm_device *drm = vop2->drm;
+	struct device *dev = vop2->dev;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct device_node *port;
+	struct vop2_win *win = NULL;
+	struct vop2_video_port *vp;
+	const struct vop2_video_port_data *vp_data;
+	uint32_t possible_crtcs;
+	int i, nvp = 0;
+	int ret;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+
+		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
+			if (nvp < vop2_data->nr_vps) {
+				vp = &vop2->vps[nvp];
+
+				possible_crtcs = BIT(vop2_data->vp[i].id);
+				vp->primary_plane = win;
+
+				nvp++;
+			} else {
+				/* change the unused primary window to overlay window */
+				win->type = DRM_PLANE_TYPE_OVERLAY;
+			}
+		}
+
+		if (win->type == DRM_PLANE_TYPE_OVERLAY)
+			possible_crtcs = (1 << vop2_data->nr_vps) - 1;
+		ret = vop2_plane_init(vop2, win, possible_crtcs);
+
+		if (ret) {
+			drm_err(vop2->drm, "failed to init plane %s: %d\n", win->data->name, ret);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		char dclk_name[9];
+
+		vp_data = &vop2_data->vp[i];
+		vp = &vop2->vps[i];
+		vp->vop2 = vop2;
+		vp->id = vp_data->id;
+		vp->regs = vp_data->regs;
+
+		vp->zpos = devm_kzalloc(vop2->dev, vop2->data->win_size * sizeof(*vp->zpos), GFP_KERNEL);
+		if (!vp->zpos)
+			return -ENOMEM;
+
+		snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
+		vp->dclk = devm_clk_get(vop2->dev, dclk_name);
+		if (IS_ERR(vp->dclk)) {
+			drm_err(vop2->drm, "failed to get %s\n", dclk_name);
+			return PTR_ERR(vp->dclk);
+		}
+
+		crtc = &vp->crtc;
+
+		port = of_graph_get_port_by_id(dev->of_node, i);
+		if (!port) {
+			drm_err(vop2->drm, "no port node found for video_port%d\n", i);
+			return -ENOENT;
+		}
+		crtc->port = port;
+
+		plane = &vp->primary_plane->base;
+
+		ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &vop2_crtc_funcs,
+						"video_port%d", vp->id);
+		if (ret) {
+			drm_err(vop2->drm, "crtc init for video_port%d failed\n", i);
+			return ret;
+		}
+
+		drm_crtc_helper_add(crtc, &vop2_crtc_helper_funcs);
+
+		drm_flip_work_init(&vp->fb_unref_work, "fb_unref", vop2_fb_unref_worker);
+
+		init_completion(&vp->dsp_hold_completion);
+		init_completion(&vp->line_flag_completion);
+	}
+
+	return 0;
+}
+
+static void vop2_destroy_crtc(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	of_node_put(crtc->port);
+
+	/*
+	 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
+	 * references the CRTC.
+	 */
+	drm_crtc_cleanup(crtc);
+	drm_flip_work_cleanup(&vp->fb_unref_work);
+}
+
+static int vop2_win_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_layer_data *layer_data;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint8_t plane_id = 0;
+	unsigned int i;
+
+	for (i = 0; i < vop2_data->win_size; i++) {
+		const struct vop2_win_data *win_data = &vop2_data->win[i];
+
+		win = &vop2->win[i];
+		win->data = win_data;
+		win->type = win_data->type;
+		win->regs = win_data->regs;
+		win->offset = win_data->base;
+		win->win_id = i;
+		win->plane_id = plane_id++;
+		win->zpos = i;
+		win->vop2 = vop2;
+	}
+
+	vop2->registered_num_wins = vop2_data->win_size;
+
+	for (i = 0; i < vop2_data->nr_layers; i++) {
+		layer = &vop2->layers[i];
+		layer_data = &vop2_data->layer[i];
+		layer->id = layer_data->id;
+		layer->regs = layer_data->regs;
+	}
+
+	return 0;
+}
+
+static int vop2_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct vop2_data *vop2_data;
+	struct drm_device *drm = data;
+	struct vop2 *vop2;
+	struct resource *res;
+	size_t alloc_size;
+	int ret;
+
+	vop2_data = of_device_get_match_data(dev);
+	if (!vop2_data)
+		return -ENODEV;
+
+	/* Allocate vop2 struct and its vop2_win array */
+	alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size;
+	vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
+	if (!vop2)
+		return -ENOMEM;
+
+	vop2->dev = dev;
+	vop2->data = vop2_data;
+	vop2->drm = drm;
+
+	dev_set_drvdata(dev, vop2);
+
+	ret = vop2_win_init(vop2);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	if (!res) {
+		drm_err(vop2->drm, "failed to get vop2 register byname\n");
+		return -EINVAL;
+	}
+	vop2->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vop2->regs))
+		return PTR_ERR(vop2->regs);
+	vop2->len = resource_size(res);
+
+	vop2->regsbak = devm_kzalloc(dev, vop2->len, GFP_KERNEL);
+	if (!vop2->regsbak)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut");
+	if (res) {
+		vop2->lut_regs = devm_ioremap_resource(dev, res);
+		if (IS_ERR(vop2->lut_regs))
+			return PTR_ERR(vop2->lut_regs);
+	}
+
+	vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+
+	vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop");
+	if (IS_ERR(vop2->hclk)) {
+		drm_err(vop2->drm, "failed to get hclk source\n");
+		return PTR_ERR(vop2->hclk);
+	}
+
+	vop2->aclk = devm_clk_get(vop2->dev, "aclk_vop");
+	if (IS_ERR(vop2->aclk)) {
+		drm_err(vop2->drm, "failed to get aclk source\n");
+		return PTR_ERR(vop2->aclk);
+	}
+
+	vop2->irq = platform_get_irq(pdev, 0);
+	if (vop2->irq < 0) {
+		drm_err(vop2->drm, "cannot find irq for vop2\n");
+		return vop2->irq;
+	}
+
+	spin_lock_init(&vop2->reg_lock);
+	spin_lock_init(&vop2->irq_lock);
+	mutex_init(&vop2->vop2_lock);
+
+	ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
+	if (ret)
+		return ret;
+
+	ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev);
+	if (ret) {
+		drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret);
+		return ret;
+	}
+
+	ret = vop2_create_crtc(vop2);
+	if (ret)
+		return ret;
+
+	ret = vop2_gamma_init(vop2);
+	if (ret)
+		return ret;
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static void vop2_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct vop2 *vop2 = dev_get_drvdata(dev);
+	struct drm_device *drm = vop2->drm;
+	struct list_head *plane_list = &drm->mode_config.plane_list;
+	struct list_head *crtc_list = &drm->mode_config.crtc_list;
+	struct drm_crtc *crtc, *tmpc;
+	struct drm_plane *plane, *tmpp;
+
+	rockchip_drm_dma_detach_device(vop2->drm, vop2->dev);
+
+	pm_runtime_disable(dev);
+
+	list_for_each_entry_safe(plane, tmpp, plane_list, head)
+		drm_plane_cleanup(plane);
+
+	list_for_each_entry_safe(crtc, tmpc, crtc_list, head)
+		vop2_destroy_crtc(crtc);
+}
+
+const struct component_ops vop2_component_ops = {
+	.bind = vop2_bind,
+	.unbind = vop2_unbind,
+};
+EXPORT_SYMBOL_GPL(vop2_component_ops);
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
new file mode 100644
index 0000000000000..669c7b6fd9eab
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -0,0 +1,916 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Rockchip Electronics Co.Ltd
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
+
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define _VOP_REG(off, _mask, _shift, _write_mask) \
+	{ \
+		.offset = off, \
+		.mask = _mask, \
+		.shift = _shift, \
+		.write_mask = _write_mask, \
+	}
+
+#define VOP_REG(off, _mask, _shift) \
+		_VOP_REG(off, _mask, _shift, false)
+
+#define VOP_REG_MASK(off, _mask, s) \
+		_VOP_REG(off, _mask, s, true)
+
+static const uint32_t formats_win_full_10bit[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+};
+
+static const uint32_t formats_win_full_10bit_yuyv[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_VYUY,
+};
+
+static const uint32_t formats_win_lite[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static const u32 formats_wb[] = {
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_NV12,
+};
+
+static const uint64_t format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const uint64_t format_modifiers_afbc[] = {
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const int rk3568_vop_axi_intrs[] = {
+	0,
+	BUS_ERROR_INTR,
+	0,
+	WB_UV_FIFO_FULL_INTR,
+	WB_YRGB_FIFO_FULL_INTR,
+	WB_COMPLETE_INTR,
+
+};
+
+static const struct vop_intr rk3568_vop_axi_intr[] = {
+	{
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS0_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS0_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS0_INT_CLR, 0xfe, 0),
+	}, {
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS1_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS1_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS1_INT_CLR, 0xfe, 0),
+	},
+};
+
+static const int rk3568_vop_intrs[] = {
+	FS_INTR,
+	FS_NEW_INTR,
+	LINE_FLAG_INTR,
+	LINE_FLAG1_INTR,
+	POST_BUF_EMPTY_INTR,
+	FS_FIELD_INTR,
+	DSP_HOLD_VALID_INTR,
+};
+
+static const struct vop_intr rk3568_vp0_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP0_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP0_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP0_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp1_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP1_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP1_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP1_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp2_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP2_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP2_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP2_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop2_wb_regs rk3568_vop_wb_regs = {
+	.enable = VOP_REG(RK3568_WB_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_WB_CTRL, 0x7, 1),
+	.dither_en = VOP_REG(RK3568_WB_CTRL, 0x1, 4),
+	.r2y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 5),
+	.scale_x_en = VOP_REG(RK3568_WB_CTRL, 0x1, 7),
+	.scale_y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 8),
+	.axi_yrgb_id = VOP_REG(RK3568_WB_CTRL, 0xff, 19),
+	.axi_uv_id = VOP_REG(RK3568_WB_CTRL, 0x1f, 27),
+	.scale_x_factor = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3fff, 16),
+	.yrgb_mst = VOP_REG(RK3568_WB_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_WB_CBR_MST, 0xffffffff, 0),
+	.vp_id = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 8),
+	.fifo_throd = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3ff, 0),
+};
+
+static const struct vop2_wb_data rk3568_vop_wb_data = {
+	.formats = formats_wb,
+	.nformats = ARRAY_SIZE(formats_wb),
+	.max_output = { 1920, 1080 },
+	.regs = &rk3568_vop_wb_regs,
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp0_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0),
+	.dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 0),
+	.out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP0_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP0_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP0_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP0_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP0_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP0_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 21),
+	.dsp_lut_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 28),
+	.hdr10_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 4),
+	.hdr_lut_update_en = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 0),
+	.hdr_lut_mode = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 1),
+	.hdr_lut_mst = VOP_REG(RK3568_HDR_LUT_MST, 0xffffffff, 0),
+	.sdr2hdr_eotf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 0),
+	.sdr2hdr_r2r_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 1),
+	.sdr2hdr_r2r_mode = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 2),
+	.sdr2hdr_oetf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 3),
+	.sdr2hdr_bypass_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 8),
+	.sdr2hdr_auto_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 9),
+	.sdr2hdr_path_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 5),
+	.hdr2sdr_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 0),
+	.hdr2sdr_bypass_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 8),
+	.hdr2sdr_auto_gating_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 9),
+	.hdr2sdr_src_min = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 0),
+	.hdr2sdr_src_max = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 16),
+	.hdr2sdr_normfaceetf = VOP_REG(RK3568_HDR2SDR_NORMFACEETF, 0x7ff, 0),
+	.hdr2sdr_dst_min = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 0),
+	.hdr2sdr_dst_max = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 16),
+	.hdr2sdr_normfacgamma = VOP_REG(RK3568_HDR2SDR_NORMFACCGAMMA, 0xffff, 0),
+	.hdr2sdr_eetf_oetf_y0_offset = RK3568_HDR_EETF_OETF_Y0,
+	.hdr2sdr_sat_y0_offset = RK3568_HDR_SAT_Y0,
+	.sdr2hdr_eotf_oetf_y0_offset = RK3568_HDR_EOTF_OETF_Y0,
+	.sdr2hdr_oetf_dx_pow1_offset = RK3568_HDR_OETF_DX_POW1,
+	.sdr2hdr_oetf_xn1_offset = RK3568_HDR_OETF_XN1,
+	.hdr_src_color_ctrl = VOP_REG(RK3568_HDR0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_dst_color_ctrl = VOP_REG(RK3568_HDR0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_src_alpha_ctrl = VOP_REG(RK3568_HDR0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.hdr_dst_alpha_ctrl = VOP_REG(RK3568_HDR0_DST_ALPHA_CTRL, 0xffffffff, 0),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP0_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP0_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP0_BCSH_COLOR_BAR, 0x1, 31),
+
+	.cubic_lut_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 0),
+	.cubic_lut_update_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 2),
+	.cubic_lut_mst = VOP_REG(RK3568_VP0_3D_LUT_MST, 0xffffffff, 0),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp1_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 1),
+	.dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 4),
+	.out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP1_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP1_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP1_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP1_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP1_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP1_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP1_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP1_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP1_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP1_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp2_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 2),
+	.dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 8),
+	.out_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP2_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP2_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP2_POST_SCL_CTRL, 0x3, 0),
+	.htotal_pw = VOP_REG(RK3568_VP2_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(RK3568_VP2_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP2_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP2_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP2_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP2_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP2_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
+	{
+		.id = 0,
+		.feature = VOP_FEATURE_OUTPUT_10BIT,
+		.gamma_lut_len = 1024,
+		.cubic_lut_len = 729, /* 9x9x9 */
+		.max_output = { 4096, 2304 },
+		.pre_scan_max_dly = { 69, 53, 53, 42 },
+		.intr = &rk3568_vp0_intr,
+		.regs = &rk3568_vop_vp0_regs,
+	}, {
+		.id = 1,
+		.gamma_lut_len = 1024,
+		.max_output = { 2048, 1536 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp1_intr,
+		.regs = &rk3568_vop_vp1_regs,
+	}, {
+		.id = 2,
+		.gamma_lut_len = 1024,
+		.max_output = { 1920, 1080 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp2_intr,
+		.regs = &rk3568_vop_vp2_regs,
+	},
+};
+
+const struct vop2_layer_regs rk3568_vop_layer0_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 0)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer1_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 4)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer2_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 8)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer3_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 12)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer4_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 16)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer5_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 20)
+};
+
+static const struct vop2_layer_data rk3568_vop_layers[] = {
+	{
+		.id = 0,
+		.regs = &rk3568_vop_layer0_regs,
+	}, {
+		.id = 1,
+		.regs = &rk3568_vop_layer1_regs,
+	}, {
+		.id = 2,
+		.regs = &rk3568_vop_layer2_regs,
+	}, {
+		.id = 3,
+		.regs = &rk3568_vop_layer3_regs,
+	}, {
+		.id = 4,
+		.regs = &rk3568_vop_layer4_regs,
+	}, {
+		.id = 5,
+		.regs = &rk3568_vop_layer5_regs,
+	},
+};
+
+static const struct vop2_cluster_regs rk3568_vop_cluster0 =  {
+	.afbc_enable = VOP_REG(RK3568_CLUSTER_CTRL, 0x1, 1),
+	.enable = VOP_REG(RK3568_CLUSTER_CTRL, 1, 0),
+	.lb_mode = VOP_REG(RK3568_CLUSTER_CTRL, 0xf, 4),
+};
+
+static const struct vop_afbc rk3568_cluster0_afbc = {
+	.format = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1f, 2),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 9),
+	.uv_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 10),
+	.auto_gating_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 0x1, 4),
+	.half_block_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 7),
+	.block_split_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 8),
+	.hdr_ptr = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0xffffffff, 0),
+	.pic_size = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0xffffffff, 0),
+	.pic_vir_width = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 0),
+	.tile_num = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 16),
+	.pic_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0xffffffff, 0),
+	.dsp_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0xffffffff, 0),
+	.transform_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0xffffffff, 0),
+	.rotate_90 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 0),
+	.rotate_270 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 1),
+	.xmirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 2),
+	.ymirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 3),
+};
+
+static const struct vop2_scl_regs rk3568_cluster0_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 16),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 14),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 12),
+	.bic_coe_sel = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 2),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 28),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 29),
+};
+
+static const struct vop2_scl_regs rk3568_esmart_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area1_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area2_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area3_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 11),
+};
+
+static const struct vop2_win_regs rk3568_cluster0_win_data = {
+	.scl = &rk3568_cluster0_win_scl,
+	.afbc = &rk3568_cluster0_afbc,
+	.cluster = &rk3568_vop_cluster0,
+	.enable = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 0),
+	.format = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1f, 1),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 14),
+	.dither_up = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 18),
+	.act_info = VOP_REG(RK3568_CLUSTER_WIN_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_CLUSTER_WIN_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_CLUSTER_WIN_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_CLUSTER_WIN_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_CLUSTER_WIN_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 19),
+	.yrgb_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 8),
+	.r2y_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 9),
+	.csc_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x3, 10),
+};
+
+static const struct vop2_win_regs rk3568_esmart_win_data = {
+	.scl = &rk3568_esmart_win_scl,
+	.enable = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1f, 1),
+	.dither_up = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 12),
+	.rb_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 14),
+	.uv_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 16),
+	.act_info = VOP_REG(RK3568_SMART_REGION0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_SMART_REGION0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_SMART_REGION0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_SMART_REGION0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_SMART_REGION0_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 17),
+	.yrgb_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 0),
+	.r2y_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 1),
+	.csc_mode = VOP_REG(RK3568_SMART_CTRL0, 0x3, 2),
+	.ymirror = VOP_REG(RK3568_SMART_CTRL1, 0x1, 31),
+	.color_key = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x3fffffff, 0),
+	.color_key_en = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x1, 31),
+};
+
+/*
+ * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
+ * Every cluster can work as 4K win or split into two win.
+ * All win in cluster support AFBCD.
+ *
+ * Every esmart win and smart win support 4 Multi-region.
+ *
+ * Scale filter mode:
+ *
+ * * Cluster:  bicubic for horizontal scale up, others use bilinear
+ * * ESmart:
+ *    * nearest-neighbor/bilinear/bicubic for scale up
+ *    * nearest-neighbor/bilinear/average for scale down
+ *
+ *
+ * @TODO describe the wind like cpu-map dt nodes;
+ */
+static const struct vop2_win_data rk3568_vop_win_data[] = {
+	{
+		.name = "Smart0-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART0,
+		.base = 0x1c00,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.layer_sel_id = 3,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Smart1-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART1,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.base = 0x1e00,
+		.layer_sel_id = 7,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart1-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1a00,
+		.layer_sel_id = 6,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart0-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1800,
+		.layer_sel_id = 2,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Cluster0-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1000,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 0,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN,
+	}, {
+		.name = "Cluster0-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1080,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB,
+	}, {
+		.name = "Cluster1-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.base = 0x1200,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 1,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_MIRROR,
+	}, {
+		.name = "Cluster1-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.base = 0x1280,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB | WIN_FEATURE_MIRROR,
+	},
+};
+
+static const struct vop_grf_ctrl rk3568_grf_ctrl = {
+	.grf_bt656_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 1),
+	.grf_bt1120_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 2),
+	.grf_dclk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 3),
+};
+
+static const struct vop2_ctrl rk3568_vop_ctrl = {
+	.cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15),
+	.wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14),
+	.auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31),
+	.ovl_cfg_done_port = VOP_REG(RK3568_OVL_CTRL, 0x3, 30),
+	.ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28),
+	.ovl_port_mux_cfg = VOP_REG(RK3568_OVL_PORT_SEL, 0xffff, 0),
+	.if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28),
+	.version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16),
+	.lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0),
+	.cluster0_src_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_dst_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_src_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.cluster0_dst_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.src_color_ctrl = VOP_REG(RK3568_MIX0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.dst_color_ctrl = VOP_REG(RK3568_MIX0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.src_alpha_ctrl = VOP_REG(RK3568_MIX0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.dst_alpha_ctrl = VOP_REG(RK3568_MIX0_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.rgb_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 0),
+	.hdmi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 1),
+	.edp0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 3),
+	.mipi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 4),
+	.mipi1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 20),
+	.lvds0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 5),
+	.lvds1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 24),
+	.bt1120_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 6),
+	.bt656_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 7),
+	.rgb_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 8),
+	.hdmi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 10),
+	.edp0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 14),
+	.mipi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 16),
+	.mipi1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 21),
+	.lvds0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 18),
+	.lvds1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 25),
+	.lvds_dual_en = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 0),
+	.lvds_dual_mode = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 1),
+	.lvds_dual_channel_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 2),
+	.bt656_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 5),
+	.bt1120_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 9),
+	.gamma_port_sel = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 0),
+	.lvds_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 0),
+	.lvds_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 3),
+	.hdmi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 4),
+	.hdmi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 7),
+	.edp_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x3, 12),
+	.edp_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 15),
+	.mipi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 16),
+	.mipi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 19),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 16),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 18),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 24),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 26),
+	.win_vp_id[ROCKCHIP_VOP2_SMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 28),
+	.win_vp_id[ROCKCHIP_VOP2_SMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 30),
+	.win_dly[0] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 0),
+	.win_dly[1] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 16),
+	.win_dly[2] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 0),
+	.win_dly[3] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 8),
+	.win_dly[4] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 16),
+	.win_dly[5] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 24),
+	.otp_en = VOP_REG(RK3568_OTP_WIN_EN, 0x1, 0),
+};
+
+static const struct vop2_data rk3568_vop = {
+	.nr_vps = 3,
+	.nr_mixers = 5,
+	.nr_gammas = 1,
+	.max_input = { 4096, 2304 },
+	.max_output = { 4096, 2304 },
+	.ctrl = &rk3568_vop_ctrl,
+	.grf_ctrl = &rk3568_grf_ctrl,
+	.axi_intr = rk3568_vop_axi_intr,
+	.nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr),
+	.vp = rk3568_vop_video_ports,
+	.wb = &rk3568_vop_wb_data,
+	.layer = rk3568_vop_layers,
+	.nr_layers = ARRAY_SIZE(rk3568_vop_layers),
+	.win = rk3568_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
+	.soc_id = 3568,
+};
+
+static const struct of_device_id vop2_dt_match[] = {
+	{
+		.compatible = "rockchip,rk3568-vop",
+		.data = &rk3568_vop
+	}, {
+	},
+};
+MODULE_DEVICE_TABLE(of, vop2_dt_match);
+
+static int vop2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	return component_add(dev, &vop2_component_ops);
+}
+
+static int vop2_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vop2_component_ops);
+
+	return 0;
+}
+
+struct platform_driver vop2_platform_driver = {
+	.probe = vop2_probe,
+	.remove = vop2_remove,
+	.driver = {
+		.name = "rockchip-vop2",
+		.of_match_table = of_match_ptr(vop2_dt_match),
+	},
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, Sascha Hauer

The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
It replaces the VOP unit found in the older Rockchip SoCs.

This driver has been derived from the downstream Rockchip Kernel and
heavily modified:

- All nonstandard DRM properties have been removed
- dropped struct vop2_plane_state and pass around less data between
  functions
- Dropped all DRM_FORMAT_* not known on upstream
- rework register access to get rid of excessively used macros

The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
board. Overlay support is tested with the modetest utility. AFBC support
is still present in the driver, but currently untested due to the lack
of suitable image sources. Also the driver has been tested with weston
using pixman and (yet to be upstreamed) panfrost driver support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/Kconfig             |    6 +
 drivers/gpu/drm/rockchip/Makefile            |    1 +
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h  |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h  |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 3611 ++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c |  916 +++++
 8 files changed, 5331 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index a1c4158259099..b841f4873f7f3 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -27,6 +27,12 @@ config ROCKCHIP_VOP
 	  This selects support for the VOP driver. You should enable it
 	  on all older SoCs up to RK3399.
 
+config ROCKCHIP_VOP2
+	bool "Rockchip VOP2 driver"
+	help
+	  This selects support for the VOP2 driver. You should enable it
+	  on all newer SoCs beginning form RK3568.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
 	depends on ROCKCHIP_VOP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index cd6e7bb5ce9c5..29848caef5c21 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index b8fe56c89cdc9..f6296b8a123ab 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -324,6 +324,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
 
 	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
 	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+	s->output_if = VOP_OUTPUT_IF_HDMI0;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 64fa5fd62c01a..2bd9acb265e5a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -474,6 +474,7 @@ static int __init rockchip_drm_init(void)
 
 	num_rockchip_sub_drivers = 0;
 	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index aa0909e8edf93..cdd2c2847441a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,12 +18,26 @@
 
 #define ROCKCHIP_MAX_FB_BUFFER	3
 #define ROCKCHIP_MAX_CONNECTOR	2
-#define ROCKCHIP_MAX_CRTC	2
+#define ROCKCHIP_MAX_CRTC	4
 
 struct drm_device;
 struct drm_connector;
 struct iommu_domain;
 
+#define VOP_OUTPUT_IF_RGB       BIT(0)
+#define VOP_OUTPUT_IF_BT1120    BIT(1)
+#define VOP_OUTPUT_IF_BT656     BIT(2)
+#define VOP_OUTPUT_IF_LVDS0     BIT(3)
+#define VOP_OUTPUT_IF_LVDS1     BIT(4)
+#define VOP_OUTPUT_IF_MIPI0     BIT(5)
+#define VOP_OUTPUT_IF_MIPI1     BIT(6)
+#define VOP_OUTPUT_IF_eDP0      BIT(7)
+#define VOP_OUTPUT_IF_eDP1      BIT(8)
+#define VOP_OUTPUT_IF_DP0       BIT(9)
+#define VOP_OUTPUT_IF_DP1       BIT(10)
+#define VOP_OUTPUT_IF_HDMI0     BIT(11)
+#define VOP_OUTPUT_IF_HDMI1     BIT(12)
+
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
 	int output_type;
@@ -31,6 +45,10 @@ struct rockchip_crtc_state {
 	int output_bpc;
 	int output_flags;
 	bool enable_afbc;
+	uint32_t bus_format;
+	uint32_t output_if;
+	u32 bus_flags;
+	int color_space;
 };
 #define to_rockchip_crtc_state(s) \
 		container_of(s, struct rockchip_crtc_state, base)
@@ -65,4 +83,6 @@ extern struct platform_driver rockchip_dp_driver;
 extern struct platform_driver rockchip_lvds_driver;
 extern struct platform_driver vop_platform_driver;
 extern struct platform_driver rk3066_hdmi_driver;
+extern struct platform_driver vop2_platform_driver;
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 857d97cdc67c6..1eccadf72b59b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -7,6 +7,8 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#include <drm/drm_modes.h>
+
 /*
  * major: IP major version, used for IP structure
  * minor: big feature change under same structure
@@ -15,6 +17,14 @@
 #define VOP_MAJOR(version)		((version) >> 8)
 #define VOP_MINOR(version)		((version) & 0xff)
 
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE    BIT(0)
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE      BIT(1)
+#define ROCKCHIP_OUTPUT_DATA_SWAP                       BIT(2)
+
+#define VOP_FEATURE_OUTPUT_10BIT        BIT(0)
+#define VOP_FEATURE_AFBDC               BIT(1)
+#define VOP_FEATURE_ALPHA_SCALE         BIT(2)
+
 #define NUM_YUV2YUV_COEFFICIENTS 12
 
 /* AFBC supports a number of configurable modes. Relevant to us is block size
@@ -54,9 +64,23 @@ struct vop_afbc {
 	struct vop_reg enable;
 	struct vop_reg win_sel;
 	struct vop_reg format;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg auto_gating_en;
+	struct vop_reg block_split_en;
+	struct vop_reg pic_vir_width;
+	struct vop_reg tile_num;
 	struct vop_reg hreg_block_split;
+	struct vop_reg pic_offset;
 	struct vop_reg pic_size;
+	struct vop_reg dsp_offset;
+	struct vop_reg transform_offset;
 	struct vop_reg hdr_ptr;
+	struct vop_reg half_block_en;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rotate_270;
+	struct vop_reg rotate_90;
 	struct vop_reg rstn;
 };
 
@@ -184,6 +208,12 @@ struct vop_win_phy {
 	struct vop_reg channel;
 };
 
+struct vop_grf_ctrl {
+	struct vop_reg grf_dclk_inv;
+	struct vop_reg grf_bt1120_clk_inv;
+	struct vop_reg grf_bt656_clk_inv;
+};
+
 struct vop_win_yuv2yuv_data {
 	uint32_t base;
 	const struct vop_yuv2yuv_phy *phy;
@@ -409,5 +439,749 @@ static inline int scl_vop_cal_lb_mode(int width, bool is_yuv)
 	return lb_mode;
 }
 
+static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
+{
+	return us * mode->clock / mode->htotal / 1000;
+}
+
 extern const struct component_ops vop_component_ops;
+
+#define WIN_FEATURE_HDR2SDR		BIT(0)
+#define WIN_FEATURE_SDR2HDR		BIT(1)
+#define WIN_FEATURE_PRE_OVERLAY		BIT(2)
+#define WIN_FEATURE_AFBDC		BIT(3)
+#define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
+#define WIN_FEATURE_CLUSTER_SUB		BIT(5)
+/* a mirror win can only get fb address
+ * from source win:
+ * Cluster1---->Cluster0
+ * Esmart1 ---->Esmart0
+ * Smart1  ---->Smart0
+ * This is a feather on rk3566
+ */
+#define WIN_FEATURE_MIRROR		BIT(6)
+#define WIN_FEATURE_MULTI_AREA		BIT(7)
+
+#define ROCKCHIP_MAX_LAYER       16
+#define MEDIA_BUS_FMT_SRGB888_3X8              0x101c
+#define WIN_FEATURE_MIRROR               BIT(6)
+#define MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA       0x101b
+#define MEDIA_BUS_FMT_SRGB888_DUMMY_4X8                0x101f
+
+/*
+ *  the delay number of a window in different mode.
+ */
+enum win_dly_mode {
+	VOP2_DLY_MODE_DEFAULT,   /**< default mode */
+	VOP2_DLY_MODE_HISO_S,    /** HDR in SDR out mode, as a SDR window */
+	VOP2_DLY_MODE_HIHO_H,    /** HDR in HDR out mode, as a HDR window */
+	VOP2_DLY_MODE_MAX,
+};
+
+struct vop_rect {
+	int width;
+	int height;
+};
+
+/* interrupt define */
+#define FS_NEW_INTR			BIT(4)
+#define ADDR_SAME_INTR			BIT(5)
+#define LINE_FLAG1_INTR			BIT(6)
+#define WIN0_EMPTY_INTR			BIT(7)
+#define WIN1_EMPTY_INTR			BIT(8)
+#define WIN2_EMPTY_INTR			BIT(9)
+#define WIN3_EMPTY_INTR			BIT(10)
+#define HWC_EMPTY_INTR			BIT(11)
+#define POST_BUF_EMPTY_INTR		BIT(12)
+#define PWM_GEN_INTR			BIT(13)
+#define DMA_FINISH_INTR			BIT(14)
+#define FS_FIELD_INTR			BIT(15)
+#define FE_INTR				BIT(16)
+#define WB_UV_FIFO_FULL_INTR		BIT(17)
+#define WB_YRGB_FIFO_FULL_INTR		BIT(18)
+#define WB_COMPLETE_INTR		BIT(19)
+
+#define VOP2_INTR_MASK			(DSP_HOLD_VALID_INTR | FS_INTR | \
+					 LINE_FLAG_INTR | BUS_ERROR_INTR | \
+					 FS_NEW_INTR | LINE_FLAG1_INTR | \
+					 WIN0_EMPTY_INTR | WIN1_EMPTY_INTR | \
+					 WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | \
+					 HWC_EMPTY_INTR | \
+					 POST_BUF_EMPTY_INTR | \
+					 DMA_FINISH_INTR | FS_FIELD_INTR | \
+					 FE_INTR)
+#define DSP_HOLD_VALID_INTR_EN(x)	((x) << 4)
+#define FS_INTR_EN(x)			((x) << 5)
+#define LINE_FLAG_INTR_EN(x)		((x) << 6)
+#define BUS_ERROR_INTR_EN(x)		((x) << 7)
+#define DSP_HOLD_VALID_INTR_MASK	(1 << 4)
+#define FS_INTR_MASK			(1 << 5)
+#define LINE_FLAG_INTR_MASK		(1 << 6)
+#define BUS_ERROR_INTR_MASK		(1 << 7)
+
+#define INTR_CLR_SHIFT			8
+#define DSP_HOLD_VALID_INTR_CLR		(1 << (INTR_CLR_SHIFT + 0))
+#define FS_INTR_CLR			(1 << (INTR_CLR_SHIFT + 1))
+#define LINE_FLAG_INTR_CLR		(1 << (INTR_CLR_SHIFT + 2))
+#define BUS_ERROR_INTR_CLR		(1 << (INTR_CLR_SHIFT + 3))
+
+#define DSP_LINE_NUM(x)			(((x) & 0x1fff) << 12)
+#define DSP_LINE_NUM_MASK		(0x1fff << 12)
+
+/* src alpha ctrl define */
+#define SRC_FADING_VALUE(x)		(((x) & 0xff) << 24)
+#define SRC_GLOBAL_ALPHA(x)		(((x) & 0xff) << 16)
+#define SRC_FACTOR_M0(x)		(((x) & 0x7) << 6)
+#define SRC_ALPHA_CAL_M0(x)		(((x) & 0x1) << 5)
+#define SRC_BLEND_M0(x)			(((x) & 0x3) << 3)
+#define SRC_ALPHA_M0(x)			(((x) & 0x1) << 2)
+#define SRC_COLOR_M0(x)			(((x) & 0x1) << 1)
+#define SRC_ALPHA_EN(x)			(((x) & 0x1) << 0)
+/* dst alpha ctrl define */
+#define DST_FACTOR_M0(x)		(((x) & 0x7) << 6)
+
+/*
+ * display output interface supported by rockchip lcdc
+ */
+#define ROCKCHIP_OUT_MODE_P888		0
+#define ROCKCHIP_OUT_MODE_BT1120	0
+#define ROCKCHIP_OUT_MODE_P666		1
+#define ROCKCHIP_OUT_MODE_P565		2
+#define ROCKCHIP_OUT_MODE_BT656		5
+#define ROCKCHIP_OUT_MODE_S888		8
+#define ROCKCHIP_OUT_MODE_S888_DUMMY	12
+#define ROCKCHIP_OUT_MODE_YUV420	14
+/* for use special outface */
+#define ROCKCHIP_OUT_MODE_AAAA		15
+
+#define ROCKCHIP_OUT_MODE_TYPE(x)	((x) >> 16)
+#define ROCKCHIP_OUT_MODE(x)		((x) & 0xffff)
+
+enum vop_csc_format {
+	CSC_BT601L,
+	CSC_BT709L,
+	CSC_BT601F,
+	CSC_BT2020,
+};
+
+enum src_factor_mode {
+	SRC_FAC_ALPHA_ZERO,
+	SRC_FAC_ALPHA_ONE,
+	SRC_FAC_ALPHA_DST,
+	SRC_FAC_ALPHA_DST_INVERSE,
+	SRC_FAC_ALPHA_SRC,
+	SRC_FAC_ALPHA_SRC_GLOBAL,
+};
+
+enum dst_factor_mode {
+	DST_FAC_ALPHA_ZERO,
+	DST_FAC_ALPHA_ONE,
+	DST_FAC_ALPHA_SRC,
+	DST_FAC_ALPHA_SRC_INVERSE,
+	DST_FAC_ALPHA_DST,
+	DST_FAC_ALPHA_DST_GLOBAL,
+};
+
+enum vop2_scale_up_mode {
+	VOP2_SCALE_UP_NRST_NBOR,
+	VOP2_SCALE_UP_BIL,
+	VOP2_SCALE_UP_BIC,
+};
+
+enum vop2_scale_down_mode {
+	VOP2_SCALE_DOWN_NRST_NBOR,
+	VOP2_SCALE_DOWN_BIL,
+	VOP2_SCALE_DOWN_AVG,
+};
+
+struct vop2_cluster_regs {
+	struct vop_reg enable;
+	struct vop_reg afbc_enable;
+	struct vop_reg lb_mode;
+};
+
+struct vop2_scl_regs {
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg yrgb_hscl_filter_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_vscl_filter_mode;
+	struct vop_reg cbcr_ver_scl_mode;
+	struct vop_reg cbcr_hscl_filter_mode;
+	struct vop_reg cbcr_hor_scl_mode;
+	struct vop_reg cbcr_vscl_filter_mode;
+	struct vop_reg vsd_cbcr_gt2;
+	struct vop_reg vsd_cbcr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+};
+
+struct vop2_win_regs {
+	const struct vop2_scl_regs *scl;
+	const struct vop2_cluster_regs *cluster;
+	const struct vop_afbc *afbc;
+
+	struct vop_reg gate;
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg csc_mode;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg act_info;
+	struct vop_reg dsp_info;
+	struct vop_reg dsp_st;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg yrgb_vir;
+	struct vop_reg uv_vir;
+	struct vop_reg yuv_clip;
+	struct vop_reg lb_mode;
+	struct vop_reg y2r_en;
+	struct vop_reg r2y_en;
+	struct vop_reg channel;
+	struct vop_reg dst_alpha_ctl;
+	struct vop_reg src_alpha_ctl;
+	struct vop_reg alpha_mode;
+	struct vop_reg alpha_en;
+	struct vop_reg global_alpha_val;
+	struct vop_reg color_key;
+	struct vop_reg color_key_en;
+	struct vop_reg dither_up;
+};
+
+struct vop2_video_port_regs {
+	struct vop_reg cfg_done;
+	struct vop_reg overlay_mode;
+	struct vop_reg dsp_background;
+	struct vop_reg port_mux;
+	struct vop_reg out_mode;
+	struct vop_reg standby;
+	struct vop_reg dsp_interlace;
+	struct vop_reg dsp_filed_pol;
+	struct vop_reg dsp_data_swap;
+	struct vop_reg post_dsp_out_r2y;
+	struct vop_reg pre_scan_htiming;
+	struct vop_reg htotal_pw;
+	struct vop_reg hact_st_end;
+	struct vop_reg vtotal_pw;
+	struct vop_reg vact_st_end;
+	struct vop_reg vact_st_end_f1;
+	struct vop_reg vs_st_end_f1;
+	struct vop_reg hpost_st_end;
+	struct vop_reg vpost_st_end;
+	struct vop_reg vpost_st_end_f1;
+	struct vop_reg post_scl_factor;
+	struct vop_reg post_scl_ctrl;
+	struct vop_reg dither_down_sel;
+	struct vop_reg dither_down_mode;
+	struct vop_reg dither_down_en;
+	struct vop_reg pre_dither_down_en;
+	struct vop_reg dither_up_en;
+	struct vop_reg bg_dly;
+
+	struct vop_reg core_dclk_div;
+	struct vop_reg p2i_en;
+	struct vop_reg mipi_dual_en;
+	struct vop_reg mipi_dual_channel_swap;
+	struct vop_reg dsp_lut_en;
+
+	struct vop_reg dclk_div2;
+	struct vop_reg dclk_div2_phase_lock;
+
+	struct vop_reg hdr10_en;
+	struct vop_reg hdr_lut_update_en;
+	struct vop_reg hdr_lut_mode;
+	struct vop_reg hdr_lut_mst;
+	struct vop_reg sdr2hdr_eotf_en;
+	struct vop_reg sdr2hdr_r2r_en;
+	struct vop_reg sdr2hdr_r2r_mode;
+	struct vop_reg sdr2hdr_oetf_en;
+	struct vop_reg sdr2hdr_bypass_en;
+	struct vop_reg sdr2hdr_auto_gating_en;
+	struct vop_reg sdr2hdr_path_en;
+	struct vop_reg hdr2sdr_en;
+	struct vop_reg hdr2sdr_bypass_en;
+	struct vop_reg hdr2sdr_auto_gating_en;
+	struct vop_reg hdr2sdr_src_min;
+	struct vop_reg hdr2sdr_src_max;
+	struct vop_reg hdr2sdr_normfaceetf;
+	struct vop_reg hdr2sdr_dst_min;
+	struct vop_reg hdr2sdr_dst_max;
+	struct vop_reg hdr2sdr_normfacgamma;
+	uint32_t hdr2sdr_eetf_oetf_y0_offset;
+	uint32_t hdr2sdr_sat_y0_offset;
+	uint32_t sdr2hdr_eotf_oetf_y0_offset;
+	uint32_t sdr2hdr_oetf_dx_pow1_offset;
+	uint32_t sdr2hdr_oetf_xn1_offset;
+	struct vop_reg hdr_src_color_ctrl;
+	struct vop_reg hdr_dst_color_ctrl;
+	struct vop_reg hdr_src_alpha_ctrl;
+	struct vop_reg hdr_dst_alpha_ctrl;
+
+	/* BCSH */
+	struct vop_reg bcsh_brightness;
+	struct vop_reg bcsh_contrast;
+	struct vop_reg bcsh_sat_con;
+	struct vop_reg bcsh_sin_hue;
+	struct vop_reg bcsh_cos_hue;
+	struct vop_reg bcsh_r2y_csc_mode;
+	struct vop_reg bcsh_r2y_en;
+	struct vop_reg bcsh_y2r_csc_mode;
+	struct vop_reg bcsh_y2r_en;
+	struct vop_reg bcsh_out_mode;
+	struct vop_reg bcsh_en;
+
+	/* 3d lut */
+	struct vop_reg cubic_lut_en;
+	struct vop_reg cubic_lut_update_en;
+	struct vop_reg cubic_lut_mst;
+};
+
+struct vop2_wb_regs {
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg dither_en;
+	struct vop_reg r2y_en;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg vp_id;
+	struct vop_reg fifo_throd;
+	struct vop_reg scale_x_factor;
+	struct vop_reg scale_x_en;
+	struct vop_reg scale_y_en;
+	struct vop_reg axi_yrgb_id;
+	struct vop_reg axi_uv_id;
+};
+
+struct vop2_win_data {
+	const char *name;
+	uint8_t phys_id;
+
+	uint32_t base;
+	enum drm_plane_type type;
+
+	uint32_t nformats;
+	const uint32_t *formats;
+	const uint64_t *format_modifiers;
+	const unsigned int supported_rotations;
+
+	const struct vop2_win_regs *regs;
+
+	/*
+	 * vertical/horizontal scale up/down filter mode
+	 */
+	const u8 hsu_filter_mode;
+	const u8 hsd_filter_mode;
+	const u8 vsu_filter_mode;
+	const u8 vsd_filter_mode;
+	/**
+	 * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2
+	 */
+	int layer_sel_id;
+	uint64_t feature;
+
+	unsigned int max_upscale_factor;
+	unsigned int max_downscale_factor;
+	const uint8_t dly[VOP2_DLY_MODE_MAX];
+};
+
+struct vop2_wb_data {
+	uint32_t nformats;
+	const uint32_t *formats;
+	struct vop_rect max_output;
+	const struct vop2_wb_regs *regs;
+};
+
+struct vop2_video_port_data {
+	char id;
+	uint32_t feature;
+	uint16_t gamma_lut_len;
+	uint16_t cubic_lut_len;
+	struct vop_rect max_output;
+	const u8 pre_scan_max_dly[4];
+	const struct vop_intr *intr;
+	const struct vop2_video_port_regs *regs;
+};
+
+struct vop2_layer_regs {
+	struct vop_reg layer_sel;
+};
+
+/**
+ * struct vop2_layer_data - The logic graphic layer in vop2
+ *
+ * The zorder:
+ *   LAYERn
+ *   LAYERn-1
+ *     .
+ *     .
+ *     .
+ *   LAYER5
+ *   LAYER4
+ *   LAYER3
+ *   LAYER2
+ *   LAYER1
+ *   LAYER0
+ *
+ * Each layer can select a unused window as input than feed to
+ * mixer for overlay.
+ *
+ * The pipeline in vop2:
+ *
+ * win-->layer-->mixer-->vp--->connector(RGB/LVDS/HDMI/MIPI)
+ *
+ */
+struct vop2_layer_data {
+	char id;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_ctrl {
+	struct vop_reg cfg_done_en;
+	struct vop_reg wb_cfg_done;
+	struct vop_reg auto_gating_en;
+	struct vop_reg ovl_cfg_done_port;
+	struct vop_reg ovl_port_mux_cfg_done_imd;
+	struct vop_reg ovl_port_mux_cfg;
+	struct vop_reg if_ctrl_cfg_done_imd;
+	struct vop_reg version;
+	struct vop_reg standby;
+	struct vop_reg dma_stop;
+	struct vop_reg lut_dma_en;
+	struct vop_reg axi_outstanding_max_num;
+	struct vop_reg axi_max_outstanding_en;
+	struct vop_reg hdmi_dclk_out_en;
+	struct vop_reg rgb_en;
+	struct vop_reg hdmi0_en;
+	struct vop_reg hdmi1_en;
+	struct vop_reg dp0_en;
+	struct vop_reg dp1_en;
+	struct vop_reg edp0_en;
+	struct vop_reg edp1_en;
+	struct vop_reg mipi0_en;
+	struct vop_reg mipi1_en;
+	struct vop_reg lvds0_en;
+	struct vop_reg lvds1_en;
+	struct vop_reg bt656_en;
+	struct vop_reg bt1120_en;
+	struct vop_reg dclk_pol;
+	struct vop_reg pin_pol;
+	struct vop_reg rgb_dclk_pol;
+	struct vop_reg rgb_pin_pol;
+	struct vop_reg lvds_dclk_pol;
+	struct vop_reg lvds_pin_pol;
+	struct vop_reg hdmi_dclk_pol;
+	struct vop_reg hdmi_pin_pol;
+	struct vop_reg edp_dclk_pol;
+	struct vop_reg edp_pin_pol;
+	struct vop_reg mipi_dclk_pol;
+	struct vop_reg mipi_pin_pol;
+	struct vop_reg dp_dclk_pol;
+	struct vop_reg dp_pin_pol;
+
+	struct vop_reg win_vp_id[8];
+	struct vop_reg win_dly[8];
+
+	/* connector mux */
+	struct vop_reg rgb_mux;
+	struct vop_reg hdmi0_mux;
+	struct vop_reg hdmi1_mux;
+	struct vop_reg dp0_mux;
+	struct vop_reg dp1_mux;
+	struct vop_reg edp0_mux;
+	struct vop_reg edp1_mux;
+	struct vop_reg mipi0_mux;
+	struct vop_reg mipi1_mux;
+	struct vop_reg lvds0_mux;
+	struct vop_reg lvds1_mux;
+
+	struct vop_reg lvds_dual_en;
+	struct vop_reg lvds_dual_mode;
+	struct vop_reg lvds_dual_channel_swap;
+
+	struct vop_reg cluster0_src_color_ctrl;
+	struct vop_reg cluster0_dst_color_ctrl;
+	struct vop_reg cluster0_src_alpha_ctrl;
+	struct vop_reg cluster0_dst_alpha_ctrl;
+	struct vop_reg src_color_ctrl;
+	struct vop_reg dst_color_ctrl;
+	struct vop_reg src_alpha_ctrl;
+	struct vop_reg dst_alpha_ctrl;
+
+	struct vop_reg bt1120_yc_swap;
+	struct vop_reg bt656_yc_swap;
+	struct vop_reg gamma_port_sel;
+
+	struct vop_reg otp_en;
+	struct vop_reg reg_done_frm;
+	struct vop_reg cfg_done;
+};
+
+/**
+ * VOP2 data struct
+ *
+ * @version: VOP IP version
+ * @win_size: hardware win number
+ */
+struct vop2_data {
+	uint8_t nr_vps;
+	uint8_t nr_mixers;
+	uint8_t nr_layers;
+	uint8_t nr_axi_intr;
+	uint8_t nr_gammas;
+	const struct vop_intr *axi_intr;
+	const struct vop2_ctrl *ctrl;
+	const struct vop2_win_data *win;
+	const struct vop2_video_port_data *vp;
+	const struct vop2_wb_data *wb;
+	const struct vop2_layer_data *layer;
+	const struct vop_csc_table *csc_table;
+	const struct vop_grf_ctrl *grf_ctrl;
+	struct vop_rect max_input;
+	struct vop_rect max_output;
+
+	unsigned int win_size;
+	unsigned int soc_id;
+};
+
+#define RK3568_GRF_VO_CON1			0x0364
+/* System registers definition */
+#define RK3568_REG_CFG_DONE			0x000
+#define RK3568_VOP2_WB_CFG_DONE			BIT(14)
+#define RK3568_VOP2_GLB_CFG_DONE_EN		BIT(15)
+#define RK3568_VERSION_INFO			0x004
+#define RK3568_SYS_AUTO_GATING_CTRL		0x008
+#define RK3568_SYS_AXI_LUT_CTRL			0x024
+#define RK3568_DSP_IF_EN			0x028
+#define RK3568_DSP_IF_CTRL			0x02c
+#define RK3568_DSP_IF_POL			0x030
+#define RK3568_WB_CTRL				0x40
+#define RK3568_WB_XSCAL_FACTOR			0x44
+#define RK3568_WB_YRGB_MST			0x48
+#define RK3568_WB_CBR_MST			0x4C
+#define RK3568_OTP_WIN_EN			0x050
+#define RK3568_LUT_PORT_SEL			0x058
+#define RK3568_SYS_STATUS0			0x060
+#define RK3568_VP0_LINE_FLAG			0x70
+#define RK3568_VP1_LINE_FLAG			0x74
+#define RK3568_VP2_LINE_FLAG			0x78
+#define RK3568_SYS0_INT_EN			0x80
+#define RK3568_SYS0_INT_CLR			0x84
+#define RK3568_SYS0_INT_STATUS			0x88
+#define RK3568_SYS1_INT_EN			0x90
+#define RK3568_SYS1_INT_CLR			0x94
+#define RK3568_SYS1_INT_STATUS			0x98
+#define RK3568_VP0_INT_EN			0xA0
+#define RK3568_VP0_INT_CLR			0xA4
+#define RK3568_VP0_INT_STATUS			0xA8
+#define RK3568_VP0_INT_RAW_STATUS		0xAC
+#define RK3568_VP1_INT_EN			0xB0
+#define RK3568_VP1_INT_CLR			0xB4
+#define RK3568_VP1_INT_STATUS			0xB8
+#define RK3568_VP1_INT_RAW_STATUS		0xBC
+#define RK3568_VP2_INT_EN			0xC0
+#define RK3568_VP2_INT_CLR			0xC4
+#define RK3568_VP2_INT_STATUS			0xC8
+#define RK3568_VP2_INT_RAW_STATUS		0xCC
+
+/* Video Port registers definition */
+#define RK3568_VP0_DSP_CTRL			0xC00
+#define RK3568_VP0_MIPI_CTRL			0xC04
+#define RK3568_VP0_COLOR_BAR_CTRL		0xC08
+#define RK3568_VP0_3D_LUT_CTRL			0xC10
+#define RK3568_VP0_3D_LUT_MST			0xC20
+#define RK3568_VP0_DSP_BG			0xC2C
+#define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
+#define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
+#define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
+#define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
+#define RK3568_VP0_POST_SCL_CTRL		0xC40
+#define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
+#define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
+#define RK3568_VP0_DSP_HACT_ST_END		0xC4C
+#define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
+#define RK3568_VP0_DSP_VACT_ST_END		0xC54
+#define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
+#define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
+#define RK3568_VP0_BCSH_CTRL			0xC60
+#define RK3568_VP0_BCSH_BCS			0xC64
+#define RK3568_VP0_BCSH_H			0xC68
+#define RK3568_VP0_BCSH_COLOR_BAR		0xC6C
+
+#define RK3568_VP1_DSP_CTRL			0xD00
+#define RK3568_VP1_MIPI_CTRL			0xD04
+#define RK3568_VP1_COLOR_BAR_CTRL		0xD08
+#define RK3568_VP1_DSP_BG			0xD2C
+#define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
+#define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
+#define RK3568_VP1_POST_SCL_CTRL		0xD40
+#define RK3568_VP1_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
+#define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
+#define RK3568_VP1_DSP_HACT_ST_END		0xD4C
+#define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
+#define RK3568_VP1_DSP_VACT_ST_END		0xD54
+#define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
+#define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
+#define RK3568_VP1_BCSH_CTRL			0xD60
+#define RK3568_VP1_BCSH_BCS			0xD64
+#define RK3568_VP1_BCSH_H			0xD68
+#define RK3568_VP1_BCSH_COLOR_BAR		0xD6C
+
+#define RK3568_VP2_DSP_CTRL			0xE00
+#define RK3568_VP2_MIPI_CTRL			0xE04
+#define RK3568_VP2_COLOR_BAR_CTRL		0xE08
+#define RK3568_VP2_DSP_BG			0xE2C
+#define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
+#define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
+#define RK3568_VP2_POST_SCL_CTRL		0xE40
+#define RK3568_VP2_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
+#define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
+#define RK3568_VP2_DSP_HACT_ST_END		0xE4C
+#define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
+#define RK3568_VP2_DSP_VACT_ST_END		0xE54
+#define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
+#define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
+#define RK3568_VP2_BCSH_CTRL			0xE60
+#define RK3568_VP2_BCSH_BCS			0xE64
+#define RK3568_VP2_BCSH_H			0xE68
+#define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
+
+/* Overlay registers definition    */
+#define RK3568_OVL_CTRL				0x600
+#define RK3568_OVL_LAYER_SEL			0x604
+#define RK3568_OVL_PORT_SEL			0x608
+#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
+#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
+#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
+#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
+#define RK3568_MIX0_SRC_COLOR_CTRL		0x650
+#define RK3568_MIX0_DST_COLOR_CTRL		0x654
+#define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
+#define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
+#define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
+#define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
+#define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
+#define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
+#define RK3568_VP0_BG_MIX_CTRL			0x6E0
+#define RK3568_VP1_BG_MIX_CTRL			0x6E4
+#define RK3568_VP2_BG_MIX_CTRL			0x6E8
+#define RK3568_CLUSTER_DLY_NUM			0x6F0
+#define RK3568_SMART_DLY_NUM			0x6F8
+
+/* Cluster register definition, offset relative to window base */
+#define RK3568_CLUSTER_WIN_CTRL0		0x00
+#define RK3568_CLUSTER_WIN_CTRL1		0x04
+#define RK3568_CLUSTER_WIN_YRGB_MST		0x10
+#define RK3568_CLUSTER_WIN_CBR_MST		0x14
+#define RK3568_CLUSTER_WIN_VIR			0x18
+#define RK3568_CLUSTER_WIN_ACT_INFO		0x20
+#define RK3568_CLUSTER_WIN_DSP_INFO		0x24
+#define RK3568_CLUSTER_WIN_DSP_ST		0x28
+#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB	0x30
+#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET	0x3C
+#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL	0x50
+#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE	0x54
+#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR	0x58
+#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH	0x5C
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE	0x60
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET	0x64
+#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET	0x68
+#define RK3568_CLUSTER_WIN_AFBCD_CTRL		0x6C
+
+#define RK3568_CLUSTER_CTRL			0x100
+
+/* (E)smart register definition, offset relative to window base */
+#define RK3568_SMART_CTRL0			0x00
+#define RK3568_SMART_CTRL1			0x04
+#define RK3568_SMART_REGION0_CTRL		0x10
+#define RK3568_SMART_REGION0_YRGB_MST		0x14
+#define RK3568_SMART_REGION0_CBR_MST		0x18
+#define RK3568_SMART_REGION0_VIR		0x1C
+#define RK3568_SMART_REGION0_ACT_INFO		0x20
+#define RK3568_SMART_REGION0_DSP_INFO		0x24
+#define RK3568_SMART_REGION0_DSP_ST		0x28
+#define RK3568_SMART_REGION0_SCL_CTRL		0x30
+#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB	0x34
+#define RK3568_SMART_REGION0_SCL_FACTOR_CBR	0x38
+#define RK3568_SMART_REGION0_SCL_OFFSET		0x3C
+#define RK3568_SMART_REGION1_CTRL		0x40
+#define RK3568_SMART_REGION1_YRGB_MST		0x44
+#define RK3568_SMART_REGION1_CBR_MST		0x48
+#define RK3568_SMART_REGION1_VIR		0x4C
+#define RK3568_SMART_REGION1_ACT_INFO		0x50
+#define RK3568_SMART_REGION1_DSP_INFO		0x54
+#define RK3568_SMART_REGION1_DSP_ST		0x58
+#define RK3568_SMART_REGION1_SCL_CTRL		0x60
+#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB	0x64
+#define RK3568_SMART_REGION1_SCL_FACTOR_CBR	0x68
+#define RK3568_SMART_REGION1_SCL_OFFSET		0x6C
+#define RK3568_SMART_REGION2_CTRL		0x70
+#define RK3568_SMART_REGION2_YRGB_MST		0x74
+#define RK3568_SMART_REGION2_CBR_MST		0x78
+#define RK3568_SMART_REGION2_VIR		0x7C
+#define RK3568_SMART_REGION2_ACT_INFO		0x80
+#define RK3568_SMART_REGION2_DSP_INFO		0x84
+#define RK3568_SMART_REGION2_DSP_ST		0x88
+#define RK3568_SMART_REGION2_SCL_CTRL		0x90
+#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB	0x94
+#define RK3568_SMART_REGION2_SCL_FACTOR_CBR	0x98
+#define RK3568_SMART_REGION2_SCL_OFFSET		0x9C
+#define RK3568_SMART_REGION3_CTRL		0xA0
+#define RK3568_SMART_REGION3_YRGB_MST		0xA4
+#define RK3568_SMART_REGION3_CBR_MST		0xA8
+#define RK3568_SMART_REGION3_VIR		0xAC
+#define RK3568_SMART_REGION3_ACT_INFO		0xB0
+#define RK3568_SMART_REGION3_DSP_INFO		0xB4
+#define RK3568_SMART_REGION3_DSP_ST		0xB8
+#define RK3568_SMART_REGION3_SCL_CTRL		0xC0
+#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB	0xC4
+#define RK3568_SMART_REGION3_SCL_FACTOR_CBR	0xC8
+#define RK3568_SMART_REGION3_SCL_OFFSET		0xCC
+#define RK3568_SMART_COLOR_KEY_CTRL		0xD0
+
+/* HDR register definition */
+#define RK3568_HDR_LUT_CTRL				0x2000
+#define RK3568_HDR_LUT_MST				0x2004
+#define RK3568_SDR2HDR_CTRL				0x2010
+#define RK3568_HDR2SDR_CTRL				0x2020
+#define RK3568_HDR2SDR_SRC_RANGE			0x2024
+#define RK3568_HDR2SDR_NORMFACEETF			0x2028
+#define RK3568_HDR2SDR_DST_RANGE			0x202C
+#define RK3568_HDR2SDR_NORMFACCGAMMA			0x2030
+#define RK3568_HDR_EETF_OETF_Y0				0x203C
+#define RK3568_HDR_SAT_Y0				0x20C0
+#define RK3568_HDR_EOTF_OETF_Y0				0x20F0
+#define RK3568_HDR_OETF_DX_POW1				0x2200
+#define RK3568_HDR_OETF_XN1				0x2300
+
+enum vop2_layer_phy_id {
+	ROCKCHIP_VOP2_CLUSTER0 = 0,
+	ROCKCHIP_VOP2_CLUSTER1,
+	ROCKCHIP_VOP2_ESMART0,
+	ROCKCHIP_VOP2_ESMART1,
+	ROCKCHIP_VOP2_SMART0,
+	ROCKCHIP_VOP2_SMART1,
+	ROCKCHIP_VOP2_CLUSTER2,
+	ROCKCHIP_VOP2_CLUSTER3,
+	ROCKCHIP_VOP2_ESMART2,
+	ROCKCHIP_VOP2_ESMART3,
+	ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
+};
+
+extern const struct component_ops vop2_component_ops;
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
new file mode 100644
index 0000000000000..60fa529718810
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -0,0 +1,3611 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+#include <drm/drm.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_writeback.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_atomic_uapi.h>
+
+#include <linux/debugfs.h>
+#include <linux/fixp-arith.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <linux/component.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/swab.h>
+#include <linux/sort.h>
+#include <drm/drm_debugfs.h>
+#include <uapi/linux/videodev2.h>
+#include <drm/drm_vblank.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_gem.h"
+#include "rockchip_drm_fb.h"
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define VOP2_SYS_AXI_BUS_NUM 2
+
+#define VOP2_CLUSTER_YUV444_10 0x12
+
+#define VOP2_COLOR_KEY_MASK		(1 << 31)
+
+#define DSP_BG_SWAP             0x1
+#define DSP_RB_SWAP             0x2
+#define DSP_RG_SWAP             0x4
+#define DSP_DELTA_SWAP          0x8
+
+enum vop2_data_format {
+	VOP2_FMT_ARGB8888 = 0,
+	VOP2_FMT_RGB888,
+	VOP2_FMT_RGB565,
+	VOP2_FMT_XRGB101010,
+	VOP2_FMT_YUV420SP,
+	VOP2_FMT_YUV422SP,
+	VOP2_FMT_YUV444SP,
+	VOP2_FMT_YUYV422 = 8,
+	VOP2_FMT_YUYV420,
+	VOP2_FMT_VYUY422,
+	VOP2_FMT_VYUY420,
+	VOP2_FMT_YUV420SP_TILE_8x4 = 0x10,
+	VOP2_FMT_YUV420SP_TILE_16x2,
+	VOP2_FMT_YUV422SP_TILE_8x4,
+	VOP2_FMT_YUV422SP_TILE_16x2,
+	VOP2_FMT_YUV420SP_10,
+	VOP2_FMT_YUV422SP_10,
+	VOP2_FMT_YUV444SP_10,
+};
+
+enum vop2_afbc_format {
+	VOP2_AFBC_FMT_RGB565,
+	VOP2_AFBC_FMT_ARGB2101010 = 2,
+	VOP2_AFBC_FMT_YUV420_10BIT,
+	VOP2_AFBC_FMT_RGB888,
+	VOP2_AFBC_FMT_ARGB8888,
+	VOP2_AFBC_FMT_YUV420 = 9,
+	VOP2_AFBC_FMT_YUV422 = 0xb,
+	VOP2_AFBC_FMT_YUV422_10BIT = 0xe,
+	VOP2_AFBC_FMT_INVALID = -1,
+};
+
+enum vop2_hdr_lut_mode {
+	VOP2_HDR_LUT_MODE_AXI,
+	VOP2_HDR_LUT_MODE_AHB,
+};
+
+enum vop2_pending {
+	VOP_PENDING_FB_UNREF,
+};
+
+struct vop2_zpos {
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	int zpos;
+};
+
+union vop2_alpha_ctrl {
+	uint32_t val;
+	struct {
+		/* [0:1] */
+		uint32_t color_mode:1;
+		uint32_t alpha_mode:1;
+		/* [2:3] */
+		uint32_t blend_mode:2;
+		uint32_t alpha_cal_mode:1;
+		/* [5:7] */
+		uint32_t factor_mode:3;
+		/* [8:9] */
+		uint32_t alpha_en:1;
+		uint32_t src_dst_swap:1;
+		uint32_t reserved:6;
+		/* [16:23] */
+		uint32_t glb_alpha:8;
+	} bits;
+};
+
+struct vop2_alpha {
+	union vop2_alpha_ctrl src_color_ctrl;
+	union vop2_alpha_ctrl dst_color_ctrl;
+	union vop2_alpha_ctrl src_alpha_ctrl;
+	union vop2_alpha_ctrl dst_alpha_ctrl;
+};
+
+struct vop2_alpha_config {
+	bool src_premulti_en;
+	bool dst_premulti_en;
+	bool src_pixel_alpha_en;
+	bool dst_pixel_alpha_en;
+	uint16_t src_glb_alpha_value;
+	uint16_t dst_glb_alpha_value;
+};
+
+struct vop2_win {
+	const char *name;
+	struct vop2 *vop2;
+	struct drm_plane base;
+	const struct vop2_win_data *data;
+
+	/*
+	 * This is for cluster window
+	 *
+	 * A cluster window can split as two windows:
+	 * a main window and a sub window.
+	 */
+	bool two_win_mode;
+
+	/**
+	 * @win_id: graphic window id, a cluster maybe split into two
+	 * graphics windows.
+	 */
+	uint8_t win_id;
+	/**
+	 * @plane_id: unique plane id.
+	 */
+	uint8_t plane_id;
+	/**
+	 * @layer_id: id of the layer which the window attached to
+	 */
+	uint8_t layer_id;
+	int layer_sel_id;
+	/**
+	 * @vp_mask: Bitmask of video_port0/1/2 this win attached to,
+	 * one win can only attach to one vp at the one time.
+	 */
+	uint8_t vp_mask;
+	/**
+	 * @old_vp_mask: Bitmask of video_port0/1/2 this win attached of last commit,
+	 * this is used for trackng the change of VOP2_PORT_SEL register.
+	 */
+	uint8_t old_vp_mask;
+	uint8_t zpos;
+	uint32_t offset;
+	enum drm_plane_type type;
+
+	const struct vop2_win_regs *regs;
+};
+
+struct vop2_cluster {
+	struct vop2_win *main;
+	struct vop2_win *sub;
+};
+
+struct vop2_layer {
+	uint8_t id;
+	struct vop2_win *win;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_video_port {
+	struct drm_crtc crtc;
+	struct vop2 *vop2;
+	struct clk *dclk;
+	uint8_t id;
+	bool layer_sel_update;
+	const struct vop2_video_port_regs *regs;
+
+	struct completion dsp_hold_completion;
+	struct completion line_flag_completion;
+
+	/* protected by dev->event_lock */
+	struct drm_pending_vblank_event *event;
+
+	struct drm_flip_work fb_unref_work;
+	unsigned long pending;
+
+	struct vop2_zpos *zpos;
+	int nr_layers;
+
+	/**
+	 * @skip_vsync: skip on vsync when port_mux changed on this vp.
+	 * a win move from one VP to another need wait one vsync until
+	 * port_mut take effect before this win can be enabled.
+	 *
+	 */
+	bool skip_vsync;
+
+	/**
+	 * @bg_ovl_dly: The timing delay from background layer
+	 * to overlay module.
+	 */
+	uint8_t bg_ovl_dly;
+
+	/**
+	 * @win_mask: Bitmask of wins attached to the video port;
+	 */
+	uint32_t win_mask;
+
+	/**
+	 * @gamma_lut_len: gamma look up table size
+	 */
+	uint32_t gamma_lut_len;
+
+	/**
+	 * @gamma_lut_active: gamma states
+	 */
+	bool gamma_lut_active;
+
+	struct vop2_win *primary_plane;
+};
+
+struct vop2 {
+	struct device *dev;
+	struct drm_device *drm;
+	struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
+
+	const struct vop2_data *data;
+	/* Number of win that registered as plane,
+	 * maybe less than the total number of hardware
+	 * win.
+	 */
+	uint32_t registered_num_wins;
+	uint8_t used_mixers;
+
+	uint16_t port_mux_cfg;
+
+	uint32_t *regsbak;
+	void __iomem *regs;
+	struct regmap *grf;
+
+	/* physical map length of vop2 register */
+	uint32_t len;
+
+	void __iomem *lut_regs;
+	/* one time only one process allowed to config the register */
+	spinlock_t reg_lock;
+	/* lock vop2 irq reg */
+	spinlock_t irq_lock;
+	/* protects crtc enable/disable */
+	struct mutex vop2_lock;
+
+	int irq;
+
+	/*
+	 * Some globle resource are shared between all
+	 * the vidoe ports(crtcs), so we need a ref counter here.
+	 */
+	unsigned int enable_count;
+	struct clk *hclk;
+	struct clk *aclk;
+
+	struct vop2_layer layers[ROCKCHIP_MAX_LAYER];
+	/* must put at the end of the struct */
+	struct vop2_win win[];
+};
+
+static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct vop2_video_port, crtc);
+}
+
+static inline struct vop2_win *to_vop2_win(struct drm_plane *p)
+{
+	return container_of(p, struct vop2_win, base);
+}
+
+static void vop2_lock(struct vop2 *vop2)
+{
+	mutex_lock(&vop2->vop2_lock);
+}
+
+static void vop2_unlock(struct vop2 *vop2)
+{
+	mutex_unlock(&vop2->vop2_lock);
+}
+
+static inline void vop2_grf_writel(struct vop2 *vop2, struct vop_reg reg, uint32_t v)
+{
+	uint32_t val = 0;
+
+	if (IS_ERR_OR_NULL(vop2->grf))
+		return;
+
+	if (reg.mask) {
+		val = (v << reg.shift) | (reg.mask << (reg.shift + 16));
+		regmap_write(vop2->grf, reg.offset, val);
+	}
+}
+
+static void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v)
+{
+	writel(v, vop2->regs + offset);
+	vop2->regsbak[offset >> 2] = v;
+}
+
+static uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset)
+{
+	return readl(vop2->regs + offset);
+}
+
+static uint32_t vop2_read_reg(struct vop2 *vop2, uint32_t offset,
+			      const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, offset + reg->offset) >> reg->shift) & reg->mask;
+}
+
+static inline uint32_t vop2_read(struct vop2 *vop2, const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, reg->offset) >> reg->shift) & reg->mask;
+}
+
+static void vop2_write_reg(struct vop2 *vop2, uint32_t offset, const struct vop_reg *reg,
+				   uint32_t v, bool relaxed)
+{
+	uint32_t mask = reg->mask;
+	uint32_t shift = reg->shift;
+
+	if (!mask)
+		return;
+
+	offset += reg->offset;
+
+	if (reg->write_mask) {
+		v = ((v & mask) << shift) | (mask << (shift + 16));
+	} else {
+		/*
+		 * Several registers in the VOP2 are double buffered and read back
+		 * the new values only after config_done bits have been set. As we
+		 * read-modify-write the hardware registers we need to cache the values
+		 * in memory to make sure we do not overwrite previous values when a
+		 * hardware register is modified multiple times before config_done is
+		 * set.
+		 */
+		uint32_t cached_val = vop2->regsbak[offset >> 2];
+
+		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
+		vop2->regsbak[offset >> 2] = v;
+	}
+
+	if (relaxed)
+		writel_relaxed(v, vop2->regs + offset);
+	else
+		writel(v, vop2->regs + offset);
+}
+
+static void vop2_write(struct vop2 *vop2, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(vop2, 0, reg, v, false);
+}
+
+static void vop2_win_write(const struct vop2_win *win, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(win->vop2, win->offset, reg, v, true);
+}
+
+static uint32_t vop2_win_read(const struct vop2_win *win, const struct vop_reg *reg)
+{
+	return vop2_read_reg(win->vop2, win->offset, reg);
+}
+
+
+static void vop2_intr_set_type(struct vop2 *vop2, const struct vop_intr *intr,
+			       const struct vop_reg *reg, uint32_t type, bool enable)
+{
+	uint32_t v = 0, mask = 0;
+	int i;
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if (intr->intrs[i] & type) {
+			if (enable)
+				v |= 1 << i;
+			mask |= 1 << i;
+		}
+	}
+
+	writel(v | (mask << 16), vop2->regs + reg->offset);
+}
+
+static inline uint32_t vop2_line_to_time(struct drm_display_mode *mode, int line)
+{
+	u64 val = 1000000000ULL * mode->crtc_htotal * line;
+
+	do_div(val, mode->crtc_clock);
+	do_div(val, 1000000);
+
+	return val; /* us */
+}
+
+static inline uint32_t vop2_get_intr_type(struct vop2 *vop2, const struct vop_intr *intr,
+					  const struct vop_reg *reg, int type)
+{
+	uint32_t val, i;
+	uint32_t ret = 0;
+
+	val = vop2_read_reg(vop2, 0, reg);
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if ((type & intr->intrs[i]) && (val & 1 << i))
+			ret |= intr->intrs[i];
+	}
+
+	return ret;
+}
+
+/*
+ * phys_id is used to identify a main window(Cluster Win/Smart Win, not
+ * include the sub win of a cluster or the multi area) that can do
+ * overlay in main overlay stage.
+ */
+static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys_id)
+{
+	struct vop2_win *win;
+	int i;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+		if (win->data->phys_id == phys_id)
+			return win;
+	}
+
+	return NULL;
+}
+
+static bool vop2_fs_irq_is_pending(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	return vop2_get_intr_type(vop2, intr, &intr->status, FS_FIELD_INTR);
+}
+
+static uint32_t vop2_read_vcnt(struct vop2_video_port *vp)
+{
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint32_t offset = RK3568_SYS_STATUS0 + (vp->id << 2);
+	uint32_t vcnt;
+
+	vcnt = vop2_readl(vp->vop2, offset) >> 16;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vcnt >>= 1;
+
+	return vcnt;
+}
+
+static void vop2_wait_for_irq_handler(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	bool pending;
+	int ret;
+
+	/*
+	 * Spin until frame start interrupt status bit goes low, which means
+	 * that interrupt handler was invoked and cleared it. The timeout of
+	 * 10 msecs is really too long, but it is just a safety measure if
+	 * something goes really wrong. The wait will only happen in the very
+	 * unlikely case of a vblank happening exactly at the same time and
+	 * shouldn't exceed microseconds range.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_fs_irq_is_pending, vp, pending,
+					!pending, 0, 10 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "VOP vblank IRQ stuck for 10 ms\n");
+
+	synchronize_irq(vop2->irq);
+}
+
+static bool vop2_vp_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & BIT(vp->id);
+
+	/*
+	 * When done bit is 0, indicate current frame is take effect.
+	 */
+	return done_bits == 0 ? true : false;
+}
+
+static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	bool done_bit;
+	int ret;
+
+	ret = readx_poll_timeout_atomic(vop2_vp_done_bit_status, vp, done_bit,
+					done_bit, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait vp%d done bit status timeout, vcnt: %d\n",
+			      vp->id, vop2_read_vcnt(vp));
+}
+
+static uint16_t vop2_read_port_mux(struct vop2 *vop2)
+{
+	return vop2_readl(vop2, RK3568_OVL_PORT_SEL) & 0xffff;
+}
+
+static void vop2_wait_for_port_mux_done(struct vop2 *vop2)
+{
+	uint16_t port_mux_cfg;
+	int ret;
+
+	/*
+	 * Spin until the previous port_mux figuration
+	 * is done.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_read_port_mux, vop2, port_mux_cfg,
+					port_mux_cfg == vop2->port_mux_cfg, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait port_mux done timeout: 0x%x--0x%x\n",
+			      port_mux_cfg, vop2->port_mux_cfg);
+}
+
+
+static int32_t vop2_pending_done_bits(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *adjusted_mode;
+	struct vop2_video_port *done_vp;
+	uint32_t done_bits, done_bits_bak;
+	uint32_t vp_id;
+	uint32_t vcnt;
+	struct drm_display_mode *first_mode, *second_mode;
+	struct vop2_video_port *first_done_vp, *second_done_vp, *wait_vp;
+	uint32_t first_vp_id, second_vp_id;
+	uint32_t first_vp_vcnt, second_vp_vcnt;
+	uint32_t first_vp_left_vcnt, second_vp_left_vcnt;
+	uint32_t first_vp_left_time, second_vp_left_time;
+	uint32_t first_vp_safe_time, second_vp_safe_time;
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	done_bits_bak = done_bits;
+
+	done_bits &= ~BIT(vp->id);
+
+	/* no done bit, so no need to wait config done take effect */
+	if (done_bits == 0)
+		return 0;
+
+	/* have the other one different vp, wait for config done take effect */
+	if (hweight32(done_bits) == 1) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		adjusted_mode = &done_vp->crtc.state->adjusted_mode;
+		vcnt = vop2_read_vcnt(done_vp);
+
+		/* if close to the last 1/8 frame, wait to next frame */
+		if (vcnt > (adjusted_mode->crtc_vtotal * 7 >> 3)) {
+			vop2_wait_for_fs_by_done_bit_status(done_vp);
+			return 0;
+		}
+		return done_bits;
+	}
+
+	first_vp_id = ffs(done_bits) - 1;
+	first_done_vp = &vop2->vps[first_vp_id];
+	first_mode = &first_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	first_vp_safe_time = 1000000 / drm_mode_vrefresh(first_mode) >> 3;
+
+	done_bits &= ~BIT(first_vp_id);
+	second_vp_id = ffs(done_bits) - 1;
+	second_done_vp = &vop2->vps[second_vp_id];
+	second_mode = &second_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	second_vp_safe_time = 1000000 / drm_mode_vrefresh(second_mode) >> 3;
+
+	first_vp_vcnt = vop2_read_vcnt(first_done_vp);
+
+	second_vp_vcnt = vop2_read_vcnt(second_done_vp);
+
+	first_vp_left_vcnt = first_mode->crtc_vtotal - first_vp_vcnt;
+	second_vp_left_vcnt = second_mode->crtc_vtotal - second_vp_vcnt;
+	first_vp_left_time = vop2_line_to_time(first_mode, first_vp_left_vcnt);
+	second_vp_left_time = vop2_line_to_time(second_mode, second_vp_left_vcnt);
+
+	/* if the two vp both at safe section, no need to wait */
+	if (first_vp_left_time > first_vp_safe_time &&
+	    second_vp_left_time > second_vp_safe_time)
+		return done_bits_bak;
+
+	if (first_vp_left_time > second_vp_left_time)
+		wait_vp = first_done_vp;
+	else
+		wait_vp = second_done_vp;
+
+	vop2_wait_for_fs_by_done_bit_status(wait_vp);
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	if (done_bits) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		vop2_wait_for_fs_by_done_bit_status(done_vp);
+	}
+	return 0;
+}
+
+static inline void vop2_cfg_done(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits;
+	uint32_t val;
+	uint32_t old_layer_sel_val, cfg_layer_sel_val;
+	struct vop2_layer *layer = &vop2->layers[0];
+	uint32_t layer_sel_offset = layer->regs->layer_sel.offset;
+
+	/*
+	 * This is a workaround, the config done bits of VP0,
+	 * VP1, VP2 on RK3568 stands on the first three bits
+	 * on REG_CFG_DONE register without mask bit.
+	 * If two or three config done events happens one after
+	 * another in a very shot time, the flowing config done
+	 * write may override the previous config done bit before
+	 * it take effect:
+	 * 1: config done 0x8001 for VP0
+	 * 2: config done 0x8002 for VP1
+	 *
+	 * 0x8002 may override 0x8001 before it take effect.
+	 *
+	 * So we do a read | write here.
+	 *
+	 */
+	done_bits = vop2_pending_done_bits(vp);
+	old_layer_sel_val = vop2_readl(vop2, layer_sel_offset);
+	cfg_layer_sel_val = vop2->regsbak[layer_sel_offset >> 2];
+	/**
+	 * This is rather low probability for miss some done bit.
+	 */
+	val = RK3568_VOP2_GLB_CFG_DONE_EN | BIT(vp->id) | done_bits |
+		(vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7);
+	vop2_writel(vop2, 0, val);
+
+	/**
+	 * Make sure the layer sel is take effect when it's updated.
+	 */
+	if (old_layer_sel_val != cfg_layer_sel_val) {
+		vp->layer_sel_update = true;
+		vop2_wait_for_fs_by_done_bit_status(vp);
+		drm_dbg(vop2->drm, "vp%d need to wait fs as old layer_sel val[0x%x] != new val[0x%x]\n",
+			      vp->id, old_layer_sel_val, cfg_layer_sel_val);
+	}
+}
+
+static void vop2_win_disable(struct vop2_win *win)
+{
+	struct vop2 *vop2 = win->vop2;
+
+	vop2_win_write(win, &win->regs->enable, 0);
+	if (win->data->feature & WIN_FEATURE_CLUSTER_MAIN) {
+		struct vop2_win *sub_win;
+		int i = 0;
+
+		for (i = 0; i < vop2->registered_num_wins; i++) {
+			sub_win = &vop2->win[i];
+
+			if ((sub_win->data->phys_id == win->data->phys_id) &&
+			    (sub_win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+				vop2_win_write(sub_win, &sub_win->regs->enable, 0);
+		}
+
+		vop2_win_write(win, &win->regs->cluster->enable, 0);
+	}
+}
+
+static enum vop2_data_format vop2_convert_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_FMT_YUV420SP;
+	case DRM_FORMAT_NV16:
+		return VOP2_FMT_YUV422SP;
+	case DRM_FORMAT_NV24:
+		return VOP2_FMT_YUV444SP;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return VOP2_FMT_VYUY422;
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_UYVY:
+		return VOP2_FMT_YUYV422;
+	default:
+		DRM_ERROR("unsupported format[%08x]\n", format);
+		return -EINVAL;
+	}
+}
+
+static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_AFBC_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_AFBC_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_AFBC_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_AFBC_FMT_YUV420;
+	case DRM_FORMAT_NV16:
+		return VOP2_AFBC_FMT_YUV422;
+
+		/* either of the below should not be reachable */
+	default:
+		DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
+		return VOP2_AFBC_FMT_INVALID;
+	}
+
+	return VOP2_AFBC_FMT_INVALID;
+}
+
+static bool vop2_win_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_BGR565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_dither_up(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode)
+{
+	/*
+	 * FIXME:
+	 *
+	 * There is no media type for YUV444 output,
+	 * so when out_mode is AAAA or P888, assume output is YUV444 on
+	 * yuv format.
+	 *
+	 * From H/W testing, YUV444 mode need a rb swap.
+	 */
+	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
+	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
+	      bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
+	     (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
+	      output_mode == ROCKCHIP_OUT_MODE_P888)))
+		return true;
+	else
+		return false;
+}
+
+static bool vop2_output_yc_swap(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_output(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_alpha_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
+{
+	int i;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return false;
+
+	for (i = 0 ; i < plane->modifier_count; i++)
+		if (plane->modifiers[i] == modifier)
+			break;
+
+	return (i < plane->modifier_count) ? true : false;
+
+}
+
+static bool rockchip_vop2_mod_supported(struct drm_plane *plane, uint32_t format, u64 modifier)
+{
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	if (modifier == DRM_FORMAT_MOD_INVALID)
+		return false;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return true;
+
+	if (!rockchip_afbc(plane, modifier)) {
+		drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", modifier);
+
+		return false;
+	}
+
+	return vop2_convert_afbc_format(format) >= 0;
+}
+
+static inline bool vop2_cluster_window(struct vop2_win *win)
+{
+	return  (win->data->feature & (WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_CLUSTER_SUB));
+}
+
+static int vop2_afbc_half_block_enable(struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 0;
+	else
+		return 1;
+}
+
+static uint32_t vop2_afbc_transform_offset(struct drm_plane_state *pstate,
+					   bool afbc_half_block_en)
+{
+	struct drm_rect *src = &pstate->src;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t vir_width = (fb->pitches[0] << 3) / bpp;
+	uint32_t width = drm_rect_width(src) >> 16;
+	uint32_t height = drm_rect_height(src) >> 16;
+	uint32_t act_xoffset = src->x1 >> 16;
+	uint32_t act_yoffset = src->y1 >> 16;
+	uint32_t align16_crop = 0;
+	uint32_t align64_crop = 0;
+	uint32_t height_tmp = 0;
+	uint32_t transform_tmp = 0;
+	uint8_t transform_xoffset = 0;
+	uint8_t transform_yoffset = 0;
+	uint8_t top_crop = 0;
+	uint8_t top_crop_line_num = 0;
+	uint8_t bottom_crop_line_num = 0;
+
+	/* 16 pixel align */
+	if (height & 0xf)
+		align16_crop = 16 - (height & 0xf);
+
+	height_tmp = height + align16_crop;
+
+	/* 64 pixel align */
+	if (height_tmp & 0x3f)
+		align64_crop = 64 - (height_tmp & 0x3f);
+
+	top_crop_line_num = top_crop << 2;
+	if (top_crop == 0)
+		bottom_crop_line_num = align16_crop + align64_crop;
+	else if (top_crop == 1)
+		bottom_crop_line_num = align16_crop + align64_crop + 12;
+	else if (top_crop == 2)
+		bottom_crop_line_num = align16_crop + align64_crop + 8;
+
+	switch (pstate->rotation &
+		(DRM_MODE_REFLECT_X |
+		 DRM_MODE_REFLECT_Y |
+		 DRM_MODE_ROTATE_90 |
+		 DRM_MODE_ROTATE_270)) {
+	case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = (transform_tmp & 0xf);
+
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case 0:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	}
+
+	return (transform_xoffset & 0xf) | ((transform_yoffset & 0xf) << 16);
+}
+
+/*
+ * A Cluster window has 2048 x 16 line buffer, which can
+ * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
+ * for Cluster_lb_mode register:
+ * 0: half mode, for plane input width range 2048 ~ 4096
+ * 1: half mode, for cluster work at 2 * 2048 plane mode
+ * 2: half mode, for rotate_90/270 mode
+ *
+ */
+static int vop2_get_cluster_lb_mode(struct vop2_win *win, struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 2;
+	else if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * bli_sd_factor = (src - 1) / (dst - 1) << 12;
+ * avg_sd_factor:
+ * bli_su_factor:
+ * bic_su_factor:
+ * = (src - 1) / (dst - 1) << 16;
+ *
+ * gt2 enable: dst get one line from two line of the src
+ * gt4 enable: dst get one line from four line of the src.
+ *
+ */
+
+static uint16_t vop2_scale_factor(enum scale_mode mode,
+				  int32_t filter_mode,
+				  uint32_t src, uint32_t dst)
+{
+	uint32_t fac;
+	int i;
+
+	if (mode == SCALE_NONE)
+		return 0;
+
+	/*
+	 * A workaround to avoid zero div.
+	 */
+	if ((dst == 1) || (src == 1)) {
+		dst = dst + 1;
+		src = src + 1;
+	}
+
+	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
+		fac = ((src - 1) << 12) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 12 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	} else {
+		fac = ((src - 1) << 16) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 16 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	}
+
+	return fac;
+}
+
+static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
+			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+			     uint32_t dst_h, uint32_t pixel_format)
+{
+	const struct vop2_win_data *win_data = win->data;
+	const struct drm_format_info *info;
+	uint16_t cbcr_src_w;
+	uint16_t cbcr_src_h;
+	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
+	uint16_t cbcr_hor_scl_mode, cbcr_ver_scl_mode;
+	uint16_t hscl_filter_mode, vscl_filter_mode;
+	uint8_t gt2 = 0;
+	uint8_t gt4 = 0;
+	uint32_t val;
+
+	info = drm_format_info(pixel_format);
+
+	cbcr_src_w = src_w / info->hsub;
+	cbcr_src_h = src_h / info->vsub;
+
+	if (src_h >= (4 * dst_h)) {
+		gt4 = 1;
+		src_h >>= 2;
+	} else if (src_h >= (2 * dst_h)) {
+		gt2 = 1;
+		src_h >>= 1;
+	}
+
+	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
+	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
+
+	if (yrgb_hor_scl_mode == SCALE_UP)
+		hscl_filter_mode = win_data->hsu_filter_mode;
+	else
+		hscl_filter_mode = win_data->hsd_filter_mode;
+
+	if (yrgb_ver_scl_mode == SCALE_UP)
+		vscl_filter_mode = win_data->vsu_filter_mode;
+	else
+		vscl_filter_mode = win_data->vsd_filter_mode;
+
+	/*
+	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
+	 * at scale down mode
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
+			drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", win->data->name, dst_w);
+			dst_w += 1;
+		}
+	}
+
+	val = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode,
+				src_w, dst_w);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_x, val);
+	val = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode,
+				src_h, dst_h);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_y, val);
+
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt4, gt4);
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt2, gt2);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hscl_filter_mode, hscl_filter_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_vscl_filter_mode, vscl_filter_mode);
+
+	if (info->is_yuv) {
+		gt4 = gt2 = 0;
+
+		if (cbcr_src_h >= (4 * dst_h))
+			gt4 = 1;
+		else if (cbcr_src_h >= (2 * dst_h))
+			gt2 = 1;
+
+		if (gt4)
+			cbcr_src_h >>= 2;
+		else if (gt2)
+			cbcr_src_h >>= 1;
+
+		cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
+		cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
+
+		val = vop2_scale_factor(cbcr_hor_scl_mode, hscl_filter_mode,
+					cbcr_src_w, dst_w);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_x, val);
+		val = vop2_scale_factor(cbcr_ver_scl_mode, vscl_filter_mode,
+					cbcr_src_h, dst_h);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_y, val);
+
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt4, gt4);
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt2, gt2);
+		vop2_win_write(win, &win->regs->scl->cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_hscl_filter_mode, hscl_filter_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_vscl_filter_mode, vscl_filter_mode);
+	}
+}
+
+static int vop2_convert_csc_mode(int csc_mode)
+{
+	switch (csc_mode) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return CSC_BT601L;
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SMPTE240M:
+	case V4L2_COLORSPACE_DEFAULT:
+		return CSC_BT709L;
+	case V4L2_COLORSPACE_JPEG:
+		return CSC_BT601F;
+	case V4L2_COLORSPACE_BT2020:
+		return CSC_BT2020;
+	default:
+		return CSC_BT709L;
+	}
+}
+
+static bool vop2_is_allwin_disabled(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	unsigned long win_mask = vp->win_mask;
+	struct vop2_win *win;
+	int phys_id;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		if (vop2_win_read(win, &win->regs->enable) != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void vop2_disable_all_planes_for_crtc(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct vop2_win *win;
+	unsigned long win_mask = vp->win_mask;
+	int phys_id, ret;
+	bool active, need_wait_win_disabled = false;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		need_wait_win_disabled |= vop2_win_read(win, &win->regs->enable);
+		vop2_win_disable(win);
+	}
+
+	if (need_wait_win_disabled) {
+		vop2_cfg_done(vp);
+		ret = readx_poll_timeout_atomic(vop2_is_allwin_disabled, vp,
+						active, active, 0, 500 * 1000);
+		if (ret)
+			drm_err(vop2->drm, "wait win close timeout\n");
+	}
+}
+
+/*
+ * colorspace path:
+ *      Input        Win csc                     Output
+ * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
+ *    RGB        --> R2Y(601)             __/
+ *
+ * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
+ *    RGB        --> bypass               __/
+ *
+ * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
+ *
+ * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
+ *
+ * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
+ *
+ * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
+ */
+
+static void vop2_setup_csc_mode(struct vop2_video_port *vp,
+				struct vop2_win *win,
+				struct drm_plane_state *pstate)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
+	int is_input_yuv = is_yuv_support(pstate->fb->format->format);
+	int is_output_yuv = is_yuv_output(vcstate->bus_format);
+	int input_csc = V4L2_COLORSPACE_DEFAULT;
+	int output_csc = vcstate->color_space;
+	bool r2y_en, y2r_en;
+	int csc_mode;
+
+	if (is_input_yuv && !is_output_yuv) {
+		y2r_en = 1;
+		r2y_en = 0;
+		csc_mode = vop2_convert_csc_mode(input_csc);
+	} else if (!is_input_yuv && is_output_yuv) {
+		y2r_en = 0;
+		r2y_en = 1;
+		csc_mode = vop2_convert_csc_mode(output_csc);
+	} else {
+		y2r_en = 0;
+		r2y_en = 0;
+		csc_mode = 0;
+	}
+
+	vop2_win_write(win, &win->regs->y2r_en, y2r_en);
+	vop2_win_write(win, &win->regs->r2y_en, r2y_en);
+	vop2_win_write(win, &win->regs->csc_mode, csc_mode);
+}
+
+static void vop2_axi_irqs_enable(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr;
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t i;
+
+	for (i = 0; i < vop2_data->nr_axi_intr; i++) {
+		intr = &vop2_data->axi_intr[i];
+		vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+		vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+	}
+}
+
+static uint32_t vop2_read_and_clear_axi_irqs(struct vop2 *vop2, int index)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr = &vop2_data->axi_intr[index];
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t val;
+
+	val = vop2_get_intr_type(vop2, intr, &intr->status, irqs);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+
+	return val;
+}
+
+static void vop2_dsp_hold_valid_irq_enable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, DSP_HOLD_VALID_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_dsp_hold_valid_irq_disable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_debug_irq_enable(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	uint32_t irqs = POST_BUF_EMPTY_INTR;
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+}
+
+static bool vop2_dsp_lut_is_enabled(struct vop2_video_port *vp)
+{
+	return vop2_read(vp->vop2, &vp->regs->dsp_lut_en);
+}
+
+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ *     the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
+ *      to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG -------------------------------+
+ * FRAME_SYNC ----+                         |
+ *                |                         |
+ *                v                         v
+ *                | Vsync | Vbp |  Vactive  | Vfp |
+ *                        ^     ^           ^     ^
+ *                        |     |           |     |
+ *                        |     |           |     |
+ * dsp_vs_end ------------+     |           |     |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --------------+           |     |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end ----------------------------+     |   VOP_DSP_VACT_ST_END
+ * dsp_total -------------------------------------+   VOP_DSP_VTOTAL_VS_END
+ */
+
+static void vop2_crtc_load_lut(struct drm_crtc *crtc, struct drm_color_lut *lut)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int dle = 0, i = 0;
+	uint8_t vp_enable_gamma_nr = 0;
+
+	for (i = 0; i < vop2->data->nr_vps; i++) {
+		struct vop2_video_port *vp = &vop2->vps[i];
+
+		if (i == vp->id)
+			continue;
+
+		if (vp->gamma_lut_active)
+			vp_enable_gamma_nr++;
+	}
+
+	if (vp_enable_gamma_nr >= vop2->data->nr_gammas) {
+		drm_info(vop2->drm, "only support %d gamma\n", vop2->data->nr_gammas);
+		return;
+	}
+
+	spin_lock(&vop2->reg_lock);
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 0);
+	vop2_cfg_done(vp);
+	spin_unlock(&vop2->reg_lock);
+
+	readx_poll_timeout(vop2_dsp_lut_is_enabled, vp, dle, !dle, 5, 33333);
+
+	for (i = 0; i < vp->gamma_lut_len; i++) {
+		uint32_t r, g, b;
+		uint32_t ll = vp->gamma_lut_len;
+
+		r = lut[i].red * (ll - 1) / 0xffff;
+		g = lut[i].green * (ll - 1) / 0xffff;
+		b = lut[i].blue * (ll - 1) / 0xffff;
+		writel(b * ll * ll + g * ll + r, vop2->lut_regs + (i << 2));
+	}
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 1);
+	vop2_write(vop2, &vop2->data->ctrl->gamma_port_sel, vp->id);
+	vop2_cfg_done(vp);
+	vp->gamma_lut_active = true;
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = clk_prepare_enable(vop2->hclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable hclk - %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vop2->aclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable aclk - %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	clk_disable_unprepare(vop2->hclk);
+
+	return ret;
+}
+
+/*
+ * VOP2 architecture
+ *
+ +----------+   +-------------+                                                        +-----------+
+ |  Cluster |   | Sel 1 from 6|                                                        | 1 from 3  |
+ |  window0 |   |    Layer0   |                                                        |    RGB    |
+ +----------+   +-------------+              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 layers|    |             |
+ |  Cluster |   | Sel 1 from 6|              |   Overlay0    +--->| Video Port0 |      +-----------+
+ |  window1 |   |    Layer1   |              |               |    |             |      | 1 from 3  |
+ +----------+   +-------------+              +---------------+    +-------------+      |   LVDS    |
+ +----------+   +-------------+                                                        +-----------+
+ |  Esmart  |   | Sel 1 from 6|
+ |  window0 |   |   Layer2    |              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 Layers|    |             | +--> | 1 from 3  |
+ +----------+   +-------------+   -------->  |   Overlay1    +--->| Video Port1 |      |   MIPI    |
+ |  Esmart  |   | Sel 1 from 6|   -------->  |               |    |             |      +-----------+
+ |  Window1 |   |   Layer3    |              +---------------+    +-------------+
+ +----------+   +-------------+                                                        +-----------+
+ +----------+   +-------------+                                                        | 1 from 3  |
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |   HDMI    |
+ |  Window0 |   |    Layer4   |              |N from 6 Layers|    |             |      +-----------+
+ +----------+   +-------------+              |   Overlay2    +--->| Video Port2 |
+ +----------+   +-------------+              |               |    |             |      +-----------+
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |  1 from 3 |
+ |  Window1 |   |    Layer5   |                                                        |    eDP    |
+ +----------+   +-------------+                                                        +-----------+
+ *
+ */
+
+static void vop2_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(vop2->dev);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
+		return;
+	}
+
+	ret = vop2_core_clks_prepare_enable(vop2);
+	if (ret) {
+		pm_runtime_put_sync(vop2->dev);
+		return;
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 0);
+
+	if (vop2->data->soc_id == 3566)
+		vop2_write(vop2, &vop2->data->ctrl->otp_en, 1);
+
+	memcpy(vop2->regsbak, vop2->regs, vop2->len);
+
+	vop2_write(vop2, &vop2->data->ctrl->cfg_done_en, 1);
+	/*
+	 * Disable auto gating, this is a workaround to
+	 * avoid display image shift when a window enabled.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->auto_gating_en, 0);
+	/*
+	 * Register OVERLAY_LAYER_SEL and OVERLAY_PORT_SEL should take effect immediately,
+	 * than windows configuration(CLUSTER/ESMART/SMART) can take effect according the
+	 * video port mux configuration as we wished.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 1);
+	/*
+	 * Let SYS_DSP_INFACE_EN/SYS_DSP_INFACE_CTRL/SYS_DSP_INFACE_POL take effect
+	 * immediately.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->if_ctrl_cfg_done_imd, 1);
+
+	vop2_axi_irqs_enable(vop2);
+}
+
+static void vop2_disable(struct vop2 *vop2)
+{
+	/*
+	 * vop2 standby complete, so iommu detach is safe.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 1);
+
+	pm_runtime_put_sync(vop2->dev);
+
+	clk_disable_unprepare(vop2->aclk);
+	clk_disable_unprepare(vop2->hclk);
+}
+
+static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
+				     struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int ret;
+
+	WARN_ON(vp->event);
+	vop2_lock(vop2);
+
+	drm_crtc_vblank_off(crtc);
+	vop2_disable_all_planes_for_crtc(vp);
+
+	/*
+	 * Vop standby will take effect at end of current frame,
+	 * if dsp hold valid irq happen, it means standby complete.
+	 *
+	 * we must wait standby complete when we want to disable aclk,
+	 * if not, memory bus maybe dead.
+	 */
+	reinit_completion(&vp->dsp_hold_completion);
+	vop2_dsp_hold_valid_irq_enable(crtc);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->standby, 1);
+
+	spin_unlock(&vop2->reg_lock);
+
+	ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50));
+	if (!ret)
+		drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id);
+
+	vop2_dsp_hold_valid_irq_disable(crtc);
+
+	clk_disable_unprepare(vp->dclk);
+
+	vop2->enable_count--;
+
+	if (!vop2->enable_count)
+		vop2_disable(vop2);
+
+	vop2_unlock(vop2);
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *astate)
+{
+	struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct drm_framebuffer *fb = pstate->fb;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct drm_crtc_state *cstate;
+	struct vop2_video_port *vp;
+	struct vop2 *vop2;
+	const struct vop2_data *vop2_data;
+	struct drm_rect *dest = &pstate->dst;
+	struct drm_rect *src = &pstate->src;
+	int min_scale = win->regs->scl ? FRAC_16_16(1, 8) : DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = win->regs->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING;
+	int format;
+	int ret;
+
+	if (!crtc)
+		return 0;
+
+	vp = to_vop2_video_port(crtc);
+	vop2 = vp->vop2;
+	vop2_data = vop2->data;
+
+	cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc);
+	if (WARN_ON(!cstate))
+		return -EINVAL;
+
+	ret = drm_atomic_helper_check_plane_state(pstate, cstate,
+						  min_scale, max_scale,
+						  true, true);
+	if (ret)
+		return ret;
+
+	if (!pstate->visible)
+		return 0;
+
+	format = vop2_convert_format(fb->format->format);
+	if (format < 0)
+		return format;
+
+	if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
+	    drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
+		drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n",
+			  drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
+			  drm_rect_width(dest), drm_rect_height(dest));
+		pstate->visible = false;
+		return 0;
+	}
+
+	if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
+	    drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
+		drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n",
+			  drm_rect_width(src) >> 16,
+			  drm_rect_height(src) >> 16,
+			  vop2_data->max_input.width,
+			  vop2_data->max_input.height);
+		return -EINVAL;
+	}
+
+	/*
+	 * Src.x1 can be odd when do clip, but yuv plane start point
+	 * need align with 2 pixel.
+	 */
+	if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) {
+		drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	drm_dbg(vop2->drm, "%s disable\n", win->data->name);
+
+	if (!old_pstate->crtc)
+		return;
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_win_disable(win);
+	vop2_win_write(win, &win->regs->yuv_clip, 0);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * The color key is 10 bit, so all format should
+ * convert to 10 bit here.
+ */
+static void vop2_plane_setup_color_key(struct drm_plane *plane, uint32_t color_key)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_framebuffer *fb = pstate->fb;
+	struct vop2_win *win = to_vop2_win(plane);
+	uint32_t color_key_en = 0;
+	uint32_t r = 0;
+	uint32_t g = 0;
+	uint32_t b = 0;
+
+	if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->color_key_en, 0);
+		return;
+	}
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		r = (color_key & 0xf800) >> 11;
+		g = (color_key & 0x7e0) >> 5;
+		b = (color_key & 0x1f);
+		r <<= 5;
+		g <<= 4;
+		b <<= 5;
+		color_key_en = 1;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		r = (color_key & 0xff0000) >> 16;
+		g = (color_key & 0xff00) >> 8;
+		b = (color_key & 0xff);
+		r <<= 2;
+		g <<= 2;
+		b <<= 2;
+		color_key_en = 1;
+		break;
+	}
+
+	vop2_win_write(win, &win->regs->color_key_en, color_key_en);
+	vop2_win_write(win, &win->regs->color_key, (r << 20) | (g << 10) | b);
+}
+
+static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = win->vop2;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t actual_w, actual_h, dsp_w, dsp_h;
+	uint32_t act_info, dsp_info;
+	uint32_t format;
+	uint32_t afbc_format;
+	uint32_t rb_swap;
+	uint32_t uv_swap;
+	struct drm_rect *src = &pstate->src;
+	struct drm_rect *dest = &pstate->dst;
+	uint32_t afbc_tile_num;
+	uint32_t afbc_half_block_en;
+	uint32_t transform_offset;
+	bool dither_up;
+	bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X;
+	bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y;
+	bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270;
+	bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
+	struct rockchip_gem_object *rk_obj;
+	unsigned long offset;
+	bool afbc_en;
+	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
+
+	/*
+	 * can't update plane when vop2 is disabled.
+	 */
+	if (WARN_ON(!crtc))
+		return;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	if (!pstate->visible) {
+		vop2_plane_atomic_disable(plane, state);
+		return;
+	}
+
+	/*
+	 * This means this window is moved from another vp
+	 * so the VOP2_PORT_SEL register is changed and
+	 * take effect by vop2_wait_for_port_mux_done
+	 * in this commit. so we can continue configure
+	 * the window and report vsync
+	 */
+	if (win->old_vp_mask != win->vp_mask) {
+		win->old_vp_mask = win->vp_mask;
+		vp->skip_vsync = false;
+	}
+
+	afbc_en = rockchip_afbc(plane, fb->modifier);
+
+	offset = (src->x1 >> 16) * fb->format->cpp[0];
+
+	/*
+	 * AFBC HDR_PTR must set to the zero offset of the framebuffer.
+	 */
+	if (afbc_en)
+		offset = 0;
+	else if (pstate->rotation & DRM_MODE_REFLECT_Y)
+		offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
+	else
+		offset += (src->y1 >> 16) * fb->pitches[0];
+
+	rk_obj = to_rockchip_obj(fb->obj[0]);
+
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	if (fb->format->is_yuv) {
+		int hsub = fb->format->hsub;
+		int vsub = fb->format->vsub;
+
+		offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
+		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
+
+		if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en)
+			offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2)  / vsub;
+
+		rk_obj = to_rockchip_obj(fb->obj[0]);
+		uv_mst = rk_obj->dma_addr + offset + fb->offsets[1];
+	}
+
+	actual_w = drm_rect_width(src) >> 16;
+	actual_h = drm_rect_height(src) >> 16;
+	dsp_w = drm_rect_width(dest);
+
+	if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
+			  vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
+		dsp_w = adjusted_mode->hdisplay - dest->x1;
+		if (dsp_w < 4)
+			dsp_w = 4;
+		actual_w = dsp_w * actual_w / drm_rect_width(dest);
+	}
+
+	dsp_h = drm_rect_height(dest);
+
+	if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
+			  vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
+		dsp_h = adjusted_mode->vdisplay - dest->y1;
+		if (dsp_h < 4)
+			dsp_h = 4;
+		actual_h = dsp_h * actual_h / drm_rect_height(dest);
+	}
+
+	/*
+	 * This is workaround solution for IC design:
+	 * esmart can't support scale down when actual_w % 16 == 1.
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
+			drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->data->name, actual_w);
+			actual_w -= 1;
+		}
+	}
+
+	if (afbc_en && actual_w % 4) {
+		drm_err(vop2->drm, "vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
+			  vp->id, win->data->name, actual_w);
+		actual_w = ALIGN_DOWN(actual_w, 4);
+	}
+
+	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
+	dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
+
+	format = vop2_convert_format(fb->format->format);
+
+	spin_lock(&vop2->reg_lock);
+	drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
+		      vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
+		      dest->x1, dest->y1,
+		      &fb->format->format,
+		      afbc_en ? "AFBC" : "", &yrgb_mst);
+
+	if (afbc_en) {
+		uint32_t stride;
+
+		/* the afbc superblock is 16 x 16 */
+		afbc_format = vop2_convert_afbc_format(fb->format->format);
+
+		/* Enable color transform for YTR */
+		if (fb->modifier & AFBC_FORMAT_MOD_YTR)
+			afbc_format |= (1 << 4);
+
+		afbc_tile_num = ALIGN(actual_w, 16) >> 4;
+
+		/*
+		 * AFBC pic_vir_width is count by pixel, this is different
+		 * with WIN_VIR_STRIDE.
+		 */
+		stride = (fb->pitches[0] << 3) / bpp;
+		if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270))
+			drm_err(vop2->drm, "vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n",
+				  vp->id, win->data->name, stride, pstate->rotation);
+
+		rb_swap = vop2_afbc_rb_swap(fb->format->format);
+		uv_swap = vop2_afbc_uv_swap(fb->format->format);
+		/*
+		 * This is a workaround for crazy IC design, Cluster
+		 * and Esmart/Smart use different format configuration map:
+		 * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
+		 *
+		 * This is one thing we can make the convert simple:
+		 * AFBCD decode all the YUV data to YUV444. So we just
+		 * set all the yuv 10 bit to YUV444_10.
+		 */
+		if (fb->format->is_yuv && (bpp == 10))
+			format = VOP2_CLUSTER_YUV444_10;
+
+		afbc_half_block_en = vop2_afbc_half_block_enable(pstate);
+		transform_offset = vop2_afbc_transform_offset(pstate, afbc_half_block_en);
+		if (vop2_cluster_window(win))
+			vop2_win_write(win, &win->regs->cluster->afbc_enable, 1);
+		vop2_win_write(win, &win->regs->afbc->format, afbc_format);
+		vop2_win_write(win, &win->regs->afbc->rb_swap, rb_swap);
+		vop2_win_write(win, &win->regs->afbc->uv_swap, uv_swap);
+		vop2_win_write(win, &win->regs->afbc->auto_gating_en, 0);
+		vop2_win_write(win, &win->regs->afbc->block_split_en, 0);
+		vop2_win_write(win, &win->regs->afbc->half_block_en, afbc_half_block_en);
+		vop2_win_write(win, &win->regs->afbc->hdr_ptr, yrgb_mst);
+		vop2_win_write(win, &win->regs->afbc->pic_size, act_info);
+		vop2_win_write(win, &win->regs->afbc->transform_offset, transform_offset);
+		vop2_win_write(win, &win->regs->afbc->pic_offset, ((src->x1 >> 16) | src->y1));
+		vop2_win_write(win, &win->regs->afbc->dsp_offset, (dest->x1 | (dest->y1 << 16)));
+		vop2_win_write(win, &win->regs->afbc->pic_vir_width, stride);
+		vop2_win_write(win, &win->regs->afbc->tile_num, afbc_tile_num);
+		vop2_win_write(win, &win->regs->afbc->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->afbc->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->afbc->rotate_270, rotate_270);
+		vop2_win_write(win, &win->regs->afbc->rotate_90, rotate_90);
+	} else {
+		if (win->regs->afbc)
+			vop2_win_write(win, &win->regs->afbc->enable, 0);
+		vop2_win_write(win, &win->regs->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
+	}
+
+	if (rotate_90 || rotate_270) {
+		act_info = swahw32(act_info);
+		actual_w = drm_rect_height(src) >> 16;
+		actual_h = drm_rect_width(src) >> 16;
+	}
+
+	vop2_win_write(win, &win->regs->format, format);
+	vop2_win_write(win, &win->regs->yrgb_mst, yrgb_mst);
+
+	rb_swap = vop2_win_rb_swap(fb->format->format);
+	uv_swap = vop2_win_uv_swap(fb->format->format);
+	vop2_win_write(win, &win->regs->rb_swap, rb_swap);
+	vop2_win_write(win, &win->regs->uv_swap, uv_swap);
+
+	if (fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->uv_vir, DIV_ROUND_UP(fb->pitches[1], 4));
+		vop2_win_write(win, &win->regs->uv_mst, uv_mst);
+	}
+
+	vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format);
+	vop2_plane_setup_color_key(plane, 0);
+	vop2_win_write(win, &win->regs->act_info, act_info);
+	vop2_win_write(win, &win->regs->dsp_info, dsp_info);
+	vop2_win_write(win, &win->regs->dsp_st, dest->y1 << 16 | (dest->x1 & 0xffff));
+
+	vop2_setup_csc_mode(vp, win, pstate);
+
+	dither_up = vop2_win_dither_up(fb->format->format);
+	vop2_win_write(win, &win->regs->dither_up, dither_up);
+
+	vop2_win_write(win, &win->regs->enable, 1);
+
+	if (vop2_cluster_window(win)) {
+		int lb_mode = vop2_get_cluster_lb_mode(win, pstate);
+
+		vop2_win_write(win, &win->regs->cluster->lb_mode, lb_mode);
+		vop2_win_write(win, &win->regs->cluster->enable, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120 ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		vop2_win_write(win, &win->regs->yuv_clip, 1);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
+	.atomic_check = vop2_plane_atomic_check,
+	.atomic_update = vop2_plane_atomic_update,
+	.atomic_disable = vop2_plane_atomic_disable,
+};
+
+static const struct drm_plane_funcs vop2_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.format_mod_supported = rockchip_vop2_mod_supported,
+};
+
+static int vop2_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return -EPERM;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, FS_FIELD_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	return 0;
+}
+
+static void vop2_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adj_mode)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		adj_mode->crtc_clock *= 2;
+
+	adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
+							   adj_mode->crtc_clock * 1000), 1000);
+
+	return true;
+}
+
+static void vop2_dither_setup(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+
+	switch (vcstate->bus_format) {
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB565);
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB666);
+		break;
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 1);
+		break;
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	case MEDIA_BUS_FMT_SRGB888_3X8:
+	case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	default:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	}
+
+	vop2_write(vop2, &vp->regs->pre_dither_down_en,
+		       vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA ? 0 : 1);
+	vop2_write(vop2, &vp->regs->dither_down_sel, DITHER_DOWN_ALLEGRO);
+}
+
+static void vop2_post_config(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate =
+			to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint32_t left_margin = 100, right_margin = 100, top_margin = 100, bottom_margin = 100;
+	uint16_t hsize = hdisplay * (left_margin + right_margin) / 200;
+	uint16_t vsize = vdisplay * (top_margin + bottom_margin) / 200;
+	uint16_t hact_end, vact_end;
+	uint32_t val;
+
+	vsize = rounddown(vsize, 2);
+	hsize = rounddown(hsize, 2);
+	hact_st += hdisplay * (100 - left_margin) / 200;
+	hact_end = hact_st + hsize;
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hpost_st_end, val);
+	vact_st += vdisplay * (100 - top_margin) / 200;
+	vact_end = vact_st + vsize;
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vpost_st_end, val);
+	val = scl_cal_scale2(vdisplay, vsize) << 16;
+	val |= scl_cal_scale2(hdisplay, hsize);
+	vop2_write(vop2, &vp->regs->post_scl_factor, val);
+
+#define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
+#define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
+	vop2_write(vop2, &vp->regs->post_scl_ctrl,
+		       POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
+		       POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vsize;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vpost_st_end_f1, val);
+	}
+	vop2_write(vop2, &vp->regs->post_dsp_out_r2y,
+		       is_yuv_output(vcstate->bus_format));
+}
+
+/*
+ * if adjusted mode update, return true, else return false
+ */
+static bool vop2_crtc_mode_update(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	uint32_t htotal_sync = htotal << 16 | hsync_len;
+	uint32_t hactive_st_end = hact_st << 16 | hact_end;
+	uint32_t vtotal_sync = vtotal << 16 | vsync_len;
+	uint32_t vactive_st_end = vact_st << 16 | vact_end;
+	uint32_t crtc_clock = mode->crtc_clock * 100;
+
+	if (htotal_sync != vop2_read(vop2, &vp->regs->htotal_pw) ||
+	    hactive_st_end != vop2_read(vop2, &vp->regs->hact_st_end) ||
+	    vtotal_sync != vop2_read(vop2, &vp->regs->vtotal_pw) ||
+	    vactive_st_end != vop2_read(vop2, &vp->regs->vact_st_end) ||
+	    crtc_clock != clk_get_rate(vp->dclk))
+		return true;
+
+	return false;
+}
+
+static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	uint8_t out_mode;
+	bool dclk_inv, yc_swap;
+	int act_end;
+	uint32_t val;
+	int ret;
+
+	vop2_lock(vop2);
+
+	drm_info(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d, output 0x%08x %s %s\n",
+		     hdisplay, vdisplay, interlaced ? "i" : "p",
+		     drm_mode_vrefresh(mode), vcstate->output_type, vp->id,
+		     vcstate->output_if,
+		     vcstate->output_if & VOP_OUTPUT_IF_MIPI0 ? "MIPI0" : "",
+		     vcstate->output_if & VOP_OUTPUT_IF_HDMI0 ? "HDMI0" : ""
+		);
+
+	ret = clk_prepare_enable(vp->dclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n",
+			      vp->id, ret);
+		return;
+	}
+
+	if (!vop2->enable_count)
+		vop2_enable(vop2);
+
+	vop2->enable_count++;
+
+	vop2_debug_irq_enable(vp);
+
+	if (vop2_crtc_mode_update(vp))
+		vop2_disable_all_planes_for_crtc(vp);
+
+	dclk_inv = (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
+	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
+	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_RGB) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_dclk_inv, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt1120_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT656) {
+		vop2_write(vop2, &vop2->data->ctrl->bt656_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt656_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt656_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS0) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS1) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
+	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_mode, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
+		vop2_write(vop2, &vp->regs->mipi_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vp->regs->mipi_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
+		vop2_write(vop2, &vop2->data->ctrl->edp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) {
+		vop2_write(vop2, &vop2->data->ctrl->edp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP0) {
+		vop2_write(vop2, &vop2->data->ctrl->dp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP1) {
+		vop2_write(vop2, &vop2->data->ctrl->dp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
+	     !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		out_mode = ROCKCHIP_OUT_MODE_P888;
+	else
+		out_mode = vcstate->output_mode;
+
+	vop2_write(vop2, &vp->regs->out_mode, out_mode);
+
+	if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
+		vop2_write(vop2, &vp->regs->dsp_data_swap, DSP_RB_SWAP);
+	else
+		vop2_write(vop2, &vp->regs->dsp_data_swap, 0);
+
+	vop2_dither_setup(crtc);
+
+	vop2_write(vop2, &vp->regs->htotal_pw, (htotal << 16) | hsync_len);
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hact_st_end, val);
+
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vact_st_end, val);
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vdisplay;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vact_st_end_f1, val);
+
+		val = vtotal << 16 | (vtotal + vsync_len);
+		vop2_write(vop2, &vp->regs->vs_st_end_f1, val);
+		vop2_write(vop2, &vp->regs->dsp_interlace, 1);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 1);
+		vop2_write(vop2, &vp->regs->p2i_en, 1);
+		vtotal += vtotal + 1;
+		act_end = vact_end_f1;
+	} else {
+		vop2_write(vop2, &vp->regs->dsp_interlace, 0);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 0);
+		vop2_write(vop2, &vp->regs->p2i_en, 0);
+		act_end = vact_end;
+	}
+
+	vop2_write(vop2, &intr->line_flag_num[0], act_end);
+	vop2_write(vop2, &intr->line_flag_num[1],
+		     act_end - us_to_vertical_line(mode, 0));
+
+	vop2_write(vop2, &vp->regs->vtotal_pw, vtotal << 16 | vsync_len);
+
+	vop2_write(vop2, &vp->regs->core_dclk_div, !!(mode->flags & DRM_MODE_FLAG_DBLCLK));
+	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
+		vop2_write(vop2, &vp->regs->dclk_div2, 1);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 1);
+	} else {
+		vop2_write(vop2, &vp->regs->dclk_div2, 0);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 0);
+	}
+
+	clk_set_rate(vp->dclk, mode->crtc_clock * 1000);
+
+	vop2_post_config(crtc);
+
+	vop2_cfg_done(vp);
+
+	/*
+	 * when clear standby bits, it will take effect immediately,
+	 * This means the vp will start scan out immediately with
+	 * the timing it been configured before.
+	 * So we must make sure release standby after the display
+	 * timing is correctly configured.
+	 * This is important when switch resolution, such as
+	 * 4K-->720P:
+	 * if we release standby before 720P timing is configured,
+	 * the VP will start scan out immediately with 4K timing,
+	 * when we switch dclk to 74.25MHZ, VP timing is still 4K,
+	 * so VP scan out with 4K timing at 74.25MHZ dclk, this is
+	 * very slow, than this will trigger vblank timeout.
+	 *
+	 */
+	vop2_write(vop2, &vp->regs->standby, 0);
+
+	drm_crtc_vblank_on(crtc);
+
+	vop2_unlock(vop2);
+}
+
+static int vop2_zpos_cmp(const void *a, const void *b)
+{
+	struct vop2_zpos *pa = (struct vop2_zpos *)a;
+	struct vop2_zpos *pb = (struct vop2_zpos *)b;
+
+	if (pa->zpos != pb->zpos)
+		return pa->zpos - pb->zpos;
+	else
+		return pa->plane->base.id - pb->plane->base.id;
+}
+
+static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+
+		if (abs(main_win->base.state->zpos - win->base.state->zpos) != 1) {
+			drm_err(vop2->drm, "vp%d Cluster%d win0[zpos:%d] must next to win1[zpos:%d]\n",
+				  vp->id, main_win->data->phys_id,
+				  main_win->base.state->zpos, win->base.state->zpos);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static bool is_opaque(uint16_t alpha)
+{
+	return (alpha >> 8) == 0xff;
+}
+
+static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
+			     struct vop2_alpha *alpha)
+{
+	int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
+	int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
+	int src_color_mode = alpha_config->src_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+	int dst_color_mode = alpha_config->dst_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+
+	alpha->src_color_ctrl.val = 0;
+	alpha->dst_color_ctrl.val = 0;
+	alpha->src_alpha_ctrl.val = 0;
+	alpha->dst_alpha_ctrl.val = 0;
+
+	if (!alpha_config->src_pixel_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+
+	alpha->src_color_ctrl.bits.alpha_en = 1;
+
+	if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	} else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
+	} else {
+		alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	}
+	alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
+	alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+
+	alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
+	alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
+	alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+
+	alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
+	alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
+
+	alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+	alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
+	alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+}
+
+static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, uint8_t port_id)
+{
+	struct vop2_video_port *vp;
+	int used_layer = 0;
+	int i;
+
+	for (i = 0; i < port_id; i++) {
+		vp = &vop2->vps[i];
+		used_layer += hweight32(vp->win_mask);
+	}
+
+	return used_layer;
+}
+
+/*
+ * src: top layer
+ * dst: bottom layer.
+ * Cluster mixer default use win1 as top layer
+ */
+static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_cluster *cluster)
+{
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->cluster0_src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->cluster0_dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->cluster0_src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->cluster0_dst_alpha_ctrl.offset;
+	uint32_t offset = (cluster->main->data->phys_id * 0x10);
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *main_win = cluster->main;
+	struct vop2_win *sub_win = cluster->sub;
+	struct drm_plane *main_plane;
+	struct drm_plane_state *top_win_pstate;
+	struct drm_plane_state *bottom_win_pstate;
+	bool src_pixel_alpha_en = false;
+	uint16_t src_glb_alpha_val, dst_glb_alpha_val;
+	bool premulti_en = false;
+	bool swap = false;
+
+	if (!sub_win) {
+		/* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
+		top_win_pstate = NULL;
+		bottom_win_pstate = main_win->base.state;
+		src_glb_alpha_val = 0;
+		dst_glb_alpha_val = main_win->base.state->alpha;
+	} else {
+		if (main_win->base.state->zpos > sub_win->base.state->zpos) {
+			swap = 1;
+			top_win_pstate = main_plane->state;
+			bottom_win_pstate = sub_win->base.state;
+			src_glb_alpha_val = main_win->base.state->alpha;
+			dst_glb_alpha_val = sub_win->base.state->alpha;
+		} else {
+			swap = 0;
+			top_win_pstate = sub_win->base.state;
+			bottom_win_pstate = main_plane->state;
+			src_glb_alpha_val = sub_win->base.state->alpha;
+			dst_glb_alpha_val = main_win->base.state->alpha;
+		}
+
+		if (!top_win_pstate->fb)
+			return;
+
+		if (top_win_pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = true;
+		else
+			premulti_en = false;
+
+		src_pixel_alpha_en = is_alpha_support(top_win_pstate->fb->format->format);
+	}
+
+	if (!bottom_win_pstate->fb)
+		return;
+
+	alpha_config.src_premulti_en = premulti_en;
+	alpha_config.dst_premulti_en = false;
+	alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	alpha_config.src_glb_alpha_value = src_glb_alpha_val;
+	alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	alpha.src_color_ctrl.bits.src_dst_swap = swap;
+	vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+	vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+	vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+	vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+}
+
+static void vop2_setup_alpha(struct vop2_video_port *vp,
+			     const struct vop2_zpos *vop2_zpos, int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->dst_alpha_ctrl.offset;
+	const struct vop2_zpos *zpos;
+	struct drm_framebuffer *fb;
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *win;
+	struct drm_plane *plane;
+	int pixel_alpha_en;
+	int premulti_en;
+	int mixer_id;
+	uint32_t offset;
+	int i;
+	bool bottom_layer_alpha_en = false;
+	uint32_t dst_global_alpha = 0xffff;
+
+	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (plane->state->zpos == 0 && !is_opaque(plane->state->alpha) &&
+		    !vop2_cluster_window(win)) {
+			/*
+			 * If bottom layer have global alpha effect [except cluster layer,
+			 * because cluster have deal with bottom layer global alpha value
+			 * at cluster mix], bottom layer mix need deal with global alpha.
+			 */
+			bottom_layer_alpha_en = true;
+			dst_global_alpha = plane->state->alpha;
+			break;
+		}
+	}
+
+	mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	for (i = 1; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		fb = plane->state->fb;
+		if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = 1;
+		else
+			premulti_en = 0;
+		pixel_alpha_en = is_alpha_support(fb->format->format);
+
+		alpha_config.src_premulti_en = premulti_en;
+		if (bottom_layer_alpha_en && i == 1) {/* Cd = Cs + (1 - As) * Cd * Agd */
+			alpha_config.dst_premulti_en = false;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = dst_global_alpha;
+		} else if (vop2_cluster_window(win)) {/* Mix output data only have pixel alpha */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = true;
+			alpha_config.src_glb_alpha_value = 0xffff;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		} else {/* Cd = Cs + (1 - As) * Cd */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		}
+		vop2_parse_alpha(&alpha_config, &alpha);
+
+		offset = (mixer_id + i - 1) * 0x10;
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+
+		if (i == 1) {
+			if (bottom_layer_alpha_en) {
+				/* Transfer pixel alpha to hdr mix */
+				alpha_config.src_premulti_en = premulti_en;
+				alpha_config.dst_premulti_en = true;
+				alpha_config.src_pixel_alpha_en = true;
+				alpha_config.src_glb_alpha_value = 0xffff;
+				alpha_config.dst_glb_alpha_value = 0xffff;
+				vop2_parse_alpha(&alpha_config, &alpha);
+
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl,
+					       alpha.src_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_color_ctrl,
+					       alpha.dst_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_src_alpha_ctrl,
+					       alpha.src_alpha_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_alpha_ctrl,
+					       alpha.dst_alpha_ctrl.val);
+			} else {
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl, 0);
+			}
+		}
+	}
+
+	/* Transfer pixel alpha value to next mix */
+	alpha_config.src_premulti_en = true;
+	alpha_config.dst_premulti_en = true;
+	alpha_config.src_pixel_alpha_en = false;
+	alpha_config.src_glb_alpha_value = 0xffff;
+	alpha_config.dst_glb_alpha_value = 0xffff;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	for (; i < hweight32(vp->win_mask); i++) {
+		offset = (mixer_id + i - 1) * 0x10;
+
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+	}
+}
+
+static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp,
+					  const struct vop2_zpos *vop2_zpos,
+					  int nr_layers)
+{
+	struct vop2_video_port *vpt;
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_zpos *zpos;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint16_t port_mux_cfg = 0;
+	uint8_t port_mux;
+	uint8_t used_layers = 0;
+	int i, nlayer;
+
+	for (i = 0; i < vop2_data->nr_vps - 1; i++) {
+		vpt = &vop2->vps[i];
+		used_layers += hweight32(vpt->win_mask);
+
+		if (used_layers == 0)
+			port_mux = 8;
+		else
+			port_mux = used_layers - 1;
+
+		port_mux_cfg |= port_mux << (vpt->id * 4);
+
+		if (port_mux > vop2_data->nr_mixers)
+			vpt->bg_ovl_dly = 0;
+		else
+			vpt->bg_ovl_dly = (vop2_data->nr_mixers - port_mux) << 1;
+	}
+
+	if (vop2_data->nr_vps >= 1)
+		port_mux_cfg |= 7 << (4 * (vop2_data->nr_vps - 1));
+
+	nlayer = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		int j;
+
+		vpt = &vop2->vps[i];
+
+		for (j = 0; j < vpt->nr_layers; j++) {
+			layer = &vop2->layers[nlayer];
+			zpos = &vpt->zpos[j];
+			win = zpos->win;
+
+			vop2_write(vop2, &vop2->data->ctrl->win_vp_id[win->data->phys_id], vpt->id);
+			vop2_write(vop2, &layer->regs->layer_sel, win->data->layer_sel_id);
+			nlayer++;
+		}
+	}
+
+	for (; nlayer < vop2_data->nr_layers; nlayer++) {
+		layer = &vop2->layers[nlayer];
+
+		vop2_write(vop2, &layer->regs->layer_sel, 5);
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->ovl_cfg_done_port, vp->id);
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 0);
+
+	spin_lock(&vop2->reg_lock);
+	if (vop2->port_mux_cfg != port_mux_cfg) {
+		vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg, port_mux_cfg);
+		vp->skip_vsync = true;
+		vop2_cfg_done(vp);
+		vop2->port_mux_cfg = port_mux_cfg;
+		vop2_wait_for_port_mux_done(vop2);
+	}
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * HDR window is fixed(not move in the overlay path with port_mux change)
+ * and is the slowest window. And the bg is the fastest. So other windows
+ * and bg need to add delay number to keep align with the slowest window.
+ * The delay number list in the trm is a relative value for port_mux set at
+ * last level.
+ */
+static void vop2_setup_dly_for_vp(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	uint16_t hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+	uint16_t hdisplay = adjusted_mode->crtc_hdisplay;
+	uint32_t bg_dly = vp_data->pre_scan_max_dly[0];
+	uint32_t pre_scan_dly;
+
+	bg_dly = vp_data->pre_scan_max_dly[3];
+	bg_dly -= vp->bg_ovl_dly;
+
+	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
+	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
+	vop2_write(vop2, &vp->regs->bg_dly, bg_dly);
+	vop2_write(vop2, &vp->regs->pre_scan_htiming, pre_scan_dly);
+}
+
+static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
+				      int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_zpos *zpos;
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	uint32_t dly;
+	int i = 0;
+
+	for (i = 0; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
+
+		if (vop2_cluster_window(win))
+			dly |= dly << 8;
+
+		vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
+	}
+
+}
+static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	struct vop2_zpos *vop2_zpos = vp->zpos;
+	struct vop2_cluster cluster;
+	uint8_t nr_layers = 0;
+
+	/* Process cluster sub windows overlay. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		win->two_win_mode = false;
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+		cluster.main = main_win;
+		cluster.sub = win;
+		win->two_win_mode = true;
+		main_win->two_win_mode = true;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+
+	vp->win_mask = 0;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		/*
+		 * Sub win of a cluster will be handled by pre overlay module automatically
+		 * win in multi area share the same overlay zorder with it's parent.
+		 */
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+		vp->win_mask |=  BIT(win->data->phys_id);
+		win->vp_mask = BIT(vp->id);
+		vop2_zpos[nr_layers].win = win;
+		vop2_zpos[nr_layers].zpos = plane->state->zpos;
+		vop2_zpos[nr_layers].plane = plane;
+		nr_layers++;
+		drm_dbg(vop2->drm, "%s active zpos:%d for vp%d\n",
+			     win->data->name, plane->state->zpos, vp->id);
+	}
+
+	vp->nr_layers = nr_layers;
+
+	drm_dbg(vop2->drm, "vp%d: %d windows, active layers %d\n",
+		      vp->id, hweight32(vp->win_mask), nr_layers);
+	if (nr_layers) {
+		sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
+
+		vop2_setup_layer_mixer_for_vp(vp, vop2_zpos, nr_layers);
+		vop2_setup_alpha(vp, vop2_zpos, nr_layers);
+		vop2_setup_dly_for_vp(vp);
+		vop2_setup_dly_for_window(vp, vop2_zpos, nr_layers);
+	}
+
+	/* The pre alpha overlay of Cluster still need process in one win mode. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_MAIN))
+			continue;
+		if (win->two_win_mode)
+			continue;
+		cluster.main = win;
+		cluster.sub = NULL;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+}
+
+static void vop2_cfg_update(struct drm_crtc *crtc,
+			    struct drm_crtc_state *old_crtc_state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t val;
+	bool yuv_overlay = is_yuv_output(vcstate->bus_format);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->overlay_mode, yuv_overlay);
+
+	if (yuv_overlay)
+		val = 0x20010200;
+	else
+		val = 0;
+
+	vop2_write(vop2, &vp->regs->dsp_background, val);
+
+	vop2_post_config(crtc);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *old_cstate = drm_atomic_get_old_crtc_state(state, crtc);
+	struct drm_atomic_state *old_state = old_cstate->state;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_plane_state *old_pstate;
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	unsigned long flags;
+	int i;
+
+	vop2_cfg_update(crtc, old_cstate);
+
+	if (crtc->state->color_mgmt_changed || crtc->state->active_changed) {
+		if (crtc->state->gamma_lut)
+			vop2_crtc_load_lut(crtc, crtc->state->gamma_lut->data);
+	} else {
+		vop2_write(vop2, &vp->regs->cubic_lut_update_en, 0);
+	}
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	vop2_cfg_done(vp);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	/*
+	 * There is a (rather unlikely) possibility that a vblank interrupt
+	 * fired before we set the cfg_done bit. To avoid spuriously
+	 * signalling flip completion we need to wait for it to finish.
+	 */
+	vop2_wait_for_irq_handler(crtc);
+
+	/*
+	 * move here is to make sure current fs call function is complete,
+	 * so when layer_sel_update is true, we can skip current vblank correctly.
+	 */
+	vp->layer_sel_update = false;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		WARN_ON(vp->event);
+
+		vp->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+
+	for_each_old_plane_in_state(old_state, plane, old_pstate, i) {
+		if (!old_pstate->fb)
+			continue;
+
+		if (old_pstate->fb == plane->state->fb)
+			continue;
+
+		drm_framebuffer_get(old_pstate->fb);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		drm_flip_work_queue(&vp->fb_unref_work, old_pstate->fb);
+		set_bit(VOP_PENDING_FB_UNREF, &vp->pending);
+	}
+}
+
+static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
+	.mode_fixup = vop2_crtc_mode_fixup,
+	.atomic_check = vop2_crtc_atomic_check,
+	.atomic_begin = vop2_crtc_atomic_begin,
+	.atomic_flush = vop2_crtc_atomic_flush,
+	.atomic_enable = vop2_crtc_atomic_enable,
+	.atomic_disable = vop2_crtc_atomic_disable,
+};
+
+static void vop2_crtc_reset(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+
+	if (crtc->state) {
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+		kfree(vcstate);
+	}
+
+	vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return;
+	crtc->state = &vcstate->base;
+	crtc->state->crtc = crtc;
+}
+
+static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate, *old_vcstate;
+
+	old_vcstate = to_rockchip_crtc_state(crtc->state);
+	vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
+
+	return &vcstate->base;
+}
+
+static void vop2_crtc_destroy_state(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
+
+	__drm_atomic_helper_crtc_destroy_state(&vcstate->base);
+	kfree(vcstate);
+}
+
+static const struct drm_crtc_funcs vop2_crtc_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.destroy = drm_crtc_cleanup,
+	.reset = vop2_crtc_reset,
+	.atomic_duplicate_state = vop2_crtc_duplicate_state,
+	.atomic_destroy_state = vop2_crtc_destroy_state,
+	.enable_vblank = vop2_crtc_enable_vblank,
+	.disable_vblank = vop2_crtc_disable_vblank,
+};
+
+static void vop2_fb_unref_worker(struct drm_flip_work *work, void *val)
+{
+	struct vop2_video_port *vp = container_of(work, struct vop2_video_port, fb_unref_work);
+	struct drm_framebuffer *fb = val;
+
+	drm_crtc_vblank_put(&vp->crtc);
+	drm_framebuffer_put(fb);
+}
+
+static void vop2_handle_vblank(struct vop2 *vop2, struct drm_crtc *crtc)
+{
+	struct drm_device *drm = vop2->drm;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	if (vp->event) {
+		drm_crtc_send_vblank_event(crtc, vp->event);
+		drm_crtc_vblank_put(crtc);
+		vp->event = NULL;
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+
+	if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vp->pending))
+		drm_flip_work_commit(&vp->fb_unref_work, system_unbound_wq);
+}
+
+static uint32_t vop2_read_and_clear_active_vp_irqs(struct vop2 *vop2, int vp_id)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	const struct vop_intr *intr;
+	int val;
+
+	vp_data = &vop2_data->vp[vp_id];
+	intr = vp_data->intr;
+	val = vop2_get_intr_type(vop2, intr, &intr->status, VOP2_INTR_MASK);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+	return val;
+}
+
+static irqreturn_t vop2_isr(int irq, void *data)
+{
+	struct vop2 *vop2 = data;
+	struct drm_crtc *crtc;
+	struct vop2_video_port *vp;
+	const struct vop2_data *vop2_data = vop2->data;
+	size_t vp_max = min_t(size_t, vop2_data->nr_vps, ROCKCHIP_MAX_CRTC);
+	size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM);
+	uint32_t vp_irqs[ROCKCHIP_MAX_CRTC];
+	uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM];
+	uint32_t active_irqs;
+	unsigned long flags;
+	int ret = IRQ_NONE;
+	int i;
+
+	/*
+	 * The irq is shared with the iommu. If the runtime-pm state of the
+	 * vop2-device is disabled the irq has to be targeted at the iommu.
+	 */
+	if (!pm_runtime_get_if_in_use(vop2->dev))
+		return IRQ_NONE;
+
+	/*
+	 * interrupt register has interrupt status, enable and clear bits, we
+	 * must hold irq_lock to avoid a race with enable/disable_vblank().
+	 */
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	for (i = 0; i < vp_max; i++)
+		vp_irqs[i] = vop2_read_and_clear_active_vp_irqs(vop2, i);
+	for (i = 0; i < axi_max; i++)
+		axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i);
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	for (i = 0; i < vp_max; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		active_irqs = vp_irqs[i];
+		if (active_irqs & DSP_HOLD_VALID_INTR) {
+			complete(&vp->dsp_hold_completion);
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & FS_FIELD_INTR) {
+			if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) {
+				drm_crtc_handle_vblank(crtc);
+				vop2_handle_vblank(vop2, crtc);
+			}
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & POST_BUF_EMPTY_INTR) {
+			drm_err_ratelimited(vop2->drm,
+					    "POST_BUF_EMPTY irq err at vp%d\n",
+					    vp->id);
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	for (i = 0; i < axi_max; i++) {
+		active_irqs = axi_irqs[i];
+
+		if (active_irqs & BUS_ERROR_INTR) {
+			drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n");
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	pm_runtime_put(vop2->dev);
+
+	return ret;
+}
+
+static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs)
+{
+	const struct vop2_win_data *win_data = win->data;
+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) |
+				  BIT(DRM_MODE_BLEND_COVERAGE);
+	int ret;
+
+	ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs,
+				       &vop2_plane_funcs, win_data->formats, win_data->nformats,
+				       win_data->format_modifiers, win_data->type, win_data->name);
+	if (ret) {
+		drm_err(vop2->drm, "failed to initialize plane %d\n", ret);
+		return ret;
+	}
+
+	drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs);
+
+	if (win->data->supported_rotations)
+		drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
+						   DRM_MODE_ROTATE_0 | win->data->supported_rotations);
+	drm_plane_create_alpha_property(&win->base);
+	drm_plane_create_blend_mode_property(&win->base, blend_caps);
+	drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop2->registered_num_wins - 1);
+
+	return 0;
+}
+
+static int vop2_gamma_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	struct vop2_video_port *vp;
+	struct drm_crtc *crtc;
+	int i = 0;
+	uint32_t lut_len = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		if (!crtc->dev)
+			continue;
+		vp_data = &vop2_data->vp[vp->id];
+		lut_len = vp_data->gamma_lut_len;
+		vp->gamma_lut_len = vp_data->gamma_lut_len;
+
+		drm_mode_crtc_set_gamma_size(crtc, lut_len);
+		drm_crtc_enable_color_mgmt(crtc, 0, false, lut_len);
+	}
+
+	return 0;
+}
+
+static int vop2_create_crtc(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	struct drm_device *drm = vop2->drm;
+	struct device *dev = vop2->dev;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct device_node *port;
+	struct vop2_win *win = NULL;
+	struct vop2_video_port *vp;
+	const struct vop2_video_port_data *vp_data;
+	uint32_t possible_crtcs;
+	int i, nvp = 0;
+	int ret;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+
+		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
+			if (nvp < vop2_data->nr_vps) {
+				vp = &vop2->vps[nvp];
+
+				possible_crtcs = BIT(vop2_data->vp[i].id);
+				vp->primary_plane = win;
+
+				nvp++;
+			} else {
+				/* change the unused primary window to overlay window */
+				win->type = DRM_PLANE_TYPE_OVERLAY;
+			}
+		}
+
+		if (win->type == DRM_PLANE_TYPE_OVERLAY)
+			possible_crtcs = (1 << vop2_data->nr_vps) - 1;
+		ret = vop2_plane_init(vop2, win, possible_crtcs);
+
+		if (ret) {
+			drm_err(vop2->drm, "failed to init plane %s: %d\n", win->data->name, ret);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		char dclk_name[9];
+
+		vp_data = &vop2_data->vp[i];
+		vp = &vop2->vps[i];
+		vp->vop2 = vop2;
+		vp->id = vp_data->id;
+		vp->regs = vp_data->regs;
+
+		vp->zpos = devm_kzalloc(vop2->dev, vop2->data->win_size * sizeof(*vp->zpos), GFP_KERNEL);
+		if (!vp->zpos)
+			return -ENOMEM;
+
+		snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
+		vp->dclk = devm_clk_get(vop2->dev, dclk_name);
+		if (IS_ERR(vp->dclk)) {
+			drm_err(vop2->drm, "failed to get %s\n", dclk_name);
+			return PTR_ERR(vp->dclk);
+		}
+
+		crtc = &vp->crtc;
+
+		port = of_graph_get_port_by_id(dev->of_node, i);
+		if (!port) {
+			drm_err(vop2->drm, "no port node found for video_port%d\n", i);
+			return -ENOENT;
+		}
+		crtc->port = port;
+
+		plane = &vp->primary_plane->base;
+
+		ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &vop2_crtc_funcs,
+						"video_port%d", vp->id);
+		if (ret) {
+			drm_err(vop2->drm, "crtc init for video_port%d failed\n", i);
+			return ret;
+		}
+
+		drm_crtc_helper_add(crtc, &vop2_crtc_helper_funcs);
+
+		drm_flip_work_init(&vp->fb_unref_work, "fb_unref", vop2_fb_unref_worker);
+
+		init_completion(&vp->dsp_hold_completion);
+		init_completion(&vp->line_flag_completion);
+	}
+
+	return 0;
+}
+
+static void vop2_destroy_crtc(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	of_node_put(crtc->port);
+
+	/*
+	 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
+	 * references the CRTC.
+	 */
+	drm_crtc_cleanup(crtc);
+	drm_flip_work_cleanup(&vp->fb_unref_work);
+}
+
+static int vop2_win_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_layer_data *layer_data;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint8_t plane_id = 0;
+	unsigned int i;
+
+	for (i = 0; i < vop2_data->win_size; i++) {
+		const struct vop2_win_data *win_data = &vop2_data->win[i];
+
+		win = &vop2->win[i];
+		win->data = win_data;
+		win->type = win_data->type;
+		win->regs = win_data->regs;
+		win->offset = win_data->base;
+		win->win_id = i;
+		win->plane_id = plane_id++;
+		win->zpos = i;
+		win->vop2 = vop2;
+	}
+
+	vop2->registered_num_wins = vop2_data->win_size;
+
+	for (i = 0; i < vop2_data->nr_layers; i++) {
+		layer = &vop2->layers[i];
+		layer_data = &vop2_data->layer[i];
+		layer->id = layer_data->id;
+		layer->regs = layer_data->regs;
+	}
+
+	return 0;
+}
+
+static int vop2_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct vop2_data *vop2_data;
+	struct drm_device *drm = data;
+	struct vop2 *vop2;
+	struct resource *res;
+	size_t alloc_size;
+	int ret;
+
+	vop2_data = of_device_get_match_data(dev);
+	if (!vop2_data)
+		return -ENODEV;
+
+	/* Allocate vop2 struct and its vop2_win array */
+	alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size;
+	vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
+	if (!vop2)
+		return -ENOMEM;
+
+	vop2->dev = dev;
+	vop2->data = vop2_data;
+	vop2->drm = drm;
+
+	dev_set_drvdata(dev, vop2);
+
+	ret = vop2_win_init(vop2);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	if (!res) {
+		drm_err(vop2->drm, "failed to get vop2 register byname\n");
+		return -EINVAL;
+	}
+	vop2->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vop2->regs))
+		return PTR_ERR(vop2->regs);
+	vop2->len = resource_size(res);
+
+	vop2->regsbak = devm_kzalloc(dev, vop2->len, GFP_KERNEL);
+	if (!vop2->regsbak)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut");
+	if (res) {
+		vop2->lut_regs = devm_ioremap_resource(dev, res);
+		if (IS_ERR(vop2->lut_regs))
+			return PTR_ERR(vop2->lut_regs);
+	}
+
+	vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+
+	vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop");
+	if (IS_ERR(vop2->hclk)) {
+		drm_err(vop2->drm, "failed to get hclk source\n");
+		return PTR_ERR(vop2->hclk);
+	}
+
+	vop2->aclk = devm_clk_get(vop2->dev, "aclk_vop");
+	if (IS_ERR(vop2->aclk)) {
+		drm_err(vop2->drm, "failed to get aclk source\n");
+		return PTR_ERR(vop2->aclk);
+	}
+
+	vop2->irq = platform_get_irq(pdev, 0);
+	if (vop2->irq < 0) {
+		drm_err(vop2->drm, "cannot find irq for vop2\n");
+		return vop2->irq;
+	}
+
+	spin_lock_init(&vop2->reg_lock);
+	spin_lock_init(&vop2->irq_lock);
+	mutex_init(&vop2->vop2_lock);
+
+	ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
+	if (ret)
+		return ret;
+
+	ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev);
+	if (ret) {
+		drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret);
+		return ret;
+	}
+
+	ret = vop2_create_crtc(vop2);
+	if (ret)
+		return ret;
+
+	ret = vop2_gamma_init(vop2);
+	if (ret)
+		return ret;
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static void vop2_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct vop2 *vop2 = dev_get_drvdata(dev);
+	struct drm_device *drm = vop2->drm;
+	struct list_head *plane_list = &drm->mode_config.plane_list;
+	struct list_head *crtc_list = &drm->mode_config.crtc_list;
+	struct drm_crtc *crtc, *tmpc;
+	struct drm_plane *plane, *tmpp;
+
+	rockchip_drm_dma_detach_device(vop2->drm, vop2->dev);
+
+	pm_runtime_disable(dev);
+
+	list_for_each_entry_safe(plane, tmpp, plane_list, head)
+		drm_plane_cleanup(plane);
+
+	list_for_each_entry_safe(crtc, tmpc, crtc_list, head)
+		vop2_destroy_crtc(crtc);
+}
+
+const struct component_ops vop2_component_ops = {
+	.bind = vop2_bind,
+	.unbind = vop2_unbind,
+};
+EXPORT_SYMBOL_GPL(vop2_component_ops);
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
new file mode 100644
index 0000000000000..669c7b6fd9eab
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -0,0 +1,916 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Rockchip Electronics Co.Ltd
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
+
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define _VOP_REG(off, _mask, _shift, _write_mask) \
+	{ \
+		.offset = off, \
+		.mask = _mask, \
+		.shift = _shift, \
+		.write_mask = _write_mask, \
+	}
+
+#define VOP_REG(off, _mask, _shift) \
+		_VOP_REG(off, _mask, _shift, false)
+
+#define VOP_REG_MASK(off, _mask, s) \
+		_VOP_REG(off, _mask, s, true)
+
+static const uint32_t formats_win_full_10bit[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+};
+
+static const uint32_t formats_win_full_10bit_yuyv[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_VYUY,
+};
+
+static const uint32_t formats_win_lite[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static const u32 formats_wb[] = {
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_NV12,
+};
+
+static const uint64_t format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const uint64_t format_modifiers_afbc[] = {
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const int rk3568_vop_axi_intrs[] = {
+	0,
+	BUS_ERROR_INTR,
+	0,
+	WB_UV_FIFO_FULL_INTR,
+	WB_YRGB_FIFO_FULL_INTR,
+	WB_COMPLETE_INTR,
+
+};
+
+static const struct vop_intr rk3568_vop_axi_intr[] = {
+	{
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS0_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS0_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS0_INT_CLR, 0xfe, 0),
+	}, {
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS1_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS1_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS1_INT_CLR, 0xfe, 0),
+	},
+};
+
+static const int rk3568_vop_intrs[] = {
+	FS_INTR,
+	FS_NEW_INTR,
+	LINE_FLAG_INTR,
+	LINE_FLAG1_INTR,
+	POST_BUF_EMPTY_INTR,
+	FS_FIELD_INTR,
+	DSP_HOLD_VALID_INTR,
+};
+
+static const struct vop_intr rk3568_vp0_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP0_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP0_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP0_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp1_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP1_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP1_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP1_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp2_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP2_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP2_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP2_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop2_wb_regs rk3568_vop_wb_regs = {
+	.enable = VOP_REG(RK3568_WB_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_WB_CTRL, 0x7, 1),
+	.dither_en = VOP_REG(RK3568_WB_CTRL, 0x1, 4),
+	.r2y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 5),
+	.scale_x_en = VOP_REG(RK3568_WB_CTRL, 0x1, 7),
+	.scale_y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 8),
+	.axi_yrgb_id = VOP_REG(RK3568_WB_CTRL, 0xff, 19),
+	.axi_uv_id = VOP_REG(RK3568_WB_CTRL, 0x1f, 27),
+	.scale_x_factor = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3fff, 16),
+	.yrgb_mst = VOP_REG(RK3568_WB_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_WB_CBR_MST, 0xffffffff, 0),
+	.vp_id = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 8),
+	.fifo_throd = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3ff, 0),
+};
+
+static const struct vop2_wb_data rk3568_vop_wb_data = {
+	.formats = formats_wb,
+	.nformats = ARRAY_SIZE(formats_wb),
+	.max_output = { 1920, 1080 },
+	.regs = &rk3568_vop_wb_regs,
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp0_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0),
+	.dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 0),
+	.out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP0_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP0_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP0_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP0_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP0_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP0_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 21),
+	.dsp_lut_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 28),
+	.hdr10_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 4),
+	.hdr_lut_update_en = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 0),
+	.hdr_lut_mode = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 1),
+	.hdr_lut_mst = VOP_REG(RK3568_HDR_LUT_MST, 0xffffffff, 0),
+	.sdr2hdr_eotf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 0),
+	.sdr2hdr_r2r_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 1),
+	.sdr2hdr_r2r_mode = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 2),
+	.sdr2hdr_oetf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 3),
+	.sdr2hdr_bypass_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 8),
+	.sdr2hdr_auto_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 9),
+	.sdr2hdr_path_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 5),
+	.hdr2sdr_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 0),
+	.hdr2sdr_bypass_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 8),
+	.hdr2sdr_auto_gating_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 9),
+	.hdr2sdr_src_min = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 0),
+	.hdr2sdr_src_max = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 16),
+	.hdr2sdr_normfaceetf = VOP_REG(RK3568_HDR2SDR_NORMFACEETF, 0x7ff, 0),
+	.hdr2sdr_dst_min = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 0),
+	.hdr2sdr_dst_max = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 16),
+	.hdr2sdr_normfacgamma = VOP_REG(RK3568_HDR2SDR_NORMFACCGAMMA, 0xffff, 0),
+	.hdr2sdr_eetf_oetf_y0_offset = RK3568_HDR_EETF_OETF_Y0,
+	.hdr2sdr_sat_y0_offset = RK3568_HDR_SAT_Y0,
+	.sdr2hdr_eotf_oetf_y0_offset = RK3568_HDR_EOTF_OETF_Y0,
+	.sdr2hdr_oetf_dx_pow1_offset = RK3568_HDR_OETF_DX_POW1,
+	.sdr2hdr_oetf_xn1_offset = RK3568_HDR_OETF_XN1,
+	.hdr_src_color_ctrl = VOP_REG(RK3568_HDR0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_dst_color_ctrl = VOP_REG(RK3568_HDR0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_src_alpha_ctrl = VOP_REG(RK3568_HDR0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.hdr_dst_alpha_ctrl = VOP_REG(RK3568_HDR0_DST_ALPHA_CTRL, 0xffffffff, 0),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP0_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP0_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP0_BCSH_COLOR_BAR, 0x1, 31),
+
+	.cubic_lut_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 0),
+	.cubic_lut_update_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 2),
+	.cubic_lut_mst = VOP_REG(RK3568_VP0_3D_LUT_MST, 0xffffffff, 0),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp1_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 1),
+	.dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 4),
+	.out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP1_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP1_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP1_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP1_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP1_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP1_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP1_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP1_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP1_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP1_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp2_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 2),
+	.dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 8),
+	.out_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP2_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP2_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP2_POST_SCL_CTRL, 0x3, 0),
+	.htotal_pw = VOP_REG(RK3568_VP2_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(RK3568_VP2_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP2_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP2_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP2_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP2_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP2_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
+	{
+		.id = 0,
+		.feature = VOP_FEATURE_OUTPUT_10BIT,
+		.gamma_lut_len = 1024,
+		.cubic_lut_len = 729, /* 9x9x9 */
+		.max_output = { 4096, 2304 },
+		.pre_scan_max_dly = { 69, 53, 53, 42 },
+		.intr = &rk3568_vp0_intr,
+		.regs = &rk3568_vop_vp0_regs,
+	}, {
+		.id = 1,
+		.gamma_lut_len = 1024,
+		.max_output = { 2048, 1536 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp1_intr,
+		.regs = &rk3568_vop_vp1_regs,
+	}, {
+		.id = 2,
+		.gamma_lut_len = 1024,
+		.max_output = { 1920, 1080 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp2_intr,
+		.regs = &rk3568_vop_vp2_regs,
+	},
+};
+
+const struct vop2_layer_regs rk3568_vop_layer0_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 0)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer1_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 4)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer2_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 8)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer3_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 12)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer4_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 16)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer5_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 20)
+};
+
+static const struct vop2_layer_data rk3568_vop_layers[] = {
+	{
+		.id = 0,
+		.regs = &rk3568_vop_layer0_regs,
+	}, {
+		.id = 1,
+		.regs = &rk3568_vop_layer1_regs,
+	}, {
+		.id = 2,
+		.regs = &rk3568_vop_layer2_regs,
+	}, {
+		.id = 3,
+		.regs = &rk3568_vop_layer3_regs,
+	}, {
+		.id = 4,
+		.regs = &rk3568_vop_layer4_regs,
+	}, {
+		.id = 5,
+		.regs = &rk3568_vop_layer5_regs,
+	},
+};
+
+static const struct vop2_cluster_regs rk3568_vop_cluster0 =  {
+	.afbc_enable = VOP_REG(RK3568_CLUSTER_CTRL, 0x1, 1),
+	.enable = VOP_REG(RK3568_CLUSTER_CTRL, 1, 0),
+	.lb_mode = VOP_REG(RK3568_CLUSTER_CTRL, 0xf, 4),
+};
+
+static const struct vop_afbc rk3568_cluster0_afbc = {
+	.format = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1f, 2),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 9),
+	.uv_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 10),
+	.auto_gating_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 0x1, 4),
+	.half_block_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 7),
+	.block_split_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 8),
+	.hdr_ptr = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0xffffffff, 0),
+	.pic_size = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0xffffffff, 0),
+	.pic_vir_width = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 0),
+	.tile_num = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 16),
+	.pic_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0xffffffff, 0),
+	.dsp_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0xffffffff, 0),
+	.transform_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0xffffffff, 0),
+	.rotate_90 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 0),
+	.rotate_270 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 1),
+	.xmirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 2),
+	.ymirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 3),
+};
+
+static const struct vop2_scl_regs rk3568_cluster0_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 16),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 14),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 12),
+	.bic_coe_sel = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 2),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 28),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 29),
+};
+
+static const struct vop2_scl_regs rk3568_esmart_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area1_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area2_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area3_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 11),
+};
+
+static const struct vop2_win_regs rk3568_cluster0_win_data = {
+	.scl = &rk3568_cluster0_win_scl,
+	.afbc = &rk3568_cluster0_afbc,
+	.cluster = &rk3568_vop_cluster0,
+	.enable = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 0),
+	.format = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1f, 1),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 14),
+	.dither_up = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 18),
+	.act_info = VOP_REG(RK3568_CLUSTER_WIN_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_CLUSTER_WIN_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_CLUSTER_WIN_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_CLUSTER_WIN_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_CLUSTER_WIN_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 19),
+	.yrgb_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 8),
+	.r2y_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 9),
+	.csc_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x3, 10),
+};
+
+static const struct vop2_win_regs rk3568_esmart_win_data = {
+	.scl = &rk3568_esmart_win_scl,
+	.enable = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1f, 1),
+	.dither_up = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 12),
+	.rb_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 14),
+	.uv_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 16),
+	.act_info = VOP_REG(RK3568_SMART_REGION0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_SMART_REGION0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_SMART_REGION0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_SMART_REGION0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_SMART_REGION0_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 17),
+	.yrgb_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 0),
+	.r2y_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 1),
+	.csc_mode = VOP_REG(RK3568_SMART_CTRL0, 0x3, 2),
+	.ymirror = VOP_REG(RK3568_SMART_CTRL1, 0x1, 31),
+	.color_key = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x3fffffff, 0),
+	.color_key_en = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x1, 31),
+};
+
+/*
+ * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
+ * Every cluster can work as 4K win or split into two win.
+ * All win in cluster support AFBCD.
+ *
+ * Every esmart win and smart win support 4 Multi-region.
+ *
+ * Scale filter mode:
+ *
+ * * Cluster:  bicubic for horizontal scale up, others use bilinear
+ * * ESmart:
+ *    * nearest-neighbor/bilinear/bicubic for scale up
+ *    * nearest-neighbor/bilinear/average for scale down
+ *
+ *
+ * @TODO describe the wind like cpu-map dt nodes;
+ */
+static const struct vop2_win_data rk3568_vop_win_data[] = {
+	{
+		.name = "Smart0-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART0,
+		.base = 0x1c00,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.layer_sel_id = 3,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Smart1-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART1,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.base = 0x1e00,
+		.layer_sel_id = 7,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart1-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1a00,
+		.layer_sel_id = 6,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart0-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1800,
+		.layer_sel_id = 2,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Cluster0-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1000,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 0,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN,
+	}, {
+		.name = "Cluster0-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1080,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB,
+	}, {
+		.name = "Cluster1-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.base = 0x1200,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 1,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_MIRROR,
+	}, {
+		.name = "Cluster1-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.base = 0x1280,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB | WIN_FEATURE_MIRROR,
+	},
+};
+
+static const struct vop_grf_ctrl rk3568_grf_ctrl = {
+	.grf_bt656_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 1),
+	.grf_bt1120_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 2),
+	.grf_dclk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 3),
+};
+
+static const struct vop2_ctrl rk3568_vop_ctrl = {
+	.cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15),
+	.wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14),
+	.auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31),
+	.ovl_cfg_done_port = VOP_REG(RK3568_OVL_CTRL, 0x3, 30),
+	.ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28),
+	.ovl_port_mux_cfg = VOP_REG(RK3568_OVL_PORT_SEL, 0xffff, 0),
+	.if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28),
+	.version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16),
+	.lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0),
+	.cluster0_src_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_dst_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_src_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.cluster0_dst_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.src_color_ctrl = VOP_REG(RK3568_MIX0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.dst_color_ctrl = VOP_REG(RK3568_MIX0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.src_alpha_ctrl = VOP_REG(RK3568_MIX0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.dst_alpha_ctrl = VOP_REG(RK3568_MIX0_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.rgb_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 0),
+	.hdmi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 1),
+	.edp0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 3),
+	.mipi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 4),
+	.mipi1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 20),
+	.lvds0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 5),
+	.lvds1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 24),
+	.bt1120_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 6),
+	.bt656_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 7),
+	.rgb_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 8),
+	.hdmi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 10),
+	.edp0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 14),
+	.mipi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 16),
+	.mipi1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 21),
+	.lvds0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 18),
+	.lvds1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 25),
+	.lvds_dual_en = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 0),
+	.lvds_dual_mode = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 1),
+	.lvds_dual_channel_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 2),
+	.bt656_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 5),
+	.bt1120_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 9),
+	.gamma_port_sel = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 0),
+	.lvds_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 0),
+	.lvds_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 3),
+	.hdmi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 4),
+	.hdmi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 7),
+	.edp_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x3, 12),
+	.edp_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 15),
+	.mipi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 16),
+	.mipi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 19),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 16),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 18),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 24),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 26),
+	.win_vp_id[ROCKCHIP_VOP2_SMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 28),
+	.win_vp_id[ROCKCHIP_VOP2_SMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 30),
+	.win_dly[0] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 0),
+	.win_dly[1] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 16),
+	.win_dly[2] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 0),
+	.win_dly[3] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 8),
+	.win_dly[4] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 16),
+	.win_dly[5] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 24),
+	.otp_en = VOP_REG(RK3568_OTP_WIN_EN, 0x1, 0),
+};
+
+static const struct vop2_data rk3568_vop = {
+	.nr_vps = 3,
+	.nr_mixers = 5,
+	.nr_gammas = 1,
+	.max_input = { 4096, 2304 },
+	.max_output = { 4096, 2304 },
+	.ctrl = &rk3568_vop_ctrl,
+	.grf_ctrl = &rk3568_grf_ctrl,
+	.axi_intr = rk3568_vop_axi_intr,
+	.nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr),
+	.vp = rk3568_vop_video_ports,
+	.wb = &rk3568_vop_wb_data,
+	.layer = rk3568_vop_layers,
+	.nr_layers = ARRAY_SIZE(rk3568_vop_layers),
+	.win = rk3568_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
+	.soc_id = 3568,
+};
+
+static const struct of_device_id vop2_dt_match[] = {
+	{
+		.compatible = "rockchip,rk3568-vop",
+		.data = &rk3568_vop
+	}, {
+	},
+};
+MODULE_DEVICE_TABLE(of, vop2_dt_match);
+
+static int vop2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	return component_add(dev, &vop2_component_ops);
+}
+
+static int vop2_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vop2_component_ops);
+
+	return 0;
+}
+
+struct platform_driver vop2_platform_driver = {
+	.probe = vop2_probe,
+	.remove = vop2_remove,
+	.driver = {
+		.name = "rockchip-vop2",
+		.of_match_table = of_match_ptr(vop2_dt_match),
+	},
+};
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 14:33   ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:33 UTC (permalink / raw)
  To: dri-devel
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
It replaces the VOP unit found in the older Rockchip SoCs.

This driver has been derived from the downstream Rockchip Kernel and
heavily modified:

- All nonstandard DRM properties have been removed
- dropped struct vop2_plane_state and pass around less data between
  functions
- Dropped all DRM_FORMAT_* not known on upstream
- rework register access to get rid of excessively used macros

The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
board. Overlay support is tested with the modetest utility. AFBC support
is still present in the driver, but currently untested due to the lack
of suitable image sources. Also the driver has been tested with weston
using pixman and (yet to be upstreamed) panfrost driver support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/rockchip/Kconfig             |    6 +
 drivers/gpu/drm/rockchip/Makefile            |    1 +
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c  |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h  |   22 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h  |  774 ++++
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 3611 ++++++++++++++++++
 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c |  916 +++++
 8 files changed, 5331 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
 create mode 100644 drivers/gpu/drm/rockchip/rockchip_vop2_reg.c

diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
index a1c4158259099..b841f4873f7f3 100644
--- a/drivers/gpu/drm/rockchip/Kconfig
+++ b/drivers/gpu/drm/rockchip/Kconfig
@@ -27,6 +27,12 @@ config ROCKCHIP_VOP
 	  This selects support for the VOP driver. You should enable it
 	  on all older SoCs up to RK3399.
 
+config ROCKCHIP_VOP2
+	bool "Rockchip VOP2 driver"
+	help
+	  This selects support for the VOP2 driver. You should enable it
+	  on all newer SoCs beginning form RK3568.
+
 config ROCKCHIP_ANALOGIX_DP
 	bool "Rockchip specific extensions for Analogix DP driver"
 	depends on ROCKCHIP_VOP
diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
index cd6e7bb5ce9c5..29848caef5c21 100644
--- a/drivers/gpu/drm/rockchip/Makefile
+++ b/drivers/gpu/drm/rockchip/Makefile
@@ -7,6 +7,7 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
 		rockchip_drm_gem.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+rockchipdrm-$(CONFIG_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
 rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index b8fe56c89cdc9..f6296b8a123ab 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -324,6 +324,7 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
 
 	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
 	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+	s->output_if = VOP_OUTPUT_IF_HDMI0;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 64fa5fd62c01a..2bd9acb265e5a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -474,6 +474,7 @@ static int __init rockchip_drm_init(void)
 
 	num_rockchip_sub_drivers = 0;
 	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
+	ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
 				CONFIG_ROCKCHIP_LVDS);
 	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index aa0909e8edf93..cdd2c2847441a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,12 +18,26 @@
 
 #define ROCKCHIP_MAX_FB_BUFFER	3
 #define ROCKCHIP_MAX_CONNECTOR	2
-#define ROCKCHIP_MAX_CRTC	2
+#define ROCKCHIP_MAX_CRTC	4
 
 struct drm_device;
 struct drm_connector;
 struct iommu_domain;
 
+#define VOP_OUTPUT_IF_RGB       BIT(0)
+#define VOP_OUTPUT_IF_BT1120    BIT(1)
+#define VOP_OUTPUT_IF_BT656     BIT(2)
+#define VOP_OUTPUT_IF_LVDS0     BIT(3)
+#define VOP_OUTPUT_IF_LVDS1     BIT(4)
+#define VOP_OUTPUT_IF_MIPI0     BIT(5)
+#define VOP_OUTPUT_IF_MIPI1     BIT(6)
+#define VOP_OUTPUT_IF_eDP0      BIT(7)
+#define VOP_OUTPUT_IF_eDP1      BIT(8)
+#define VOP_OUTPUT_IF_DP0       BIT(9)
+#define VOP_OUTPUT_IF_DP1       BIT(10)
+#define VOP_OUTPUT_IF_HDMI0     BIT(11)
+#define VOP_OUTPUT_IF_HDMI1     BIT(12)
+
 struct rockchip_crtc_state {
 	struct drm_crtc_state base;
 	int output_type;
@@ -31,6 +45,10 @@ struct rockchip_crtc_state {
 	int output_bpc;
 	int output_flags;
 	bool enable_afbc;
+	uint32_t bus_format;
+	uint32_t output_if;
+	u32 bus_flags;
+	int color_space;
 };
 #define to_rockchip_crtc_state(s) \
 		container_of(s, struct rockchip_crtc_state, base)
@@ -65,4 +83,6 @@ extern struct platform_driver rockchip_dp_driver;
 extern struct platform_driver rockchip_lvds_driver;
 extern struct platform_driver vop_platform_driver;
 extern struct platform_driver rk3066_hdmi_driver;
+extern struct platform_driver vop2_platform_driver;
+
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 857d97cdc67c6..1eccadf72b59b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -7,6 +7,8 @@
 #ifndef _ROCKCHIP_DRM_VOP_H
 #define _ROCKCHIP_DRM_VOP_H
 
+#include <drm/drm_modes.h>
+
 /*
  * major: IP major version, used for IP structure
  * minor: big feature change under same structure
@@ -15,6 +17,14 @@
 #define VOP_MAJOR(version)		((version) >> 8)
 #define VOP_MINOR(version)		((version) & 0xff)
 
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE    BIT(0)
+#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE      BIT(1)
+#define ROCKCHIP_OUTPUT_DATA_SWAP                       BIT(2)
+
+#define VOP_FEATURE_OUTPUT_10BIT        BIT(0)
+#define VOP_FEATURE_AFBDC               BIT(1)
+#define VOP_FEATURE_ALPHA_SCALE         BIT(2)
+
 #define NUM_YUV2YUV_COEFFICIENTS 12
 
 /* AFBC supports a number of configurable modes. Relevant to us is block size
@@ -54,9 +64,23 @@ struct vop_afbc {
 	struct vop_reg enable;
 	struct vop_reg win_sel;
 	struct vop_reg format;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg auto_gating_en;
+	struct vop_reg block_split_en;
+	struct vop_reg pic_vir_width;
+	struct vop_reg tile_num;
 	struct vop_reg hreg_block_split;
+	struct vop_reg pic_offset;
 	struct vop_reg pic_size;
+	struct vop_reg dsp_offset;
+	struct vop_reg transform_offset;
 	struct vop_reg hdr_ptr;
+	struct vop_reg half_block_en;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rotate_270;
+	struct vop_reg rotate_90;
 	struct vop_reg rstn;
 };
 
@@ -184,6 +208,12 @@ struct vop_win_phy {
 	struct vop_reg channel;
 };
 
+struct vop_grf_ctrl {
+	struct vop_reg grf_dclk_inv;
+	struct vop_reg grf_bt1120_clk_inv;
+	struct vop_reg grf_bt656_clk_inv;
+};
+
 struct vop_win_yuv2yuv_data {
 	uint32_t base;
 	const struct vop_yuv2yuv_phy *phy;
@@ -409,5 +439,749 @@ static inline int scl_vop_cal_lb_mode(int width, bool is_yuv)
 	return lb_mode;
 }
 
+static inline int us_to_vertical_line(struct drm_display_mode *mode, int us)
+{
+	return us * mode->clock / mode->htotal / 1000;
+}
+
 extern const struct component_ops vop_component_ops;
+
+#define WIN_FEATURE_HDR2SDR		BIT(0)
+#define WIN_FEATURE_SDR2HDR		BIT(1)
+#define WIN_FEATURE_PRE_OVERLAY		BIT(2)
+#define WIN_FEATURE_AFBDC		BIT(3)
+#define WIN_FEATURE_CLUSTER_MAIN	BIT(4)
+#define WIN_FEATURE_CLUSTER_SUB		BIT(5)
+/* a mirror win can only get fb address
+ * from source win:
+ * Cluster1---->Cluster0
+ * Esmart1 ---->Esmart0
+ * Smart1  ---->Smart0
+ * This is a feather on rk3566
+ */
+#define WIN_FEATURE_MIRROR		BIT(6)
+#define WIN_FEATURE_MULTI_AREA		BIT(7)
+
+#define ROCKCHIP_MAX_LAYER       16
+#define MEDIA_BUS_FMT_SRGB888_3X8              0x101c
+#define WIN_FEATURE_MIRROR               BIT(6)
+#define MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA       0x101b
+#define MEDIA_BUS_FMT_SRGB888_DUMMY_4X8                0x101f
+
+/*
+ *  the delay number of a window in different mode.
+ */
+enum win_dly_mode {
+	VOP2_DLY_MODE_DEFAULT,   /**< default mode */
+	VOP2_DLY_MODE_HISO_S,    /** HDR in SDR out mode, as a SDR window */
+	VOP2_DLY_MODE_HIHO_H,    /** HDR in HDR out mode, as a HDR window */
+	VOP2_DLY_MODE_MAX,
+};
+
+struct vop_rect {
+	int width;
+	int height;
+};
+
+/* interrupt define */
+#define FS_NEW_INTR			BIT(4)
+#define ADDR_SAME_INTR			BIT(5)
+#define LINE_FLAG1_INTR			BIT(6)
+#define WIN0_EMPTY_INTR			BIT(7)
+#define WIN1_EMPTY_INTR			BIT(8)
+#define WIN2_EMPTY_INTR			BIT(9)
+#define WIN3_EMPTY_INTR			BIT(10)
+#define HWC_EMPTY_INTR			BIT(11)
+#define POST_BUF_EMPTY_INTR		BIT(12)
+#define PWM_GEN_INTR			BIT(13)
+#define DMA_FINISH_INTR			BIT(14)
+#define FS_FIELD_INTR			BIT(15)
+#define FE_INTR				BIT(16)
+#define WB_UV_FIFO_FULL_INTR		BIT(17)
+#define WB_YRGB_FIFO_FULL_INTR		BIT(18)
+#define WB_COMPLETE_INTR		BIT(19)
+
+#define VOP2_INTR_MASK			(DSP_HOLD_VALID_INTR | FS_INTR | \
+					 LINE_FLAG_INTR | BUS_ERROR_INTR | \
+					 FS_NEW_INTR | LINE_FLAG1_INTR | \
+					 WIN0_EMPTY_INTR | WIN1_EMPTY_INTR | \
+					 WIN2_EMPTY_INTR | WIN3_EMPTY_INTR | \
+					 HWC_EMPTY_INTR | \
+					 POST_BUF_EMPTY_INTR | \
+					 DMA_FINISH_INTR | FS_FIELD_INTR | \
+					 FE_INTR)
+#define DSP_HOLD_VALID_INTR_EN(x)	((x) << 4)
+#define FS_INTR_EN(x)			((x) << 5)
+#define LINE_FLAG_INTR_EN(x)		((x) << 6)
+#define BUS_ERROR_INTR_EN(x)		((x) << 7)
+#define DSP_HOLD_VALID_INTR_MASK	(1 << 4)
+#define FS_INTR_MASK			(1 << 5)
+#define LINE_FLAG_INTR_MASK		(1 << 6)
+#define BUS_ERROR_INTR_MASK		(1 << 7)
+
+#define INTR_CLR_SHIFT			8
+#define DSP_HOLD_VALID_INTR_CLR		(1 << (INTR_CLR_SHIFT + 0))
+#define FS_INTR_CLR			(1 << (INTR_CLR_SHIFT + 1))
+#define LINE_FLAG_INTR_CLR		(1 << (INTR_CLR_SHIFT + 2))
+#define BUS_ERROR_INTR_CLR		(1 << (INTR_CLR_SHIFT + 3))
+
+#define DSP_LINE_NUM(x)			(((x) & 0x1fff) << 12)
+#define DSP_LINE_NUM_MASK		(0x1fff << 12)
+
+/* src alpha ctrl define */
+#define SRC_FADING_VALUE(x)		(((x) & 0xff) << 24)
+#define SRC_GLOBAL_ALPHA(x)		(((x) & 0xff) << 16)
+#define SRC_FACTOR_M0(x)		(((x) & 0x7) << 6)
+#define SRC_ALPHA_CAL_M0(x)		(((x) & 0x1) << 5)
+#define SRC_BLEND_M0(x)			(((x) & 0x3) << 3)
+#define SRC_ALPHA_M0(x)			(((x) & 0x1) << 2)
+#define SRC_COLOR_M0(x)			(((x) & 0x1) << 1)
+#define SRC_ALPHA_EN(x)			(((x) & 0x1) << 0)
+/* dst alpha ctrl define */
+#define DST_FACTOR_M0(x)		(((x) & 0x7) << 6)
+
+/*
+ * display output interface supported by rockchip lcdc
+ */
+#define ROCKCHIP_OUT_MODE_P888		0
+#define ROCKCHIP_OUT_MODE_BT1120	0
+#define ROCKCHIP_OUT_MODE_P666		1
+#define ROCKCHIP_OUT_MODE_P565		2
+#define ROCKCHIP_OUT_MODE_BT656		5
+#define ROCKCHIP_OUT_MODE_S888		8
+#define ROCKCHIP_OUT_MODE_S888_DUMMY	12
+#define ROCKCHIP_OUT_MODE_YUV420	14
+/* for use special outface */
+#define ROCKCHIP_OUT_MODE_AAAA		15
+
+#define ROCKCHIP_OUT_MODE_TYPE(x)	((x) >> 16)
+#define ROCKCHIP_OUT_MODE(x)		((x) & 0xffff)
+
+enum vop_csc_format {
+	CSC_BT601L,
+	CSC_BT709L,
+	CSC_BT601F,
+	CSC_BT2020,
+};
+
+enum src_factor_mode {
+	SRC_FAC_ALPHA_ZERO,
+	SRC_FAC_ALPHA_ONE,
+	SRC_FAC_ALPHA_DST,
+	SRC_FAC_ALPHA_DST_INVERSE,
+	SRC_FAC_ALPHA_SRC,
+	SRC_FAC_ALPHA_SRC_GLOBAL,
+};
+
+enum dst_factor_mode {
+	DST_FAC_ALPHA_ZERO,
+	DST_FAC_ALPHA_ONE,
+	DST_FAC_ALPHA_SRC,
+	DST_FAC_ALPHA_SRC_INVERSE,
+	DST_FAC_ALPHA_DST,
+	DST_FAC_ALPHA_DST_GLOBAL,
+};
+
+enum vop2_scale_up_mode {
+	VOP2_SCALE_UP_NRST_NBOR,
+	VOP2_SCALE_UP_BIL,
+	VOP2_SCALE_UP_BIC,
+};
+
+enum vop2_scale_down_mode {
+	VOP2_SCALE_DOWN_NRST_NBOR,
+	VOP2_SCALE_DOWN_BIL,
+	VOP2_SCALE_DOWN_AVG,
+};
+
+struct vop2_cluster_regs {
+	struct vop_reg enable;
+	struct vop_reg afbc_enable;
+	struct vop_reg lb_mode;
+};
+
+struct vop2_scl_regs {
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg yrgb_hscl_filter_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_vscl_filter_mode;
+	struct vop_reg cbcr_ver_scl_mode;
+	struct vop_reg cbcr_hscl_filter_mode;
+	struct vop_reg cbcr_hor_scl_mode;
+	struct vop_reg cbcr_vscl_filter_mode;
+	struct vop_reg vsd_cbcr_gt2;
+	struct vop_reg vsd_cbcr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+};
+
+struct vop2_win_regs {
+	const struct vop2_scl_regs *scl;
+	const struct vop2_cluster_regs *cluster;
+	const struct vop_afbc *afbc;
+
+	struct vop_reg gate;
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg csc_mode;
+	struct vop_reg xmirror;
+	struct vop_reg ymirror;
+	struct vop_reg rb_swap;
+	struct vop_reg uv_swap;
+	struct vop_reg act_info;
+	struct vop_reg dsp_info;
+	struct vop_reg dsp_st;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg yrgb_vir;
+	struct vop_reg uv_vir;
+	struct vop_reg yuv_clip;
+	struct vop_reg lb_mode;
+	struct vop_reg y2r_en;
+	struct vop_reg r2y_en;
+	struct vop_reg channel;
+	struct vop_reg dst_alpha_ctl;
+	struct vop_reg src_alpha_ctl;
+	struct vop_reg alpha_mode;
+	struct vop_reg alpha_en;
+	struct vop_reg global_alpha_val;
+	struct vop_reg color_key;
+	struct vop_reg color_key_en;
+	struct vop_reg dither_up;
+};
+
+struct vop2_video_port_regs {
+	struct vop_reg cfg_done;
+	struct vop_reg overlay_mode;
+	struct vop_reg dsp_background;
+	struct vop_reg port_mux;
+	struct vop_reg out_mode;
+	struct vop_reg standby;
+	struct vop_reg dsp_interlace;
+	struct vop_reg dsp_filed_pol;
+	struct vop_reg dsp_data_swap;
+	struct vop_reg post_dsp_out_r2y;
+	struct vop_reg pre_scan_htiming;
+	struct vop_reg htotal_pw;
+	struct vop_reg hact_st_end;
+	struct vop_reg vtotal_pw;
+	struct vop_reg vact_st_end;
+	struct vop_reg vact_st_end_f1;
+	struct vop_reg vs_st_end_f1;
+	struct vop_reg hpost_st_end;
+	struct vop_reg vpost_st_end;
+	struct vop_reg vpost_st_end_f1;
+	struct vop_reg post_scl_factor;
+	struct vop_reg post_scl_ctrl;
+	struct vop_reg dither_down_sel;
+	struct vop_reg dither_down_mode;
+	struct vop_reg dither_down_en;
+	struct vop_reg pre_dither_down_en;
+	struct vop_reg dither_up_en;
+	struct vop_reg bg_dly;
+
+	struct vop_reg core_dclk_div;
+	struct vop_reg p2i_en;
+	struct vop_reg mipi_dual_en;
+	struct vop_reg mipi_dual_channel_swap;
+	struct vop_reg dsp_lut_en;
+
+	struct vop_reg dclk_div2;
+	struct vop_reg dclk_div2_phase_lock;
+
+	struct vop_reg hdr10_en;
+	struct vop_reg hdr_lut_update_en;
+	struct vop_reg hdr_lut_mode;
+	struct vop_reg hdr_lut_mst;
+	struct vop_reg sdr2hdr_eotf_en;
+	struct vop_reg sdr2hdr_r2r_en;
+	struct vop_reg sdr2hdr_r2r_mode;
+	struct vop_reg sdr2hdr_oetf_en;
+	struct vop_reg sdr2hdr_bypass_en;
+	struct vop_reg sdr2hdr_auto_gating_en;
+	struct vop_reg sdr2hdr_path_en;
+	struct vop_reg hdr2sdr_en;
+	struct vop_reg hdr2sdr_bypass_en;
+	struct vop_reg hdr2sdr_auto_gating_en;
+	struct vop_reg hdr2sdr_src_min;
+	struct vop_reg hdr2sdr_src_max;
+	struct vop_reg hdr2sdr_normfaceetf;
+	struct vop_reg hdr2sdr_dst_min;
+	struct vop_reg hdr2sdr_dst_max;
+	struct vop_reg hdr2sdr_normfacgamma;
+	uint32_t hdr2sdr_eetf_oetf_y0_offset;
+	uint32_t hdr2sdr_sat_y0_offset;
+	uint32_t sdr2hdr_eotf_oetf_y0_offset;
+	uint32_t sdr2hdr_oetf_dx_pow1_offset;
+	uint32_t sdr2hdr_oetf_xn1_offset;
+	struct vop_reg hdr_src_color_ctrl;
+	struct vop_reg hdr_dst_color_ctrl;
+	struct vop_reg hdr_src_alpha_ctrl;
+	struct vop_reg hdr_dst_alpha_ctrl;
+
+	/* BCSH */
+	struct vop_reg bcsh_brightness;
+	struct vop_reg bcsh_contrast;
+	struct vop_reg bcsh_sat_con;
+	struct vop_reg bcsh_sin_hue;
+	struct vop_reg bcsh_cos_hue;
+	struct vop_reg bcsh_r2y_csc_mode;
+	struct vop_reg bcsh_r2y_en;
+	struct vop_reg bcsh_y2r_csc_mode;
+	struct vop_reg bcsh_y2r_en;
+	struct vop_reg bcsh_out_mode;
+	struct vop_reg bcsh_en;
+
+	/* 3d lut */
+	struct vop_reg cubic_lut_en;
+	struct vop_reg cubic_lut_update_en;
+	struct vop_reg cubic_lut_mst;
+};
+
+struct vop2_wb_regs {
+	struct vop_reg enable;
+	struct vop_reg format;
+	struct vop_reg dither_en;
+	struct vop_reg r2y_en;
+	struct vop_reg yrgb_mst;
+	struct vop_reg uv_mst;
+	struct vop_reg vp_id;
+	struct vop_reg fifo_throd;
+	struct vop_reg scale_x_factor;
+	struct vop_reg scale_x_en;
+	struct vop_reg scale_y_en;
+	struct vop_reg axi_yrgb_id;
+	struct vop_reg axi_uv_id;
+};
+
+struct vop2_win_data {
+	const char *name;
+	uint8_t phys_id;
+
+	uint32_t base;
+	enum drm_plane_type type;
+
+	uint32_t nformats;
+	const uint32_t *formats;
+	const uint64_t *format_modifiers;
+	const unsigned int supported_rotations;
+
+	const struct vop2_win_regs *regs;
+
+	/*
+	 * vertical/horizontal scale up/down filter mode
+	 */
+	const u8 hsu_filter_mode;
+	const u8 hsd_filter_mode;
+	const u8 vsu_filter_mode;
+	const u8 vsd_filter_mode;
+	/**
+	 * @layer_sel_id: defined by register OVERLAY_LAYER_SEL of VOP2
+	 */
+	int layer_sel_id;
+	uint64_t feature;
+
+	unsigned int max_upscale_factor;
+	unsigned int max_downscale_factor;
+	const uint8_t dly[VOP2_DLY_MODE_MAX];
+};
+
+struct vop2_wb_data {
+	uint32_t nformats;
+	const uint32_t *formats;
+	struct vop_rect max_output;
+	const struct vop2_wb_regs *regs;
+};
+
+struct vop2_video_port_data {
+	char id;
+	uint32_t feature;
+	uint16_t gamma_lut_len;
+	uint16_t cubic_lut_len;
+	struct vop_rect max_output;
+	const u8 pre_scan_max_dly[4];
+	const struct vop_intr *intr;
+	const struct vop2_video_port_regs *regs;
+};
+
+struct vop2_layer_regs {
+	struct vop_reg layer_sel;
+};
+
+/**
+ * struct vop2_layer_data - The logic graphic layer in vop2
+ *
+ * The zorder:
+ *   LAYERn
+ *   LAYERn-1
+ *     .
+ *     .
+ *     .
+ *   LAYER5
+ *   LAYER4
+ *   LAYER3
+ *   LAYER2
+ *   LAYER1
+ *   LAYER0
+ *
+ * Each layer can select a unused window as input than feed to
+ * mixer for overlay.
+ *
+ * The pipeline in vop2:
+ *
+ * win-->layer-->mixer-->vp--->connector(RGB/LVDS/HDMI/MIPI)
+ *
+ */
+struct vop2_layer_data {
+	char id;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_ctrl {
+	struct vop_reg cfg_done_en;
+	struct vop_reg wb_cfg_done;
+	struct vop_reg auto_gating_en;
+	struct vop_reg ovl_cfg_done_port;
+	struct vop_reg ovl_port_mux_cfg_done_imd;
+	struct vop_reg ovl_port_mux_cfg;
+	struct vop_reg if_ctrl_cfg_done_imd;
+	struct vop_reg version;
+	struct vop_reg standby;
+	struct vop_reg dma_stop;
+	struct vop_reg lut_dma_en;
+	struct vop_reg axi_outstanding_max_num;
+	struct vop_reg axi_max_outstanding_en;
+	struct vop_reg hdmi_dclk_out_en;
+	struct vop_reg rgb_en;
+	struct vop_reg hdmi0_en;
+	struct vop_reg hdmi1_en;
+	struct vop_reg dp0_en;
+	struct vop_reg dp1_en;
+	struct vop_reg edp0_en;
+	struct vop_reg edp1_en;
+	struct vop_reg mipi0_en;
+	struct vop_reg mipi1_en;
+	struct vop_reg lvds0_en;
+	struct vop_reg lvds1_en;
+	struct vop_reg bt656_en;
+	struct vop_reg bt1120_en;
+	struct vop_reg dclk_pol;
+	struct vop_reg pin_pol;
+	struct vop_reg rgb_dclk_pol;
+	struct vop_reg rgb_pin_pol;
+	struct vop_reg lvds_dclk_pol;
+	struct vop_reg lvds_pin_pol;
+	struct vop_reg hdmi_dclk_pol;
+	struct vop_reg hdmi_pin_pol;
+	struct vop_reg edp_dclk_pol;
+	struct vop_reg edp_pin_pol;
+	struct vop_reg mipi_dclk_pol;
+	struct vop_reg mipi_pin_pol;
+	struct vop_reg dp_dclk_pol;
+	struct vop_reg dp_pin_pol;
+
+	struct vop_reg win_vp_id[8];
+	struct vop_reg win_dly[8];
+
+	/* connector mux */
+	struct vop_reg rgb_mux;
+	struct vop_reg hdmi0_mux;
+	struct vop_reg hdmi1_mux;
+	struct vop_reg dp0_mux;
+	struct vop_reg dp1_mux;
+	struct vop_reg edp0_mux;
+	struct vop_reg edp1_mux;
+	struct vop_reg mipi0_mux;
+	struct vop_reg mipi1_mux;
+	struct vop_reg lvds0_mux;
+	struct vop_reg lvds1_mux;
+
+	struct vop_reg lvds_dual_en;
+	struct vop_reg lvds_dual_mode;
+	struct vop_reg lvds_dual_channel_swap;
+
+	struct vop_reg cluster0_src_color_ctrl;
+	struct vop_reg cluster0_dst_color_ctrl;
+	struct vop_reg cluster0_src_alpha_ctrl;
+	struct vop_reg cluster0_dst_alpha_ctrl;
+	struct vop_reg src_color_ctrl;
+	struct vop_reg dst_color_ctrl;
+	struct vop_reg src_alpha_ctrl;
+	struct vop_reg dst_alpha_ctrl;
+
+	struct vop_reg bt1120_yc_swap;
+	struct vop_reg bt656_yc_swap;
+	struct vop_reg gamma_port_sel;
+
+	struct vop_reg otp_en;
+	struct vop_reg reg_done_frm;
+	struct vop_reg cfg_done;
+};
+
+/**
+ * VOP2 data struct
+ *
+ * @version: VOP IP version
+ * @win_size: hardware win number
+ */
+struct vop2_data {
+	uint8_t nr_vps;
+	uint8_t nr_mixers;
+	uint8_t nr_layers;
+	uint8_t nr_axi_intr;
+	uint8_t nr_gammas;
+	const struct vop_intr *axi_intr;
+	const struct vop2_ctrl *ctrl;
+	const struct vop2_win_data *win;
+	const struct vop2_video_port_data *vp;
+	const struct vop2_wb_data *wb;
+	const struct vop2_layer_data *layer;
+	const struct vop_csc_table *csc_table;
+	const struct vop_grf_ctrl *grf_ctrl;
+	struct vop_rect max_input;
+	struct vop_rect max_output;
+
+	unsigned int win_size;
+	unsigned int soc_id;
+};
+
+#define RK3568_GRF_VO_CON1			0x0364
+/* System registers definition */
+#define RK3568_REG_CFG_DONE			0x000
+#define RK3568_VOP2_WB_CFG_DONE			BIT(14)
+#define RK3568_VOP2_GLB_CFG_DONE_EN		BIT(15)
+#define RK3568_VERSION_INFO			0x004
+#define RK3568_SYS_AUTO_GATING_CTRL		0x008
+#define RK3568_SYS_AXI_LUT_CTRL			0x024
+#define RK3568_DSP_IF_EN			0x028
+#define RK3568_DSP_IF_CTRL			0x02c
+#define RK3568_DSP_IF_POL			0x030
+#define RK3568_WB_CTRL				0x40
+#define RK3568_WB_XSCAL_FACTOR			0x44
+#define RK3568_WB_YRGB_MST			0x48
+#define RK3568_WB_CBR_MST			0x4C
+#define RK3568_OTP_WIN_EN			0x050
+#define RK3568_LUT_PORT_SEL			0x058
+#define RK3568_SYS_STATUS0			0x060
+#define RK3568_VP0_LINE_FLAG			0x70
+#define RK3568_VP1_LINE_FLAG			0x74
+#define RK3568_VP2_LINE_FLAG			0x78
+#define RK3568_SYS0_INT_EN			0x80
+#define RK3568_SYS0_INT_CLR			0x84
+#define RK3568_SYS0_INT_STATUS			0x88
+#define RK3568_SYS1_INT_EN			0x90
+#define RK3568_SYS1_INT_CLR			0x94
+#define RK3568_SYS1_INT_STATUS			0x98
+#define RK3568_VP0_INT_EN			0xA0
+#define RK3568_VP0_INT_CLR			0xA4
+#define RK3568_VP0_INT_STATUS			0xA8
+#define RK3568_VP0_INT_RAW_STATUS		0xAC
+#define RK3568_VP1_INT_EN			0xB0
+#define RK3568_VP1_INT_CLR			0xB4
+#define RK3568_VP1_INT_STATUS			0xB8
+#define RK3568_VP1_INT_RAW_STATUS		0xBC
+#define RK3568_VP2_INT_EN			0xC0
+#define RK3568_VP2_INT_CLR			0xC4
+#define RK3568_VP2_INT_STATUS			0xC8
+#define RK3568_VP2_INT_RAW_STATUS		0xCC
+
+/* Video Port registers definition */
+#define RK3568_VP0_DSP_CTRL			0xC00
+#define RK3568_VP0_MIPI_CTRL			0xC04
+#define RK3568_VP0_COLOR_BAR_CTRL		0xC08
+#define RK3568_VP0_3D_LUT_CTRL			0xC10
+#define RK3568_VP0_3D_LUT_MST			0xC20
+#define RK3568_VP0_DSP_BG			0xC2C
+#define RK3568_VP0_PRE_SCAN_HTIMING		0xC30
+#define RK3568_VP0_POST_DSP_HACT_INFO		0xC34
+#define RK3568_VP0_POST_DSP_VACT_INFO		0xC38
+#define RK3568_VP0_POST_SCL_FACTOR_YRGB		0xC3C
+#define RK3568_VP0_POST_SCL_CTRL		0xC40
+#define RK3568_VP0_POST_DSP_VACT_INFO_F1	0xC44
+#define RK3568_VP0_DSP_HTOTAL_HS_END		0xC48
+#define RK3568_VP0_DSP_HACT_ST_END		0xC4C
+#define RK3568_VP0_DSP_VTOTAL_VS_END		0xC50
+#define RK3568_VP0_DSP_VACT_ST_END		0xC54
+#define RK3568_VP0_DSP_VS_ST_END_F1		0xC58
+#define RK3568_VP0_DSP_VACT_ST_END_F1		0xC5C
+#define RK3568_VP0_BCSH_CTRL			0xC60
+#define RK3568_VP0_BCSH_BCS			0xC64
+#define RK3568_VP0_BCSH_H			0xC68
+#define RK3568_VP0_BCSH_COLOR_BAR		0xC6C
+
+#define RK3568_VP1_DSP_CTRL			0xD00
+#define RK3568_VP1_MIPI_CTRL			0xD04
+#define RK3568_VP1_COLOR_BAR_CTRL		0xD08
+#define RK3568_VP1_DSP_BG			0xD2C
+#define RK3568_VP1_PRE_SCAN_HTIMING		0xD30
+#define RK3568_VP1_POST_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_POST_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_SCL_FACTOR_YRGB		0xD3C
+#define RK3568_VP1_POST_SCL_CTRL		0xD40
+#define RK3568_VP1_DSP_HACT_INFO		0xD34
+#define RK3568_VP1_DSP_VACT_INFO		0xD38
+#define RK3568_VP1_POST_DSP_VACT_INFO_F1	0xD44
+#define RK3568_VP1_DSP_HTOTAL_HS_END		0xD48
+#define RK3568_VP1_DSP_HACT_ST_END		0xD4C
+#define RK3568_VP1_DSP_VTOTAL_VS_END		0xD50
+#define RK3568_VP1_DSP_VACT_ST_END		0xD54
+#define RK3568_VP1_DSP_VS_ST_END_F1		0xD58
+#define RK3568_VP1_DSP_VACT_ST_END_F1		0xD5C
+#define RK3568_VP1_BCSH_CTRL			0xD60
+#define RK3568_VP1_BCSH_BCS			0xD64
+#define RK3568_VP1_BCSH_H			0xD68
+#define RK3568_VP1_BCSH_COLOR_BAR		0xD6C
+
+#define RK3568_VP2_DSP_CTRL			0xE00
+#define RK3568_VP2_MIPI_CTRL			0xE04
+#define RK3568_VP2_COLOR_BAR_CTRL		0xE08
+#define RK3568_VP2_DSP_BG			0xE2C
+#define RK3568_VP2_PRE_SCAN_HTIMING		0xE30
+#define RK3568_VP2_POST_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_POST_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_SCL_FACTOR_YRGB		0xE3C
+#define RK3568_VP2_POST_SCL_CTRL		0xE40
+#define RK3568_VP2_DSP_HACT_INFO		0xE34
+#define RK3568_VP2_DSP_VACT_INFO		0xE38
+#define RK3568_VP2_POST_DSP_VACT_INFO_F1	0xE44
+#define RK3568_VP2_DSP_HTOTAL_HS_END		0xE48
+#define RK3568_VP2_DSP_HACT_ST_END		0xE4C
+#define RK3568_VP2_DSP_VTOTAL_VS_END		0xE50
+#define RK3568_VP2_DSP_VACT_ST_END		0xE54
+#define RK3568_VP2_DSP_VS_ST_END_F1		0xE58
+#define RK3568_VP2_DSP_VACT_ST_END_F1		0xE5C
+#define RK3568_VP2_BCSH_CTRL			0xE60
+#define RK3568_VP2_BCSH_BCS			0xE64
+#define RK3568_VP2_BCSH_H			0xE68
+#define RK3568_VP2_BCSH_COLOR_BAR		0xE6C
+
+/* Overlay registers definition    */
+#define RK3568_OVL_CTRL				0x600
+#define RK3568_OVL_LAYER_SEL			0x604
+#define RK3568_OVL_PORT_SEL			0x608
+#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL	0x610
+#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL	0x614
+#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL	0x618
+#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL	0x61C
+#define RK3568_MIX0_SRC_COLOR_CTRL		0x650
+#define RK3568_MIX0_DST_COLOR_CTRL		0x654
+#define RK3568_MIX0_SRC_ALPHA_CTRL		0x658
+#define RK3568_MIX0_DST_ALPHA_CTRL		0x65C
+#define RK3568_HDR0_SRC_COLOR_CTRL		0x6C0
+#define RK3568_HDR0_DST_COLOR_CTRL		0x6C4
+#define RK3568_HDR0_SRC_ALPHA_CTRL		0x6C8
+#define RK3568_HDR0_DST_ALPHA_CTRL		0x6CC
+#define RK3568_VP0_BG_MIX_CTRL			0x6E0
+#define RK3568_VP1_BG_MIX_CTRL			0x6E4
+#define RK3568_VP2_BG_MIX_CTRL			0x6E8
+#define RK3568_CLUSTER_DLY_NUM			0x6F0
+#define RK3568_SMART_DLY_NUM			0x6F8
+
+/* Cluster register definition, offset relative to window base */
+#define RK3568_CLUSTER_WIN_CTRL0		0x00
+#define RK3568_CLUSTER_WIN_CTRL1		0x04
+#define RK3568_CLUSTER_WIN_YRGB_MST		0x10
+#define RK3568_CLUSTER_WIN_CBR_MST		0x14
+#define RK3568_CLUSTER_WIN_VIR			0x18
+#define RK3568_CLUSTER_WIN_ACT_INFO		0x20
+#define RK3568_CLUSTER_WIN_DSP_INFO		0x24
+#define RK3568_CLUSTER_WIN_DSP_ST		0x28
+#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB	0x30
+#define RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET	0x3C
+#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL	0x50
+#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE	0x54
+#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR	0x58
+#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH	0x5C
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE	0x60
+#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET	0x64
+#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET	0x68
+#define RK3568_CLUSTER_WIN_AFBCD_CTRL		0x6C
+
+#define RK3568_CLUSTER_CTRL			0x100
+
+/* (E)smart register definition, offset relative to window base */
+#define RK3568_SMART_CTRL0			0x00
+#define RK3568_SMART_CTRL1			0x04
+#define RK3568_SMART_REGION0_CTRL		0x10
+#define RK3568_SMART_REGION0_YRGB_MST		0x14
+#define RK3568_SMART_REGION0_CBR_MST		0x18
+#define RK3568_SMART_REGION0_VIR		0x1C
+#define RK3568_SMART_REGION0_ACT_INFO		0x20
+#define RK3568_SMART_REGION0_DSP_INFO		0x24
+#define RK3568_SMART_REGION0_DSP_ST		0x28
+#define RK3568_SMART_REGION0_SCL_CTRL		0x30
+#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB	0x34
+#define RK3568_SMART_REGION0_SCL_FACTOR_CBR	0x38
+#define RK3568_SMART_REGION0_SCL_OFFSET		0x3C
+#define RK3568_SMART_REGION1_CTRL		0x40
+#define RK3568_SMART_REGION1_YRGB_MST		0x44
+#define RK3568_SMART_REGION1_CBR_MST		0x48
+#define RK3568_SMART_REGION1_VIR		0x4C
+#define RK3568_SMART_REGION1_ACT_INFO		0x50
+#define RK3568_SMART_REGION1_DSP_INFO		0x54
+#define RK3568_SMART_REGION1_DSP_ST		0x58
+#define RK3568_SMART_REGION1_SCL_CTRL		0x60
+#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB	0x64
+#define RK3568_SMART_REGION1_SCL_FACTOR_CBR	0x68
+#define RK3568_SMART_REGION1_SCL_OFFSET		0x6C
+#define RK3568_SMART_REGION2_CTRL		0x70
+#define RK3568_SMART_REGION2_YRGB_MST		0x74
+#define RK3568_SMART_REGION2_CBR_MST		0x78
+#define RK3568_SMART_REGION2_VIR		0x7C
+#define RK3568_SMART_REGION2_ACT_INFO		0x80
+#define RK3568_SMART_REGION2_DSP_INFO		0x84
+#define RK3568_SMART_REGION2_DSP_ST		0x88
+#define RK3568_SMART_REGION2_SCL_CTRL		0x90
+#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB	0x94
+#define RK3568_SMART_REGION2_SCL_FACTOR_CBR	0x98
+#define RK3568_SMART_REGION2_SCL_OFFSET		0x9C
+#define RK3568_SMART_REGION3_CTRL		0xA0
+#define RK3568_SMART_REGION3_YRGB_MST		0xA4
+#define RK3568_SMART_REGION3_CBR_MST		0xA8
+#define RK3568_SMART_REGION3_VIR		0xAC
+#define RK3568_SMART_REGION3_ACT_INFO		0xB0
+#define RK3568_SMART_REGION3_DSP_INFO		0xB4
+#define RK3568_SMART_REGION3_DSP_ST		0xB8
+#define RK3568_SMART_REGION3_SCL_CTRL		0xC0
+#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB	0xC4
+#define RK3568_SMART_REGION3_SCL_FACTOR_CBR	0xC8
+#define RK3568_SMART_REGION3_SCL_OFFSET		0xCC
+#define RK3568_SMART_COLOR_KEY_CTRL		0xD0
+
+/* HDR register definition */
+#define RK3568_HDR_LUT_CTRL				0x2000
+#define RK3568_HDR_LUT_MST				0x2004
+#define RK3568_SDR2HDR_CTRL				0x2010
+#define RK3568_HDR2SDR_CTRL				0x2020
+#define RK3568_HDR2SDR_SRC_RANGE			0x2024
+#define RK3568_HDR2SDR_NORMFACEETF			0x2028
+#define RK3568_HDR2SDR_DST_RANGE			0x202C
+#define RK3568_HDR2SDR_NORMFACCGAMMA			0x2030
+#define RK3568_HDR_EETF_OETF_Y0				0x203C
+#define RK3568_HDR_SAT_Y0				0x20C0
+#define RK3568_HDR_EOTF_OETF_Y0				0x20F0
+#define RK3568_HDR_OETF_DX_POW1				0x2200
+#define RK3568_HDR_OETF_XN1				0x2300
+
+enum vop2_layer_phy_id {
+	ROCKCHIP_VOP2_CLUSTER0 = 0,
+	ROCKCHIP_VOP2_CLUSTER1,
+	ROCKCHIP_VOP2_ESMART0,
+	ROCKCHIP_VOP2_ESMART1,
+	ROCKCHIP_VOP2_SMART0,
+	ROCKCHIP_VOP2_SMART1,
+	ROCKCHIP_VOP2_CLUSTER2,
+	ROCKCHIP_VOP2_CLUSTER3,
+	ROCKCHIP_VOP2_ESMART2,
+	ROCKCHIP_VOP2_ESMART3,
+	ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
+};
+
+extern const struct component_ops vop2_component_ops;
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
new file mode 100644
index 0000000000000..60fa529718810
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -0,0 +1,3611 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+#include <drm/drm.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_writeback.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_atomic_uapi.h>
+
+#include <linux/debugfs.h>
+#include <linux/fixp-arith.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/pm_runtime.h>
+#include <linux/component.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/delay.h>
+#include <linux/swab.h>
+#include <linux/sort.h>
+#include <drm/drm_debugfs.h>
+#include <uapi/linux/videodev2.h>
+#include <drm/drm_vblank.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_gem.h"
+#include "rockchip_drm_fb.h"
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define VOP2_SYS_AXI_BUS_NUM 2
+
+#define VOP2_CLUSTER_YUV444_10 0x12
+
+#define VOP2_COLOR_KEY_MASK		(1 << 31)
+
+#define DSP_BG_SWAP             0x1
+#define DSP_RB_SWAP             0x2
+#define DSP_RG_SWAP             0x4
+#define DSP_DELTA_SWAP          0x8
+
+enum vop2_data_format {
+	VOP2_FMT_ARGB8888 = 0,
+	VOP2_FMT_RGB888,
+	VOP2_FMT_RGB565,
+	VOP2_FMT_XRGB101010,
+	VOP2_FMT_YUV420SP,
+	VOP2_FMT_YUV422SP,
+	VOP2_FMT_YUV444SP,
+	VOP2_FMT_YUYV422 = 8,
+	VOP2_FMT_YUYV420,
+	VOP2_FMT_VYUY422,
+	VOP2_FMT_VYUY420,
+	VOP2_FMT_YUV420SP_TILE_8x4 = 0x10,
+	VOP2_FMT_YUV420SP_TILE_16x2,
+	VOP2_FMT_YUV422SP_TILE_8x4,
+	VOP2_FMT_YUV422SP_TILE_16x2,
+	VOP2_FMT_YUV420SP_10,
+	VOP2_FMT_YUV422SP_10,
+	VOP2_FMT_YUV444SP_10,
+};
+
+enum vop2_afbc_format {
+	VOP2_AFBC_FMT_RGB565,
+	VOP2_AFBC_FMT_ARGB2101010 = 2,
+	VOP2_AFBC_FMT_YUV420_10BIT,
+	VOP2_AFBC_FMT_RGB888,
+	VOP2_AFBC_FMT_ARGB8888,
+	VOP2_AFBC_FMT_YUV420 = 9,
+	VOP2_AFBC_FMT_YUV422 = 0xb,
+	VOP2_AFBC_FMT_YUV422_10BIT = 0xe,
+	VOP2_AFBC_FMT_INVALID = -1,
+};
+
+enum vop2_hdr_lut_mode {
+	VOP2_HDR_LUT_MODE_AXI,
+	VOP2_HDR_LUT_MODE_AHB,
+};
+
+enum vop2_pending {
+	VOP_PENDING_FB_UNREF,
+};
+
+struct vop2_zpos {
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	int zpos;
+};
+
+union vop2_alpha_ctrl {
+	uint32_t val;
+	struct {
+		/* [0:1] */
+		uint32_t color_mode:1;
+		uint32_t alpha_mode:1;
+		/* [2:3] */
+		uint32_t blend_mode:2;
+		uint32_t alpha_cal_mode:1;
+		/* [5:7] */
+		uint32_t factor_mode:3;
+		/* [8:9] */
+		uint32_t alpha_en:1;
+		uint32_t src_dst_swap:1;
+		uint32_t reserved:6;
+		/* [16:23] */
+		uint32_t glb_alpha:8;
+	} bits;
+};
+
+struct vop2_alpha {
+	union vop2_alpha_ctrl src_color_ctrl;
+	union vop2_alpha_ctrl dst_color_ctrl;
+	union vop2_alpha_ctrl src_alpha_ctrl;
+	union vop2_alpha_ctrl dst_alpha_ctrl;
+};
+
+struct vop2_alpha_config {
+	bool src_premulti_en;
+	bool dst_premulti_en;
+	bool src_pixel_alpha_en;
+	bool dst_pixel_alpha_en;
+	uint16_t src_glb_alpha_value;
+	uint16_t dst_glb_alpha_value;
+};
+
+struct vop2_win {
+	const char *name;
+	struct vop2 *vop2;
+	struct drm_plane base;
+	const struct vop2_win_data *data;
+
+	/*
+	 * This is for cluster window
+	 *
+	 * A cluster window can split as two windows:
+	 * a main window and a sub window.
+	 */
+	bool two_win_mode;
+
+	/**
+	 * @win_id: graphic window id, a cluster maybe split into two
+	 * graphics windows.
+	 */
+	uint8_t win_id;
+	/**
+	 * @plane_id: unique plane id.
+	 */
+	uint8_t plane_id;
+	/**
+	 * @layer_id: id of the layer which the window attached to
+	 */
+	uint8_t layer_id;
+	int layer_sel_id;
+	/**
+	 * @vp_mask: Bitmask of video_port0/1/2 this win attached to,
+	 * one win can only attach to one vp at the one time.
+	 */
+	uint8_t vp_mask;
+	/**
+	 * @old_vp_mask: Bitmask of video_port0/1/2 this win attached of last commit,
+	 * this is used for trackng the change of VOP2_PORT_SEL register.
+	 */
+	uint8_t old_vp_mask;
+	uint8_t zpos;
+	uint32_t offset;
+	enum drm_plane_type type;
+
+	const struct vop2_win_regs *regs;
+};
+
+struct vop2_cluster {
+	struct vop2_win *main;
+	struct vop2_win *sub;
+};
+
+struct vop2_layer {
+	uint8_t id;
+	struct vop2_win *win;
+	const struct vop2_layer_regs *regs;
+};
+
+struct vop2_video_port {
+	struct drm_crtc crtc;
+	struct vop2 *vop2;
+	struct clk *dclk;
+	uint8_t id;
+	bool layer_sel_update;
+	const struct vop2_video_port_regs *regs;
+
+	struct completion dsp_hold_completion;
+	struct completion line_flag_completion;
+
+	/* protected by dev->event_lock */
+	struct drm_pending_vblank_event *event;
+
+	struct drm_flip_work fb_unref_work;
+	unsigned long pending;
+
+	struct vop2_zpos *zpos;
+	int nr_layers;
+
+	/**
+	 * @skip_vsync: skip on vsync when port_mux changed on this vp.
+	 * a win move from one VP to another need wait one vsync until
+	 * port_mut take effect before this win can be enabled.
+	 *
+	 */
+	bool skip_vsync;
+
+	/**
+	 * @bg_ovl_dly: The timing delay from background layer
+	 * to overlay module.
+	 */
+	uint8_t bg_ovl_dly;
+
+	/**
+	 * @win_mask: Bitmask of wins attached to the video port;
+	 */
+	uint32_t win_mask;
+
+	/**
+	 * @gamma_lut_len: gamma look up table size
+	 */
+	uint32_t gamma_lut_len;
+
+	/**
+	 * @gamma_lut_active: gamma states
+	 */
+	bool gamma_lut_active;
+
+	struct vop2_win *primary_plane;
+};
+
+struct vop2 {
+	struct device *dev;
+	struct drm_device *drm;
+	struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
+
+	const struct vop2_data *data;
+	/* Number of win that registered as plane,
+	 * maybe less than the total number of hardware
+	 * win.
+	 */
+	uint32_t registered_num_wins;
+	uint8_t used_mixers;
+
+	uint16_t port_mux_cfg;
+
+	uint32_t *regsbak;
+	void __iomem *regs;
+	struct regmap *grf;
+
+	/* physical map length of vop2 register */
+	uint32_t len;
+
+	void __iomem *lut_regs;
+	/* one time only one process allowed to config the register */
+	spinlock_t reg_lock;
+	/* lock vop2 irq reg */
+	spinlock_t irq_lock;
+	/* protects crtc enable/disable */
+	struct mutex vop2_lock;
+
+	int irq;
+
+	/*
+	 * Some globle resource are shared between all
+	 * the vidoe ports(crtcs), so we need a ref counter here.
+	 */
+	unsigned int enable_count;
+	struct clk *hclk;
+	struct clk *aclk;
+
+	struct vop2_layer layers[ROCKCHIP_MAX_LAYER];
+	/* must put at the end of the struct */
+	struct vop2_win win[];
+};
+
+static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct vop2_video_port, crtc);
+}
+
+static inline struct vop2_win *to_vop2_win(struct drm_plane *p)
+{
+	return container_of(p, struct vop2_win, base);
+}
+
+static void vop2_lock(struct vop2 *vop2)
+{
+	mutex_lock(&vop2->vop2_lock);
+}
+
+static void vop2_unlock(struct vop2 *vop2)
+{
+	mutex_unlock(&vop2->vop2_lock);
+}
+
+static inline void vop2_grf_writel(struct vop2 *vop2, struct vop_reg reg, uint32_t v)
+{
+	uint32_t val = 0;
+
+	if (IS_ERR_OR_NULL(vop2->grf))
+		return;
+
+	if (reg.mask) {
+		val = (v << reg.shift) | (reg.mask << (reg.shift + 16));
+		regmap_write(vop2->grf, reg.offset, val);
+	}
+}
+
+static void vop2_writel(struct vop2 *vop2, uint32_t offset, uint32_t v)
+{
+	writel(v, vop2->regs + offset);
+	vop2->regsbak[offset >> 2] = v;
+}
+
+static uint32_t vop2_readl(struct vop2 *vop2, uint32_t offset)
+{
+	return readl(vop2->regs + offset);
+}
+
+static uint32_t vop2_read_reg(struct vop2 *vop2, uint32_t offset,
+			      const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, offset + reg->offset) >> reg->shift) & reg->mask;
+}
+
+static inline uint32_t vop2_read(struct vop2 *vop2, const struct vop_reg *reg)
+{
+	return (vop2_readl(vop2, reg->offset) >> reg->shift) & reg->mask;
+}
+
+static void vop2_write_reg(struct vop2 *vop2, uint32_t offset, const struct vop_reg *reg,
+				   uint32_t v, bool relaxed)
+{
+	uint32_t mask = reg->mask;
+	uint32_t shift = reg->shift;
+
+	if (!mask)
+		return;
+
+	offset += reg->offset;
+
+	if (reg->write_mask) {
+		v = ((v & mask) << shift) | (mask << (shift + 16));
+	} else {
+		/*
+		 * Several registers in the VOP2 are double buffered and read back
+		 * the new values only after config_done bits have been set. As we
+		 * read-modify-write the hardware registers we need to cache the values
+		 * in memory to make sure we do not overwrite previous values when a
+		 * hardware register is modified multiple times before config_done is
+		 * set.
+		 */
+		uint32_t cached_val = vop2->regsbak[offset >> 2];
+
+		v = (cached_val & ~(mask << shift)) | ((v & mask) << shift);
+		vop2->regsbak[offset >> 2] = v;
+	}
+
+	if (relaxed)
+		writel_relaxed(v, vop2->regs + offset);
+	else
+		writel(v, vop2->regs + offset);
+}
+
+static void vop2_write(struct vop2 *vop2, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(vop2, 0, reg, v, false);
+}
+
+static void vop2_win_write(const struct vop2_win *win, const struct vop_reg *reg, uint32_t v)
+{
+	vop2_write_reg(win->vop2, win->offset, reg, v, true);
+}
+
+static uint32_t vop2_win_read(const struct vop2_win *win, const struct vop_reg *reg)
+{
+	return vop2_read_reg(win->vop2, win->offset, reg);
+}
+
+
+static void vop2_intr_set_type(struct vop2 *vop2, const struct vop_intr *intr,
+			       const struct vop_reg *reg, uint32_t type, bool enable)
+{
+	uint32_t v = 0, mask = 0;
+	int i;
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if (intr->intrs[i] & type) {
+			if (enable)
+				v |= 1 << i;
+			mask |= 1 << i;
+		}
+	}
+
+	writel(v | (mask << 16), vop2->regs + reg->offset);
+}
+
+static inline uint32_t vop2_line_to_time(struct drm_display_mode *mode, int line)
+{
+	u64 val = 1000000000ULL * mode->crtc_htotal * line;
+
+	do_div(val, mode->crtc_clock);
+	do_div(val, 1000000);
+
+	return val; /* us */
+}
+
+static inline uint32_t vop2_get_intr_type(struct vop2 *vop2, const struct vop_intr *intr,
+					  const struct vop_reg *reg, int type)
+{
+	uint32_t val, i;
+	uint32_t ret = 0;
+
+	val = vop2_read_reg(vop2, 0, reg);
+
+	for (i = 0; i < intr->nintrs; i++) {
+		if ((type & intr->intrs[i]) && (val & 1 << i))
+			ret |= intr->intrs[i];
+	}
+
+	return ret;
+}
+
+/*
+ * phys_id is used to identify a main window(Cluster Win/Smart Win, not
+ * include the sub win of a cluster or the multi area) that can do
+ * overlay in main overlay stage.
+ */
+static struct vop2_win *vop2_find_win_by_phys_id(struct vop2 *vop2, uint8_t phys_id)
+{
+	struct vop2_win *win;
+	int i;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+		if (win->data->phys_id == phys_id)
+			return win;
+	}
+
+	return NULL;
+}
+
+static bool vop2_fs_irq_is_pending(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	return vop2_get_intr_type(vop2, intr, &intr->status, FS_FIELD_INTR);
+}
+
+static uint32_t vop2_read_vcnt(struct vop2_video_port *vp)
+{
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint32_t offset = RK3568_SYS_STATUS0 + (vp->id << 2);
+	uint32_t vcnt;
+
+	vcnt = vop2_readl(vp->vop2, offset) >> 16;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vcnt >>= 1;
+
+	return vcnt;
+}
+
+static void vop2_wait_for_irq_handler(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	bool pending;
+	int ret;
+
+	/*
+	 * Spin until frame start interrupt status bit goes low, which means
+	 * that interrupt handler was invoked and cleared it. The timeout of
+	 * 10 msecs is really too long, but it is just a safety measure if
+	 * something goes really wrong. The wait will only happen in the very
+	 * unlikely case of a vblank happening exactly at the same time and
+	 * shouldn't exceed microseconds range.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_fs_irq_is_pending, vp, pending,
+					!pending, 0, 10 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "VOP vblank IRQ stuck for 10 ms\n");
+
+	synchronize_irq(vop2->irq);
+}
+
+static bool vop2_vp_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & BIT(vp->id);
+
+	/*
+	 * When done bit is 0, indicate current frame is take effect.
+	 */
+	return done_bits == 0 ? true : false;
+}
+
+static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	bool done_bit;
+	int ret;
+
+	ret = readx_poll_timeout_atomic(vop2_vp_done_bit_status, vp, done_bit,
+					done_bit, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait vp%d done bit status timeout, vcnt: %d\n",
+			      vp->id, vop2_read_vcnt(vp));
+}
+
+static uint16_t vop2_read_port_mux(struct vop2 *vop2)
+{
+	return vop2_readl(vop2, RK3568_OVL_PORT_SEL) & 0xffff;
+}
+
+static void vop2_wait_for_port_mux_done(struct vop2 *vop2)
+{
+	uint16_t port_mux_cfg;
+	int ret;
+
+	/*
+	 * Spin until the previous port_mux figuration
+	 * is done.
+	 */
+	ret = readx_poll_timeout_atomic(vop2_read_port_mux, vop2, port_mux_cfg,
+					port_mux_cfg == vop2->port_mux_cfg, 0, 50 * 1000);
+	if (ret)
+		drm_err(vop2->drm, "wait port_mux done timeout: 0x%x--0x%x\n",
+			      port_mux_cfg, vop2->port_mux_cfg);
+}
+
+
+static int32_t vop2_pending_done_bits(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *adjusted_mode;
+	struct vop2_video_port *done_vp;
+	uint32_t done_bits, done_bits_bak;
+	uint32_t vp_id;
+	uint32_t vcnt;
+	struct drm_display_mode *first_mode, *second_mode;
+	struct vop2_video_port *first_done_vp, *second_done_vp, *wait_vp;
+	uint32_t first_vp_id, second_vp_id;
+	uint32_t first_vp_vcnt, second_vp_vcnt;
+	uint32_t first_vp_left_vcnt, second_vp_left_vcnt;
+	uint32_t first_vp_left_time, second_vp_left_time;
+	uint32_t first_vp_safe_time, second_vp_safe_time;
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	done_bits_bak = done_bits;
+
+	done_bits &= ~BIT(vp->id);
+
+	/* no done bit, so no need to wait config done take effect */
+	if (done_bits == 0)
+		return 0;
+
+	/* have the other one different vp, wait for config done take effect */
+	if (hweight32(done_bits) == 1) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		adjusted_mode = &done_vp->crtc.state->adjusted_mode;
+		vcnt = vop2_read_vcnt(done_vp);
+
+		/* if close to the last 1/8 frame, wait to next frame */
+		if (vcnt > (adjusted_mode->crtc_vtotal * 7 >> 3)) {
+			vop2_wait_for_fs_by_done_bit_status(done_vp);
+			return 0;
+		}
+		return done_bits;
+	}
+
+	first_vp_id = ffs(done_bits) - 1;
+	first_done_vp = &vop2->vps[first_vp_id];
+	first_mode = &first_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	first_vp_safe_time = 1000000 / drm_mode_vrefresh(first_mode) >> 3;
+
+	done_bits &= ~BIT(first_vp_id);
+	second_vp_id = ffs(done_bits) - 1;
+	second_done_vp = &vop2->vps[second_vp_id];
+	second_mode = &second_done_vp->crtc.state->adjusted_mode;
+	/* set last 1/8 frame time as safe section */
+	second_vp_safe_time = 1000000 / drm_mode_vrefresh(second_mode) >> 3;
+
+	first_vp_vcnt = vop2_read_vcnt(first_done_vp);
+
+	second_vp_vcnt = vop2_read_vcnt(second_done_vp);
+
+	first_vp_left_vcnt = first_mode->crtc_vtotal - first_vp_vcnt;
+	second_vp_left_vcnt = second_mode->crtc_vtotal - second_vp_vcnt;
+	first_vp_left_time = vop2_line_to_time(first_mode, first_vp_left_vcnt);
+	second_vp_left_time = vop2_line_to_time(second_mode, second_vp_left_vcnt);
+
+	/* if the two vp both at safe section, no need to wait */
+	if (first_vp_left_time > first_vp_safe_time &&
+	    second_vp_left_time > second_vp_safe_time)
+		return done_bits_bak;
+
+	if (first_vp_left_time > second_vp_left_time)
+		wait_vp = first_done_vp;
+	else
+		wait_vp = second_done_vp;
+
+	vop2_wait_for_fs_by_done_bit_status(wait_vp);
+
+	done_bits = vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7;
+	if (done_bits) {
+		vp_id = ffs(done_bits) - 1;
+		done_vp = &vop2->vps[vp_id];
+		vop2_wait_for_fs_by_done_bit_status(done_vp);
+	}
+	return 0;
+}
+
+static inline void vop2_cfg_done(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t done_bits;
+	uint32_t val;
+	uint32_t old_layer_sel_val, cfg_layer_sel_val;
+	struct vop2_layer *layer = &vop2->layers[0];
+	uint32_t layer_sel_offset = layer->regs->layer_sel.offset;
+
+	/*
+	 * This is a workaround, the config done bits of VP0,
+	 * VP1, VP2 on RK3568 stands on the first three bits
+	 * on REG_CFG_DONE register without mask bit.
+	 * If two or three config done events happens one after
+	 * another in a very shot time, the flowing config done
+	 * write may override the previous config done bit before
+	 * it take effect:
+	 * 1: config done 0x8001 for VP0
+	 * 2: config done 0x8002 for VP1
+	 *
+	 * 0x8002 may override 0x8001 before it take effect.
+	 *
+	 * So we do a read | write here.
+	 *
+	 */
+	done_bits = vop2_pending_done_bits(vp);
+	old_layer_sel_val = vop2_readl(vop2, layer_sel_offset);
+	cfg_layer_sel_val = vop2->regsbak[layer_sel_offset >> 2];
+	/**
+	 * This is rather low probability for miss some done bit.
+	 */
+	val = RK3568_VOP2_GLB_CFG_DONE_EN | BIT(vp->id) | done_bits |
+		(vop2_readl(vop2, RK3568_REG_CFG_DONE) & 0x7);
+	vop2_writel(vop2, 0, val);
+
+	/**
+	 * Make sure the layer sel is take effect when it's updated.
+	 */
+	if (old_layer_sel_val != cfg_layer_sel_val) {
+		vp->layer_sel_update = true;
+		vop2_wait_for_fs_by_done_bit_status(vp);
+		drm_dbg(vop2->drm, "vp%d need to wait fs as old layer_sel val[0x%x] != new val[0x%x]\n",
+			      vp->id, old_layer_sel_val, cfg_layer_sel_val);
+	}
+}
+
+static void vop2_win_disable(struct vop2_win *win)
+{
+	struct vop2 *vop2 = win->vop2;
+
+	vop2_win_write(win, &win->regs->enable, 0);
+	if (win->data->feature & WIN_FEATURE_CLUSTER_MAIN) {
+		struct vop2_win *sub_win;
+		int i = 0;
+
+		for (i = 0; i < vop2->registered_num_wins; i++) {
+			sub_win = &vop2->win[i];
+
+			if ((sub_win->data->phys_id == win->data->phys_id) &&
+			    (sub_win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+				vop2_win_write(sub_win, &sub_win->regs->enable, 0);
+		}
+
+		vop2_win_write(win, &win->regs->cluster->enable, 0);
+	}
+}
+
+static enum vop2_data_format vop2_convert_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_FMT_YUV420SP;
+	case DRM_FORMAT_NV16:
+		return VOP2_FMT_YUV422SP;
+	case DRM_FORMAT_NV24:
+		return VOP2_FMT_YUV444SP;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+		return VOP2_FMT_VYUY422;
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_UYVY:
+		return VOP2_FMT_YUYV422;
+	default:
+		DRM_ERROR("unsupported format[%08x]\n", format);
+		return -EINVAL;
+	}
+}
+
+static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return VOP2_AFBC_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		return VOP2_AFBC_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		return VOP2_AFBC_FMT_RGB565;
+	case DRM_FORMAT_NV12:
+		return VOP2_AFBC_FMT_YUV420;
+	case DRM_FORMAT_NV16:
+		return VOP2_AFBC_FMT_YUV422;
+
+		/* either of the below should not be reachable */
+	default:
+		DRM_WARN_ONCE("unsupported AFBC format[%08x]\n", format);
+		return VOP2_AFBC_FMT_INVALID;
+	}
+
+	return VOP2_AFBC_FMT_INVALID;
+}
+
+static bool vop2_win_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_BGR565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_rb_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_afbc_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_uv_swap(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_win_dither_up(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB565:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool vop2_output_uv_swap(uint32_t bus_format, uint32_t output_mode)
+{
+	/*
+	 * FIXME:
+	 *
+	 * There is no media type for YUV444 output,
+	 * so when out_mode is AAAA or P888, assume output is YUV444 on
+	 * yuv format.
+	 *
+	 * From H/W testing, YUV444 mode need a rb swap.
+	 */
+	if (bus_format == MEDIA_BUS_FMT_YVYU8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_1X16 ||
+	    bus_format == MEDIA_BUS_FMT_YVYU8_2X8 ||
+	    bus_format == MEDIA_BUS_FMT_VYUY8_2X8 ||
+	    ((bus_format == MEDIA_BUS_FMT_YUV8_1X24 ||
+	      bus_format == MEDIA_BUS_FMT_YUV10_1X30) &&
+	     (output_mode == ROCKCHIP_OUT_MODE_AAAA ||
+	      output_mode == ROCKCHIP_OUT_MODE_P888)))
+		return true;
+	else
+		return false;
+}
+
+static bool vop2_output_yc_swap(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_yuv_output(uint32_t bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YVYU8_2X8:
+	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_VYUY8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool is_alpha_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool rockchip_afbc(struct drm_plane *plane, u64 modifier)
+{
+	int i;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return false;
+
+	for (i = 0 ; i < plane->modifier_count; i++)
+		if (plane->modifiers[i] == modifier)
+			break;
+
+	return (i < plane->modifier_count) ? true : false;
+
+}
+
+static bool rockchip_vop2_mod_supported(struct drm_plane *plane, uint32_t format, u64 modifier)
+{
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	if (modifier == DRM_FORMAT_MOD_INVALID)
+		return false;
+
+	if (modifier == DRM_FORMAT_MOD_LINEAR)
+		return true;
+
+	if (!rockchip_afbc(plane, modifier)) {
+		drm_err(vop2->drm, "Unsupported format modifier 0x%llx\n", modifier);
+
+		return false;
+	}
+
+	return vop2_convert_afbc_format(format) >= 0;
+}
+
+static inline bool vop2_cluster_window(struct vop2_win *win)
+{
+	return  (win->data->feature & (WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_CLUSTER_SUB));
+}
+
+static int vop2_afbc_half_block_enable(struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 0;
+	else
+		return 1;
+}
+
+static uint32_t vop2_afbc_transform_offset(struct drm_plane_state *pstate,
+					   bool afbc_half_block_en)
+{
+	struct drm_rect *src = &pstate->src;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t vir_width = (fb->pitches[0] << 3) / bpp;
+	uint32_t width = drm_rect_width(src) >> 16;
+	uint32_t height = drm_rect_height(src) >> 16;
+	uint32_t act_xoffset = src->x1 >> 16;
+	uint32_t act_yoffset = src->y1 >> 16;
+	uint32_t align16_crop = 0;
+	uint32_t align64_crop = 0;
+	uint32_t height_tmp = 0;
+	uint32_t transform_tmp = 0;
+	uint8_t transform_xoffset = 0;
+	uint8_t transform_yoffset = 0;
+	uint8_t top_crop = 0;
+	uint8_t top_crop_line_num = 0;
+	uint8_t bottom_crop_line_num = 0;
+
+	/* 16 pixel align */
+	if (height & 0xf)
+		align16_crop = 16 - (height & 0xf);
+
+	height_tmp = height + align16_crop;
+
+	/* 64 pixel align */
+	if (height_tmp & 0x3f)
+		align64_crop = 64 - (height_tmp & 0x3f);
+
+	top_crop_line_num = top_crop << 2;
+	if (top_crop == 0)
+		bottom_crop_line_num = align16_crop + align64_crop;
+	else if (top_crop == 1)
+		bottom_crop_line_num = align16_crop + align64_crop + 12;
+	else if (top_crop == 2)
+		bottom_crop_line_num = align16_crop + align64_crop + 8;
+
+	switch (pstate->rotation &
+		(DRM_MODE_REFLECT_X |
+		 DRM_MODE_REFLECT_Y |
+		 DRM_MODE_ROTATE_90 |
+		 DRM_MODE_ROTATE_270)) {
+	case DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = (transform_tmp & 0xf);
+
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_REFLECT_X:
+		transform_tmp = act_xoffset + width;
+		transform_xoffset = 16 - (transform_tmp & 0xf);
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_REFLECT_Y:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	case DRM_MODE_ROTATE_90:
+		transform_tmp = bottom_crop_line_num - act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case DRM_MODE_ROTATE_270:
+		transform_tmp = top_crop_line_num + act_yoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = vir_width - width - act_xoffset;
+		transform_yoffset = transform_tmp & 0xf;
+		break;
+	case 0:
+		transform_tmp = act_xoffset;
+		transform_xoffset = transform_tmp & 0xf;
+		transform_tmp = top_crop_line_num + act_yoffset;
+
+		if (afbc_half_block_en)
+			transform_yoffset = transform_tmp & 0x7;
+		else
+			transform_yoffset = transform_tmp & 0xf;
+
+		break;
+	}
+
+	return (transform_xoffset & 0xf) | ((transform_yoffset & 0xf) << 16);
+}
+
+/*
+ * A Cluster window has 2048 x 16 line buffer, which can
+ * works at 2048 x 16(Full) or 4096 x 8 (Half) mode.
+ * for Cluster_lb_mode register:
+ * 0: half mode, for plane input width range 2048 ~ 4096
+ * 1: half mode, for cluster work at 2 * 2048 plane mode
+ * 2: half mode, for rotate_90/270 mode
+ *
+ */
+static int vop2_get_cluster_lb_mode(struct vop2_win *win, struct drm_plane_state *pstate)
+{
+	if ((pstate->rotation & DRM_MODE_ROTATE_270) || (pstate->rotation & DRM_MODE_ROTATE_90))
+		return 2;
+	else if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * bli_sd_factor = (src - 1) / (dst - 1) << 12;
+ * avg_sd_factor:
+ * bli_su_factor:
+ * bic_su_factor:
+ * = (src - 1) / (dst - 1) << 16;
+ *
+ * gt2 enable: dst get one line from two line of the src
+ * gt4 enable: dst get one line from four line of the src.
+ *
+ */
+
+static uint16_t vop2_scale_factor(enum scale_mode mode,
+				  int32_t filter_mode,
+				  uint32_t src, uint32_t dst)
+{
+	uint32_t fac;
+	int i;
+
+	if (mode == SCALE_NONE)
+		return 0;
+
+	/*
+	 * A workaround to avoid zero div.
+	 */
+	if ((dst == 1) || (src == 1)) {
+		dst = dst + 1;
+		src = src + 1;
+	}
+
+	if ((mode == SCALE_DOWN) && (filter_mode == VOP2_SCALE_DOWN_BIL)) {
+		fac = ((src - 1) << 12) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 12 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("down fac cali: src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	} else {
+		fac = ((src - 1) << 16) / (dst - 1);
+		for (i = 0; i < 100; i++) {
+			if (fac * (dst - 1) >> 16 < (src - 1))
+				break;
+			fac -= 1;
+			DRM_DEBUG("up fac cali:  src:%d, dst:%d, fac:0x%x\n", src, dst, fac);
+		}
+	}
+
+	return fac;
+}
+
+static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
+			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+			     uint32_t dst_h, uint32_t pixel_format)
+{
+	const struct vop2_win_data *win_data = win->data;
+	const struct drm_format_info *info;
+	uint16_t cbcr_src_w;
+	uint16_t cbcr_src_h;
+	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
+	uint16_t cbcr_hor_scl_mode, cbcr_ver_scl_mode;
+	uint16_t hscl_filter_mode, vscl_filter_mode;
+	uint8_t gt2 = 0;
+	uint8_t gt4 = 0;
+	uint32_t val;
+
+	info = drm_format_info(pixel_format);
+
+	cbcr_src_w = src_w / info->hsub;
+	cbcr_src_h = src_h / info->vsub;
+
+	if (src_h >= (4 * dst_h)) {
+		gt4 = 1;
+		src_h >>= 2;
+	} else if (src_h >= (2 * dst_h)) {
+		gt2 = 1;
+		src_h >>= 1;
+	}
+
+	yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
+	yrgb_ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
+
+	if (yrgb_hor_scl_mode == SCALE_UP)
+		hscl_filter_mode = win_data->hsu_filter_mode;
+	else
+		hscl_filter_mode = win_data->hsd_filter_mode;
+
+	if (yrgb_ver_scl_mode == SCALE_UP)
+		vscl_filter_mode = win_data->vsu_filter_mode;
+	else
+		vscl_filter_mode = win_data->vsd_filter_mode;
+
+	/*
+	 * RK3568 VOP Esmart/Smart dsp_w should be even pixel
+	 * at scale down mode
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if ((yrgb_hor_scl_mode == SCALE_DOWN) && (dst_w & 0x1)) {
+			drm_dbg(vop2->drm, "%s dst_w[%d] should align as 2 pixel\n", win->data->name, dst_w);
+			dst_w += 1;
+		}
+	}
+
+	val = vop2_scale_factor(yrgb_hor_scl_mode, hscl_filter_mode,
+				src_w, dst_w);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_x, val);
+	val = vop2_scale_factor(yrgb_ver_scl_mode, vscl_filter_mode,
+				src_h, dst_h);
+	vop2_win_write(win, &win->regs->scl->scale_yrgb_y, val);
+
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt4, gt4);
+	vop2_win_write(win, &win->regs->scl->vsd_yrgb_gt2, gt2);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+
+	vop2_win_write(win, &win->regs->scl->yrgb_hscl_filter_mode, hscl_filter_mode);
+	vop2_win_write(win, &win->regs->scl->yrgb_vscl_filter_mode, vscl_filter_mode);
+
+	if (info->is_yuv) {
+		gt4 = gt2 = 0;
+
+		if (cbcr_src_h >= (4 * dst_h))
+			gt4 = 1;
+		else if (cbcr_src_h >= (2 * dst_h))
+			gt2 = 1;
+
+		if (gt4)
+			cbcr_src_h >>= 2;
+		else if (gt2)
+			cbcr_src_h >>= 1;
+
+		cbcr_hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
+		cbcr_ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
+
+		val = vop2_scale_factor(cbcr_hor_scl_mode, hscl_filter_mode,
+					cbcr_src_w, dst_w);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_x, val);
+		val = vop2_scale_factor(cbcr_ver_scl_mode, vscl_filter_mode,
+					cbcr_src_h, dst_h);
+		vop2_win_write(win, &win->regs->scl->scale_cbcr_y, val);
+
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt4, gt4);
+		vop2_win_write(win, &win->regs->scl->vsd_cbcr_gt2, gt2);
+		vop2_win_write(win, &win->regs->scl->cbcr_hor_scl_mode, cbcr_hor_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_ver_scl_mode, cbcr_ver_scl_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_hscl_filter_mode, hscl_filter_mode);
+		vop2_win_write(win, &win->regs->scl->cbcr_vscl_filter_mode, vscl_filter_mode);
+	}
+}
+
+static int vop2_convert_csc_mode(int csc_mode)
+{
+	switch (csc_mode) {
+	case V4L2_COLORSPACE_SMPTE170M:
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		return CSC_BT601L;
+	case V4L2_COLORSPACE_REC709:
+	case V4L2_COLORSPACE_SMPTE240M:
+	case V4L2_COLORSPACE_DEFAULT:
+		return CSC_BT709L;
+	case V4L2_COLORSPACE_JPEG:
+		return CSC_BT601F;
+	case V4L2_COLORSPACE_BT2020:
+		return CSC_BT2020;
+	default:
+		return CSC_BT709L;
+	}
+}
+
+static bool vop2_is_allwin_disabled(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	unsigned long win_mask = vp->win_mask;
+	struct vop2_win *win;
+	int phys_id;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		if (vop2_win_read(win, &win->regs->enable) != 0)
+			return false;
+	}
+
+	return true;
+}
+
+static void vop2_disable_all_planes_for_crtc(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct vop2_win *win;
+	unsigned long win_mask = vp->win_mask;
+	int phys_id, ret;
+	bool active, need_wait_win_disabled = false;
+
+	for_each_set_bit(phys_id, &win_mask, ROCKCHIP_MAX_LAYER) {
+		win = vop2_find_win_by_phys_id(vop2, phys_id);
+		need_wait_win_disabled |= vop2_win_read(win, &win->regs->enable);
+		vop2_win_disable(win);
+	}
+
+	if (need_wait_win_disabled) {
+		vop2_cfg_done(vp);
+		ret = readx_poll_timeout_atomic(vop2_is_allwin_disabled, vp,
+						active, active, 0, 500 * 1000);
+		if (ret)
+			drm_err(vop2->drm, "wait win close timeout\n");
+	}
+}
+
+/*
+ * colorspace path:
+ *      Input        Win csc                     Output
+ * 1. YUV(2020)  --> Y2R->2020To709->R2Y   --> YUV_OUTPUT(601/709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 2. YUV(2020)  --> bypasss               --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 3. YUV(2020)  --> Y2R->2020To709        --> RGB_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 4. YUV(601/709)-> Y2R->709To2020->R2Y   --> YUV_OUTPUT(2020)
+ *    RGB        --> 709To2020->R2Y       __/
+ *
+ * 5. YUV(601/709)-> bypass                --> YUV_OUTPUT(709)
+ *    RGB        --> R2Y                  __/
+ *
+ * 6. YUV(601/709)-> bypass                --> YUV_OUTPUT(601)
+ *    RGB        --> R2Y(601)             __/
+ *
+ * 7. YUV        --> Y2R(709)              --> RGB_OUTPUT(709)
+ *    RGB        --> bypass               __/
+ *
+ * 8. RGB        --> 709To2020->R2Y        --> YUV_OUTPUT(2020)
+ *
+ * 9. RGB        --> R2Y(709)              --> YUV_OUTPUT(709)
+ *
+ * 10. RGB       --> R2Y(601)              --> YUV_OUTPUT(601)
+ *
+ * 11. RGB       --> bypass                --> RGB_OUTPUT(709)
+ */
+
+static void vop2_setup_csc_mode(struct vop2_video_port *vp,
+				struct vop2_win *win,
+				struct drm_plane_state *pstate)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state);
+	int is_input_yuv = is_yuv_support(pstate->fb->format->format);
+	int is_output_yuv = is_yuv_output(vcstate->bus_format);
+	int input_csc = V4L2_COLORSPACE_DEFAULT;
+	int output_csc = vcstate->color_space;
+	bool r2y_en, y2r_en;
+	int csc_mode;
+
+	if (is_input_yuv && !is_output_yuv) {
+		y2r_en = 1;
+		r2y_en = 0;
+		csc_mode = vop2_convert_csc_mode(input_csc);
+	} else if (!is_input_yuv && is_output_yuv) {
+		y2r_en = 0;
+		r2y_en = 1;
+		csc_mode = vop2_convert_csc_mode(output_csc);
+	} else {
+		y2r_en = 0;
+		r2y_en = 0;
+		csc_mode = 0;
+	}
+
+	vop2_win_write(win, &win->regs->y2r_en, y2r_en);
+	vop2_win_write(win, &win->regs->r2y_en, r2y_en);
+	vop2_win_write(win, &win->regs->csc_mode, csc_mode);
+}
+
+static void vop2_axi_irqs_enable(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr;
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t i;
+
+	for (i = 0; i < vop2_data->nr_axi_intr; i++) {
+		intr = &vop2_data->axi_intr[i];
+		vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+		vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+	}
+}
+
+static uint32_t vop2_read_and_clear_axi_irqs(struct vop2 *vop2, int index)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop_intr *intr = &vop2_data->axi_intr[index];
+	uint32_t irqs = BUS_ERROR_INTR;
+	uint32_t val;
+
+	val = vop2_get_intr_type(vop2, intr, &intr->status, irqs);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+
+	return val;
+}
+
+static void vop2_dsp_hold_valid_irq_enable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, DSP_HOLD_VALID_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_dsp_hold_valid_irq_disable(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, DSP_HOLD_VALID_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static void vop2_debug_irq_enable(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	uint32_t irqs = POST_BUF_EMPTY_INTR;
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, irqs, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, irqs, 1);
+}
+
+static bool vop2_dsp_lut_is_enabled(struct vop2_video_port *vp)
+{
+	return vop2_read(vp->vop2, &vp->regs->dsp_lut_en);
+}
+
+/*
+ * (1) each frame starts at the start of the Vsync pulse which is signaled by
+ *     the "FRAME_SYNC" interrupt.
+ * (2) the active data region of each frame ends at dsp_vact_end
+ * (3) we should program this same number (dsp_vact_end) into dsp_line_frag_num,
+ *      to get "LINE_FLAG" interrupt at the end of the active on screen data.
+ *
+ * VOP_INTR_CTRL0.dsp_line_frag_num = VOP_DSP_VACT_ST_END.dsp_vact_end
+ * Interrupts
+ * LINE_FLAG -------------------------------+
+ * FRAME_SYNC ----+                         |
+ *                |                         |
+ *                v                         v
+ *                | Vsync | Vbp |  Vactive  | Vfp |
+ *                        ^     ^           ^     ^
+ *                        |     |           |     |
+ *                        |     |           |     |
+ * dsp_vs_end ------------+     |           |     |   VOP_DSP_VTOTAL_VS_END
+ * dsp_vact_start --------------+           |     |   VOP_DSP_VACT_ST_END
+ * dsp_vact_end ----------------------------+     |   VOP_DSP_VACT_ST_END
+ * dsp_total -------------------------------------+   VOP_DSP_VTOTAL_VS_END
+ */
+
+static void vop2_crtc_load_lut(struct drm_crtc *crtc, struct drm_color_lut *lut)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int dle = 0, i = 0;
+	uint8_t vp_enable_gamma_nr = 0;
+
+	for (i = 0; i < vop2->data->nr_vps; i++) {
+		struct vop2_video_port *vp = &vop2->vps[i];
+
+		if (i == vp->id)
+			continue;
+
+		if (vp->gamma_lut_active)
+			vp_enable_gamma_nr++;
+	}
+
+	if (vp_enable_gamma_nr >= vop2->data->nr_gammas) {
+		drm_info(vop2->drm, "only support %d gamma\n", vop2->data->nr_gammas);
+		return;
+	}
+
+	spin_lock(&vop2->reg_lock);
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 0);
+	vop2_cfg_done(vp);
+	spin_unlock(&vop2->reg_lock);
+
+	readx_poll_timeout(vop2_dsp_lut_is_enabled, vp, dle, !dle, 5, 33333);
+
+	for (i = 0; i < vp->gamma_lut_len; i++) {
+		uint32_t r, g, b;
+		uint32_t ll = vp->gamma_lut_len;
+
+		r = lut[i].red * (ll - 1) / 0xffff;
+		g = lut[i].green * (ll - 1) / 0xffff;
+		b = lut[i].blue * (ll - 1) / 0xffff;
+		writel(b * ll * ll + g * ll + r, vop2->lut_regs + (i << 2));
+	}
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->dsp_lut_en, 1);
+	vop2_write(vop2, &vop2->data->ctrl->gamma_port_sel, vp->id);
+	vop2_cfg_done(vp);
+	vp->gamma_lut_active = true;
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static int vop2_core_clks_prepare_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = clk_prepare_enable(vop2->hclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable hclk - %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vop2->aclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable aclk - %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	clk_disable_unprepare(vop2->hclk);
+
+	return ret;
+}
+
+/*
+ * VOP2 architecture
+ *
+ +----------+   +-------------+                                                        +-----------+
+ |  Cluster |   | Sel 1 from 6|                                                        | 1 from 3  |
+ |  window0 |   |    Layer0   |                                                        |    RGB    |
+ +----------+   +-------------+              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 layers|    |             |
+ |  Cluster |   | Sel 1 from 6|              |   Overlay0    +--->| Video Port0 |      +-----------+
+ |  window1 |   |    Layer1   |              |               |    |             |      | 1 from 3  |
+ +----------+   +-------------+              +---------------+    +-------------+      |   LVDS    |
+ +----------+   +-------------+                                                        +-----------+
+ |  Esmart  |   | Sel 1 from 6|
+ |  window0 |   |   Layer2    |              +---------------+    +-------------+      +-----------+
+ +----------+   +-------------+              |N from 6 Layers|    |             | +--> | 1 from 3  |
+ +----------+   +-------------+   -------->  |   Overlay1    +--->| Video Port1 |      |   MIPI    |
+ |  Esmart  |   | Sel 1 from 6|   -------->  |               |    |             |      +-----------+
+ |  Window1 |   |   Layer3    |              +---------------+    +-------------+
+ +----------+   +-------------+                                                        +-----------+
+ +----------+   +-------------+                                                        | 1 from 3  |
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |   HDMI    |
+ |  Window0 |   |    Layer4   |              |N from 6 Layers|    |             |      +-----------+
+ +----------+   +-------------+              |   Overlay2    +--->| Video Port2 |
+ +----------+   +-------------+              |               |    |             |      +-----------+
+ |  Smart   |   | Sel 1 from 6|              +---------------+    +-------------+      |  1 from 3 |
+ |  Window1 |   |    Layer5   |                                                        |    eDP    |
+ +----------+   +-------------+                                                        +-----------+
+ *
+ */
+
+static void vop2_enable(struct vop2 *vop2)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(vop2->dev);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
+		return;
+	}
+
+	ret = vop2_core_clks_prepare_enable(vop2);
+	if (ret) {
+		pm_runtime_put_sync(vop2->dev);
+		return;
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 0);
+
+	if (vop2->data->soc_id == 3566)
+		vop2_write(vop2, &vop2->data->ctrl->otp_en, 1);
+
+	memcpy(vop2->regsbak, vop2->regs, vop2->len);
+
+	vop2_write(vop2, &vop2->data->ctrl->cfg_done_en, 1);
+	/*
+	 * Disable auto gating, this is a workaround to
+	 * avoid display image shift when a window enabled.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->auto_gating_en, 0);
+	/*
+	 * Register OVERLAY_LAYER_SEL and OVERLAY_PORT_SEL should take effect immediately,
+	 * than windows configuration(CLUSTER/ESMART/SMART) can take effect according the
+	 * video port mux configuration as we wished.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 1);
+	/*
+	 * Let SYS_DSP_INFACE_EN/SYS_DSP_INFACE_CTRL/SYS_DSP_INFACE_POL take effect
+	 * immediately.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->if_ctrl_cfg_done_imd, 1);
+
+	vop2_axi_irqs_enable(vop2);
+}
+
+static void vop2_disable(struct vop2 *vop2)
+{
+	/*
+	 * vop2 standby complete, so iommu detach is safe.
+	 */
+	vop2_write(vop2, &vop2->data->ctrl->dma_stop, 1);
+
+	pm_runtime_put_sync(vop2->dev);
+
+	clk_disable_unprepare(vop2->aclk);
+	clk_disable_unprepare(vop2->hclk);
+}
+
+static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
+				     struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	int ret;
+
+	WARN_ON(vp->event);
+	vop2_lock(vop2);
+
+	drm_crtc_vblank_off(crtc);
+	vop2_disable_all_planes_for_crtc(vp);
+
+	/*
+	 * Vop standby will take effect at end of current frame,
+	 * if dsp hold valid irq happen, it means standby complete.
+	 *
+	 * we must wait standby complete when we want to disable aclk,
+	 * if not, memory bus maybe dead.
+	 */
+	reinit_completion(&vp->dsp_hold_completion);
+	vop2_dsp_hold_valid_irq_enable(crtc);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->standby, 1);
+
+	spin_unlock(&vop2->reg_lock);
+
+	ret = wait_for_completion_timeout(&vp->dsp_hold_completion, msecs_to_jiffies(50));
+	if (!ret)
+		drm_info(vop2->drm, "wait for vp%d dsp_hold timeout\n", vp->id);
+
+	vop2_dsp_hold_valid_irq_disable(crtc);
+
+	clk_disable_unprepare(vp->dclk);
+
+	vop2->enable_count--;
+
+	if (!vop2->enable_count)
+		vop2_disable(vop2);
+
+	vop2_unlock(vop2);
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *astate)
+{
+	struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(astate, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct drm_framebuffer *fb = pstate->fb;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct drm_crtc_state *cstate;
+	struct vop2_video_port *vp;
+	struct vop2 *vop2;
+	const struct vop2_data *vop2_data;
+	struct drm_rect *dest = &pstate->dst;
+	struct drm_rect *src = &pstate->src;
+	int min_scale = win->regs->scl ? FRAC_16_16(1, 8) : DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = win->regs->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING;
+	int format;
+	int ret;
+
+	if (!crtc)
+		return 0;
+
+	vp = to_vop2_video_port(crtc);
+	vop2 = vp->vop2;
+	vop2_data = vop2->data;
+
+	cstate = drm_atomic_get_existing_crtc_state(pstate->state, crtc);
+	if (WARN_ON(!cstate))
+		return -EINVAL;
+
+	ret = drm_atomic_helper_check_plane_state(pstate, cstate,
+						  min_scale, max_scale,
+						  true, true);
+	if (ret)
+		return ret;
+
+	if (!pstate->visible)
+		return 0;
+
+	format = vop2_convert_format(fb->format->format);
+	if (format < 0)
+		return format;
+
+	if (drm_rect_width(src) >> 16 < 4 || drm_rect_height(src) >> 16 < 4 ||
+	    drm_rect_width(dest) < 4 || drm_rect_width(dest) < 4) {
+		drm_err(vop2->drm, "Invalid size: %dx%d->%dx%d, min size is 4x4\n",
+			  drm_rect_width(src) >> 16, drm_rect_height(src) >> 16,
+			  drm_rect_width(dest), drm_rect_height(dest));
+		pstate->visible = false;
+		return 0;
+	}
+
+	if (drm_rect_width(src) >> 16 > vop2_data->max_input.width ||
+	    drm_rect_height(src) >> 16 > vop2_data->max_input.height) {
+		drm_err(vop2->drm, "Invalid source: %dx%d. max input: %dx%d\n",
+			  drm_rect_width(src) >> 16,
+			  drm_rect_height(src) >> 16,
+			  vop2_data->max_input.width,
+			  vop2_data->max_input.height);
+		return -EINVAL;
+	}
+
+	/*
+	 * Src.x1 can be odd when do clip, but yuv plane start point
+	 * need align with 2 pixel.
+	 */
+	if (fb->format->is_yuv && ((pstate->src.x1 >> 16) % 2)) {
+		drm_err(vop2->drm, "Invalid Source: Yuv format not support odd xpos\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vop2_plane_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(state, plane);
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2 *vop2 = win->vop2;
+
+	drm_dbg(vop2->drm, "%s disable\n", win->data->name);
+
+	if (!old_pstate->crtc)
+		return;
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_win_disable(win);
+	vop2_win_write(win, &win->regs->yuv_clip, 0);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * The color key is 10 bit, so all format should
+ * convert to 10 bit here.
+ */
+static void vop2_plane_setup_color_key(struct drm_plane *plane, uint32_t color_key)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_framebuffer *fb = pstate->fb;
+	struct vop2_win *win = to_vop2_win(plane);
+	uint32_t color_key_en = 0;
+	uint32_t r = 0;
+	uint32_t g = 0;
+	uint32_t b = 0;
+
+	if (!(color_key & VOP2_COLOR_KEY_MASK) || fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->color_key_en, 0);
+		return;
+	}
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+		r = (color_key & 0xf800) >> 11;
+		g = (color_key & 0x7e0) >> 5;
+		b = (color_key & 0x1f);
+		r <<= 5;
+		g <<= 4;
+		b <<= 5;
+		color_key_en = 1;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+		r = (color_key & 0xff0000) >> 16;
+		g = (color_key & 0xff00) >> 8;
+		b = (color_key & 0xff);
+		r <<= 2;
+		g <<= 2;
+		b <<= 2;
+		color_key_en = 1;
+		break;
+	}
+
+	vop2_win_write(win, &win->regs->color_key_en, color_key_en);
+	vop2_win_write(win, &win->regs->color_key, (r << 20) | (g << 10) | b);
+}
+
+static void vop2_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state)
+{
+	struct drm_plane_state *pstate = plane->state;
+	struct drm_crtc *crtc = pstate->crtc;
+	struct vop2_win *win = to_vop2_win(plane);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = win->vop2;
+	struct drm_framebuffer *fb = pstate->fb;
+	uint32_t bpp = fb->format->cpp[0] * 8;
+	uint32_t actual_w, actual_h, dsp_w, dsp_h;
+	uint32_t act_info, dsp_info;
+	uint32_t format;
+	uint32_t afbc_format;
+	uint32_t rb_swap;
+	uint32_t uv_swap;
+	struct drm_rect *src = &pstate->src;
+	struct drm_rect *dest = &pstate->dst;
+	uint32_t afbc_tile_num;
+	uint32_t afbc_half_block_en;
+	uint32_t transform_offset;
+	bool dither_up;
+	bool xmirror = pstate->rotation & DRM_MODE_REFLECT_X;
+	bool ymirror = pstate->rotation & DRM_MODE_REFLECT_Y;
+	bool rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270;
+	bool rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90;
+	struct rockchip_gem_object *rk_obj;
+	unsigned long offset;
+	bool afbc_en;
+	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
+
+	/*
+	 * can't update plane when vop2 is disabled.
+	 */
+	if (WARN_ON(!crtc))
+		return;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	if (!pstate->visible) {
+		vop2_plane_atomic_disable(plane, state);
+		return;
+	}
+
+	/*
+	 * This means this window is moved from another vp
+	 * so the VOP2_PORT_SEL register is changed and
+	 * take effect by vop2_wait_for_port_mux_done
+	 * in this commit. so we can continue configure
+	 * the window and report vsync
+	 */
+	if (win->old_vp_mask != win->vp_mask) {
+		win->old_vp_mask = win->vp_mask;
+		vp->skip_vsync = false;
+	}
+
+	afbc_en = rockchip_afbc(plane, fb->modifier);
+
+	offset = (src->x1 >> 16) * fb->format->cpp[0];
+
+	/*
+	 * AFBC HDR_PTR must set to the zero offset of the framebuffer.
+	 */
+	if (afbc_en)
+		offset = 0;
+	else if (pstate->rotation & DRM_MODE_REFLECT_Y)
+		offset += ((src->y2 >> 16) - 1) * fb->pitches[0];
+	else
+		offset += (src->y1 >> 16) * fb->pitches[0];
+
+	rk_obj = to_rockchip_obj(fb->obj[0]);
+
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
+	if (fb->format->is_yuv) {
+		int hsub = fb->format->hsub;
+		int vsub = fb->format->vsub;
+
+		offset = (src->x1 >> 16) * fb->format->cpp[1] / hsub;
+		offset += (src->y1 >> 16) * fb->pitches[1] / vsub;
+
+		if ((pstate->rotation & DRM_MODE_REFLECT_Y) && !afbc_en)
+			offset += fb->pitches[1] * ((pstate->src_h >> 16) - 2)  / vsub;
+
+		rk_obj = to_rockchip_obj(fb->obj[0]);
+		uv_mst = rk_obj->dma_addr + offset + fb->offsets[1];
+	}
+
+	actual_w = drm_rect_width(src) >> 16;
+	actual_h = drm_rect_height(src) >> 16;
+	dsp_w = drm_rect_width(dest);
+
+	if (dest->x1 + dsp_w > adjusted_mode->hdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->x1[%d] + dsp_w[%d] exceed mode hdisplay[%d]\n",
+			  vp->id, win->data->name, dest->x1, dsp_w, adjusted_mode->hdisplay);
+		dsp_w = adjusted_mode->hdisplay - dest->x1;
+		if (dsp_w < 4)
+			dsp_w = 4;
+		actual_w = dsp_w * actual_w / drm_rect_width(dest);
+	}
+
+	dsp_h = drm_rect_height(dest);
+
+	if (dest->y1 + dsp_h > adjusted_mode->vdisplay) {
+		drm_err(vop2->drm, "vp%d %s dest->y1[%d] + dsp_h[%d] exceed mode vdisplay[%d]\n",
+			  vp->id, win->data->name, dest->y1, dsp_h, adjusted_mode->vdisplay);
+		dsp_h = adjusted_mode->vdisplay - dest->y1;
+		if (dsp_h < 4)
+			dsp_h = 4;
+		actual_h = dsp_h * actual_h / drm_rect_height(dest);
+	}
+
+	/*
+	 * This is workaround solution for IC design:
+	 * esmart can't support scale down when actual_w % 16 == 1.
+	 */
+	if (!(win->data->feature & WIN_FEATURE_AFBDC)) {
+		if (actual_w > dsp_w && (actual_w & 0xf) == 1) {
+			drm_err(vop2->drm, "vp%d %s act_w[%d] MODE 16 == 1\n", vp->id, win->data->name, actual_w);
+			actual_w -= 1;
+		}
+	}
+
+	if (afbc_en && actual_w % 4) {
+		drm_err(vop2->drm, "vp%d %s actual_w[%d] should align as 4 pixel when enable afbc\n",
+			  vp->id, win->data->name, actual_w);
+		actual_w = ALIGN_DOWN(actual_w, 4);
+	}
+
+	act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
+	dsp_info = (dsp_h - 1) << 16 | ((dsp_w - 1) & 0xffff);
+
+	format = vop2_convert_format(fb->format->format);
+
+	spin_lock(&vop2->reg_lock);
+	drm_dbg(vop2->drm, "vp%d update %s[%dx%d->%dx%d@%dx%d] fmt[%p4cc_%s] addr[%pad]\n",
+		      vp->id, win->data->name, actual_w, actual_h, dsp_w, dsp_h,
+		      dest->x1, dest->y1,
+		      &fb->format->format,
+		      afbc_en ? "AFBC" : "", &yrgb_mst);
+
+	if (afbc_en) {
+		uint32_t stride;
+
+		/* the afbc superblock is 16 x 16 */
+		afbc_format = vop2_convert_afbc_format(fb->format->format);
+
+		/* Enable color transform for YTR */
+		if (fb->modifier & AFBC_FORMAT_MOD_YTR)
+			afbc_format |= (1 << 4);
+
+		afbc_tile_num = ALIGN(actual_w, 16) >> 4;
+
+		/*
+		 * AFBC pic_vir_width is count by pixel, this is different
+		 * with WIN_VIR_STRIDE.
+		 */
+		stride = (fb->pitches[0] << 3) / bpp;
+		if ((stride & 0x3f) && (xmirror || rotate_90 || rotate_270))
+			drm_err(vop2->drm, "vp%d %s stride[%d] must align as 64 pixel when enable xmirror/rotate_90/rotate_270[0x%x]\n",
+				  vp->id, win->data->name, stride, pstate->rotation);
+
+		rb_swap = vop2_afbc_rb_swap(fb->format->format);
+		uv_swap = vop2_afbc_uv_swap(fb->format->format);
+		/*
+		 * This is a workaround for crazy IC design, Cluster
+		 * and Esmart/Smart use different format configuration map:
+		 * YUV420_10BIT: 0x10 for Cluster, 0x14 for Esmart/Smart.
+		 *
+		 * This is one thing we can make the convert simple:
+		 * AFBCD decode all the YUV data to YUV444. So we just
+		 * set all the yuv 10 bit to YUV444_10.
+		 */
+		if (fb->format->is_yuv && (bpp == 10))
+			format = VOP2_CLUSTER_YUV444_10;
+
+		afbc_half_block_en = vop2_afbc_half_block_enable(pstate);
+		transform_offset = vop2_afbc_transform_offset(pstate, afbc_half_block_en);
+		if (vop2_cluster_window(win))
+			vop2_win_write(win, &win->regs->cluster->afbc_enable, 1);
+		vop2_win_write(win, &win->regs->afbc->format, afbc_format);
+		vop2_win_write(win, &win->regs->afbc->rb_swap, rb_swap);
+		vop2_win_write(win, &win->regs->afbc->uv_swap, uv_swap);
+		vop2_win_write(win, &win->regs->afbc->auto_gating_en, 0);
+		vop2_win_write(win, &win->regs->afbc->block_split_en, 0);
+		vop2_win_write(win, &win->regs->afbc->half_block_en, afbc_half_block_en);
+		vop2_win_write(win, &win->regs->afbc->hdr_ptr, yrgb_mst);
+		vop2_win_write(win, &win->regs->afbc->pic_size, act_info);
+		vop2_win_write(win, &win->regs->afbc->transform_offset, transform_offset);
+		vop2_win_write(win, &win->regs->afbc->pic_offset, ((src->x1 >> 16) | src->y1));
+		vop2_win_write(win, &win->regs->afbc->dsp_offset, (dest->x1 | (dest->y1 << 16)));
+		vop2_win_write(win, &win->regs->afbc->pic_vir_width, stride);
+		vop2_win_write(win, &win->regs->afbc->tile_num, afbc_tile_num);
+		vop2_win_write(win, &win->regs->afbc->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->afbc->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->afbc->rotate_270, rotate_270);
+		vop2_win_write(win, &win->regs->afbc->rotate_90, rotate_90);
+	} else {
+		if (win->regs->afbc)
+			vop2_win_write(win, &win->regs->afbc->enable, 0);
+		vop2_win_write(win, &win->regs->ymirror, ymirror);
+		vop2_win_write(win, &win->regs->xmirror, xmirror);
+		vop2_win_write(win, &win->regs->yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
+	}
+
+	if (rotate_90 || rotate_270) {
+		act_info = swahw32(act_info);
+		actual_w = drm_rect_height(src) >> 16;
+		actual_h = drm_rect_width(src) >> 16;
+	}
+
+	vop2_win_write(win, &win->regs->format, format);
+	vop2_win_write(win, &win->regs->yrgb_mst, yrgb_mst);
+
+	rb_swap = vop2_win_rb_swap(fb->format->format);
+	uv_swap = vop2_win_uv_swap(fb->format->format);
+	vop2_win_write(win, &win->regs->rb_swap, rb_swap);
+	vop2_win_write(win, &win->regs->uv_swap, uv_swap);
+
+	if (fb->format->is_yuv) {
+		vop2_win_write(win, &win->regs->uv_vir, DIV_ROUND_UP(fb->pitches[1], 4));
+		vop2_win_write(win, &win->regs->uv_mst, uv_mst);
+	}
+
+	vop2_setup_scale(vop2, win, actual_w, actual_h, dsp_w, dsp_h, fb->format->format);
+	vop2_plane_setup_color_key(plane, 0);
+	vop2_win_write(win, &win->regs->act_info, act_info);
+	vop2_win_write(win, &win->regs->dsp_info, dsp_info);
+	vop2_win_write(win, &win->regs->dsp_st, dest->y1 << 16 | (dest->x1 & 0xffff));
+
+	vop2_setup_csc_mode(vp, win, pstate);
+
+	dither_up = vop2_win_dither_up(fb->format->format);
+	vop2_win_write(win, &win->regs->dither_up, dither_up);
+
+	vop2_win_write(win, &win->regs->enable, 1);
+
+	if (vop2_cluster_window(win)) {
+		int lb_mode = vop2_get_cluster_lb_mode(win, pstate);
+
+		vop2_win_write(win, &win->regs->cluster->lb_mode, lb_mode);
+		vop2_win_write(win, &win->regs->cluster->enable, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120 ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		vop2_win_write(win, &win->regs->yuv_clip, 1);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static const struct drm_plane_helper_funcs vop2_plane_helper_funcs = {
+	.atomic_check = vop2_plane_atomic_check,
+	.atomic_update = vop2_plane_atomic_update,
+	.atomic_disable = vop2_plane_atomic_disable,
+};
+
+static const struct drm_plane_funcs vop2_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.format_mod_supported = rockchip_vop2_mod_supported,
+};
+
+static int vop2_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return -EPERM;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->clear, FS_FIELD_INTR, 1);
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 1);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	return 0;
+}
+
+static void vop2_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	unsigned long flags;
+
+	if (WARN_ON(!vop2->enable_count))
+		return;
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+
+	vop2_intr_set_type(vop2, intr, &intr->enable, FS_FIELD_INTR, 0);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+}
+
+static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adj_mode)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	drm_mode_set_crtcinfo(adj_mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE);
+
+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+		adj_mode->crtc_clock *= 2;
+
+	adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk,
+							   adj_mode->crtc_clock * 1000), 1000);
+
+	return true;
+}
+
+static void vop2_dither_setup(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+
+	switch (vcstate->bus_format) {
+	case MEDIA_BUS_FMT_RGB565_1X16:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB565);
+		break;
+	case MEDIA_BUS_FMT_RGB666_1X18:
+	case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:
+		vop2_write(vop2, &vp->regs->dither_down_en, 1);
+		vop2_write(vop2, &vp->regs->dither_down_mode, RGB888_TO_RGB666);
+		break;
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 1);
+		break;
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	case MEDIA_BUS_FMT_SRGB888_3X8:
+	case MEDIA_BUS_FMT_SRGB888_DUMMY_4X8:
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+	default:
+		vop2_write(vop2, &vp->regs->dither_down_en, 0);
+		vop2_write(vop2, &vp->regs->pre_dither_down_en, 0);
+		break;
+	}
+
+	vop2_write(vop2, &vp->regs->pre_dither_down_en,
+		       vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA ? 0 : 1);
+	vop2_write(vop2, &vp->regs->dither_down_sel, DITHER_DOWN_ALLEGRO);
+}
+
+static void vop2_post_config(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate =
+			to_rockchip_crtc_state(crtc->state);
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint32_t left_margin = 100, right_margin = 100, top_margin = 100, bottom_margin = 100;
+	uint16_t hsize = hdisplay * (left_margin + right_margin) / 200;
+	uint16_t vsize = vdisplay * (top_margin + bottom_margin) / 200;
+	uint16_t hact_end, vact_end;
+	uint32_t val;
+
+	vsize = rounddown(vsize, 2);
+	hsize = rounddown(hsize, 2);
+	hact_st += hdisplay * (100 - left_margin) / 200;
+	hact_end = hact_st + hsize;
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hpost_st_end, val);
+	vact_st += vdisplay * (100 - top_margin) / 200;
+	vact_end = vact_st + vsize;
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vpost_st_end, val);
+	val = scl_cal_scale2(vdisplay, vsize) << 16;
+	val |= scl_cal_scale2(hdisplay, hsize);
+	vop2_write(vop2, &vp->regs->post_scl_factor, val);
+
+#define POST_HORIZONTAL_SCALEDOWN_EN(x)		((x) << 0)
+#define POST_VERTICAL_SCALEDOWN_EN(x)		((x) << 1)
+	vop2_write(vop2, &vp->regs->post_scl_ctrl,
+		       POST_HORIZONTAL_SCALEDOWN_EN(hdisplay != hsize) |
+		       POST_VERTICAL_SCALEDOWN_EN(vdisplay != vsize));
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vsize;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vpost_st_end_f1, val);
+	}
+	vop2_write(vop2, &vp->regs->post_dsp_out_r2y,
+		       is_yuv_output(vcstate->bus_format));
+}
+
+/*
+ * if adjusted mode update, return true, else return false
+ */
+static bool vop2_crtc_mode_update(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_display_mode *mode = &vp->crtc.state->adjusted_mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	uint32_t htotal_sync = htotal << 16 | hsync_len;
+	uint32_t hactive_st_end = hact_st << 16 | hact_end;
+	uint32_t vtotal_sync = vtotal << 16 | vsync_len;
+	uint32_t vactive_st_end = vact_st << 16 | vact_end;
+	uint32_t crtc_clock = mode->crtc_clock * 100;
+
+	if (htotal_sync != vop2_read(vop2, &vp->regs->htotal_pw) ||
+	    hactive_st_end != vop2_read(vop2, &vp->regs->hact_st_end) ||
+	    vtotal_sync != vop2_read(vop2, &vp->regs->vtotal_pw) ||
+	    vactive_st_end != vop2_read(vop2, &vp->regs->vact_st_end) ||
+	    crtc_clock != clk_get_rate(vp->dclk))
+		return true;
+
+	return false;
+}
+
+static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	const struct vop_intr *intr = vp_data->intr;
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct drm_display_mode *mode = &crtc->state->mode;
+	uint16_t hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	uint16_t hdisplay = mode->crtc_hdisplay;
+	uint16_t htotal = mode->crtc_htotal;
+	uint16_t hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
+	uint16_t hact_end = hact_st + hdisplay;
+	uint16_t vdisplay = mode->crtc_vdisplay;
+	uint16_t vtotal = mode->crtc_vtotal;
+	uint16_t vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	uint16_t vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
+	uint16_t vact_end = vact_st + vdisplay;
+	bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	uint8_t out_mode;
+	bool dclk_inv, yc_swap;
+	int act_end;
+	uint32_t val;
+	int ret;
+
+	vop2_lock(vop2);
+
+	drm_info(vop2->drm, "Update mode to %dx%d%s%d, type: %d for vp%d, output 0x%08x %s %s\n",
+		     hdisplay, vdisplay, interlaced ? "i" : "p",
+		     drm_mode_vrefresh(mode), vcstate->output_type, vp->id,
+		     vcstate->output_if,
+		     vcstate->output_if & VOP_OUTPUT_IF_MIPI0 ? "MIPI0" : "",
+		     vcstate->output_if & VOP_OUTPUT_IF_HDMI0 ? "HDMI0" : ""
+		);
+
+	ret = clk_prepare_enable(vp->dclk);
+	if (ret < 0) {
+		drm_err(vop2->drm, "failed to enable dclk for video port%d - %d\n",
+			      vp->id, ret);
+		return;
+	}
+
+	if (!vop2->enable_count)
+		vop2_enable(vop2);
+
+	vop2->enable_count++;
+
+	vop2_debug_irq_enable(vp);
+
+	if (vop2_crtc_mode_update(vp))
+		vop2_disable_all_planes_for_crtc(vp);
+
+	dclk_inv = (vcstate->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0;
+	val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : BIT(HSYNC_POSITIVE);
+	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : BIT(VSYNC_POSITIVE);
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_RGB) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_dclk_inv, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT1120) {
+		vop2_write(vop2, &vop2->data->ctrl->rgb_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt1120_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt1120_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_BT656) {
+		vop2_write(vop2, &vop2->data->ctrl->bt656_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->rgb_mux, vp_data->id);
+		vop2_grf_writel(vop2, vop2->data->grf_ctrl->grf_bt656_clk_inv, !dclk_inv);
+		yc_swap = vop2_output_yc_swap(vcstate->bus_format);
+		vop2_write(vop2, &vop2->data->ctrl->bt656_yc_swap, yc_swap);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS0) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_LVDS1) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->lvds1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE |
+	    ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) {
+		vop2_write(vop2, &vop2->data->ctrl->lvds_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_mode, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vop2->data->ctrl->lvds_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI0) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_MIPI1) {
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->mipi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->mipi_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) {
+		vop2_write(vop2, &vp->regs->mipi_dual_en, 1);
+		if (vcstate->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP)
+			vop2_write(vop2, &vp->regs->mipi_dual_channel_swap, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) {
+		vop2_write(vop2, &vop2->data->ctrl->edp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_eDP1) {
+		vop2_write(vop2, &vop2->data->ctrl->edp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->edp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->edp_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->edp_dclk_pol, dclk_inv);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP0) {
+		vop2_write(vop2, &vop2->data->ctrl->dp0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_DP1) {
+		vop2_write(vop2, &vop2->data->ctrl->dp1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->dp1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->dp_dclk_pol, 0);
+		vop2_write(vop2, &vop2->data->ctrl->dp_pin_pol, val);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI0) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi0_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if (vcstate->output_if & VOP_OUTPUT_IF_HDMI1) {
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_en, 1);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi1_mux, vp_data->id);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_pin_pol, val);
+		vop2_write(vop2, &vop2->data->ctrl->hdmi_dclk_pol, 1);
+	}
+
+	if ((vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
+	     !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) ||
+	    vcstate->output_if & VOP_OUTPUT_IF_BT656)
+		out_mode = ROCKCHIP_OUT_MODE_P888;
+	else
+		out_mode = vcstate->output_mode;
+
+	vop2_write(vop2, &vp->regs->out_mode, out_mode);
+
+	if (vop2_output_uv_swap(vcstate->bus_format, vcstate->output_mode))
+		vop2_write(vop2, &vp->regs->dsp_data_swap, DSP_RB_SWAP);
+	else
+		vop2_write(vop2, &vp->regs->dsp_data_swap, 0);
+
+	vop2_dither_setup(crtc);
+
+	vop2_write(vop2, &vp->regs->htotal_pw, (htotal << 16) | hsync_len);
+	val = hact_st << 16;
+	val |= hact_end;
+	vop2_write(vop2, &vp->regs->hact_st_end, val);
+
+	val = vact_st << 16;
+	val |= vact_end;
+	vop2_write(vop2, &vp->regs->vact_st_end, val);
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		uint16_t vact_st_f1 = vtotal + vact_st + 1;
+		uint16_t vact_end_f1 = vact_st_f1 + vdisplay;
+
+		val = vact_st_f1 << 16 | vact_end_f1;
+		vop2_write(vop2, &vp->regs->vact_st_end_f1, val);
+
+		val = vtotal << 16 | (vtotal + vsync_len);
+		vop2_write(vop2, &vp->regs->vs_st_end_f1, val);
+		vop2_write(vop2, &vp->regs->dsp_interlace, 1);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 1);
+		vop2_write(vop2, &vp->regs->p2i_en, 1);
+		vtotal += vtotal + 1;
+		act_end = vact_end_f1;
+	} else {
+		vop2_write(vop2, &vp->regs->dsp_interlace, 0);
+		vop2_write(vop2, &vp->regs->dsp_filed_pol, 0);
+		vop2_write(vop2, &vp->regs->p2i_en, 0);
+		act_end = vact_end;
+	}
+
+	vop2_write(vop2, &intr->line_flag_num[0], act_end);
+	vop2_write(vop2, &intr->line_flag_num[1],
+		     act_end - us_to_vertical_line(mode, 0));
+
+	vop2_write(vop2, &vp->regs->vtotal_pw, vtotal << 16 | vsync_len);
+
+	vop2_write(vop2, &vp->regs->core_dclk_div, !!(mode->flags & DRM_MODE_FLAG_DBLCLK));
+	if (vcstate->output_mode == ROCKCHIP_OUT_MODE_YUV420) {
+		vop2_write(vop2, &vp->regs->dclk_div2, 1);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 1);
+	} else {
+		vop2_write(vop2, &vp->regs->dclk_div2, 0);
+		vop2_write(vop2, &vp->regs->dclk_div2_phase_lock, 0);
+	}
+
+	clk_set_rate(vp->dclk, mode->crtc_clock * 1000);
+
+	vop2_post_config(crtc);
+
+	vop2_cfg_done(vp);
+
+	/*
+	 * when clear standby bits, it will take effect immediately,
+	 * This means the vp will start scan out immediately with
+	 * the timing it been configured before.
+	 * So we must make sure release standby after the display
+	 * timing is correctly configured.
+	 * This is important when switch resolution, such as
+	 * 4K-->720P:
+	 * if we release standby before 720P timing is configured,
+	 * the VP will start scan out immediately with 4K timing,
+	 * when we switch dclk to 74.25MHZ, VP timing is still 4K,
+	 * so VP scan out with 4K timing at 74.25MHZ dclk, this is
+	 * very slow, than this will trigger vblank timeout.
+	 *
+	 */
+	vop2_write(vop2, &vp->regs->standby, 0);
+
+	drm_crtc_vblank_on(crtc);
+
+	vop2_unlock(vop2);
+}
+
+static int vop2_zpos_cmp(const void *a, const void *b)
+{
+	struct vop2_zpos *pa = (struct vop2_zpos *)a;
+	struct vop2_zpos *pb = (struct vop2_zpos *)b;
+
+	if (pa->zpos != pb->zpos)
+		return pa->zpos - pb->zpos;
+	else
+		return pa->plane->base.id - pb->plane->base.id;
+}
+
+static int vop2_crtc_atomic_check(struct drm_crtc *crtc,
+				  struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+
+		if (abs(main_win->base.state->zpos - win->base.state->zpos) != 1) {
+			drm_err(vop2->drm, "vp%d Cluster%d win0[zpos:%d] must next to win1[zpos:%d]\n",
+				  vp->id, main_win->data->phys_id,
+				  main_win->base.state->zpos, win->base.state->zpos);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static bool is_opaque(uint16_t alpha)
+{
+	return (alpha >> 8) == 0xff;
+}
+
+static void vop2_parse_alpha(struct vop2_alpha_config *alpha_config,
+			     struct vop2_alpha *alpha)
+{
+	int src_glb_alpha_en = is_opaque(alpha_config->src_glb_alpha_value) ? 0 : 1;
+	int dst_glb_alpha_en = is_opaque(alpha_config->dst_glb_alpha_value) ? 0 : 1;
+	int src_color_mode = alpha_config->src_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+	int dst_color_mode = alpha_config->dst_premulti_en ? ALPHA_SRC_PRE_MUL : ALPHA_SRC_NO_PRE_MUL;
+
+	alpha->src_color_ctrl.val = 0;
+	alpha->dst_color_ctrl.val = 0;
+	alpha->src_alpha_ctrl.val = 0;
+	alpha->dst_alpha_ctrl.val = 0;
+
+	if (!alpha_config->src_pixel_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	else if (alpha_config->src_pixel_alpha_en && !src_glb_alpha_en)
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->src_color_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+
+	alpha->src_color_ctrl.bits.alpha_en = 1;
+
+	if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_GLOBAL) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	} else if (alpha->src_color_ctrl.bits.blend_mode == ALPHA_PER_PIX) {
+		alpha->src_color_ctrl.bits.color_mode = src_color_mode;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_ONE;
+	} else {
+		alpha->src_color_ctrl.bits.color_mode = ALPHA_SRC_PRE_MUL;
+		alpha->src_color_ctrl.bits.factor_mode = SRC_FAC_ALPHA_SRC_GLOBAL;
+	}
+	alpha->src_color_ctrl.bits.glb_alpha = alpha_config->src_glb_alpha_value >> 8;
+	alpha->src_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+
+	alpha->dst_color_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->dst_color_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->dst_color_ctrl.bits.blend_mode = ALPHA_GLOBAL;
+	alpha->dst_color_ctrl.bits.glb_alpha = alpha_config->dst_glb_alpha_value >> 8;
+	alpha->dst_color_ctrl.bits.color_mode = dst_color_mode;
+	alpha->dst_color_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+
+	alpha->src_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	alpha->src_alpha_ctrl.bits.blend_mode = alpha->src_color_ctrl.bits.blend_mode;
+	alpha->src_alpha_ctrl.bits.alpha_cal_mode = ALPHA_SATURATION;
+	alpha->src_alpha_ctrl.bits.factor_mode = ALPHA_ONE;
+
+	alpha->dst_alpha_ctrl.bits.alpha_mode = ALPHA_STRAIGHT;
+	if (alpha_config->dst_pixel_alpha_en && !dst_glb_alpha_en)
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX;
+	else
+		alpha->dst_alpha_ctrl.bits.blend_mode = ALPHA_PER_PIX_GLOBAL;
+	alpha->dst_alpha_ctrl.bits.alpha_cal_mode = ALPHA_NO_SATURATION;
+	alpha->dst_alpha_ctrl.bits.factor_mode = ALPHA_SRC_INVERSE;
+}
+
+static int vop2_find_start_mixer_id_for_vp(struct vop2 *vop2, uint8_t port_id)
+{
+	struct vop2_video_port *vp;
+	int used_layer = 0;
+	int i;
+
+	for (i = 0; i < port_id; i++) {
+		vp = &vop2->vps[i];
+		used_layer += hweight32(vp->win_mask);
+	}
+
+	return used_layer;
+}
+
+/*
+ * src: top layer
+ * dst: bottom layer.
+ * Cluster mixer default use win1 as top layer
+ */
+static void vop2_setup_cluster_alpha(struct vop2 *vop2, struct vop2_cluster *cluster)
+{
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->cluster0_src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->cluster0_dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->cluster0_src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->cluster0_dst_alpha_ctrl.offset;
+	uint32_t offset = (cluster->main->data->phys_id * 0x10);
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *main_win = cluster->main;
+	struct vop2_win *sub_win = cluster->sub;
+	struct drm_plane *main_plane;
+	struct drm_plane_state *top_win_pstate;
+	struct drm_plane_state *bottom_win_pstate;
+	bool src_pixel_alpha_en = false;
+	uint16_t src_glb_alpha_val, dst_glb_alpha_val;
+	bool premulti_en = false;
+	bool swap = false;
+
+	if (!sub_win) {
+		/* At one win mode, win0 is dst/bottom win, and win1 is a all zero src/top win */
+		top_win_pstate = NULL;
+		bottom_win_pstate = main_win->base.state;
+		src_glb_alpha_val = 0;
+		dst_glb_alpha_val = main_win->base.state->alpha;
+	} else {
+		if (main_win->base.state->zpos > sub_win->base.state->zpos) {
+			swap = 1;
+			top_win_pstate = main_plane->state;
+			bottom_win_pstate = sub_win->base.state;
+			src_glb_alpha_val = main_win->base.state->alpha;
+			dst_glb_alpha_val = sub_win->base.state->alpha;
+		} else {
+			swap = 0;
+			top_win_pstate = sub_win->base.state;
+			bottom_win_pstate = main_plane->state;
+			src_glb_alpha_val = sub_win->base.state->alpha;
+			dst_glb_alpha_val = main_win->base.state->alpha;
+		}
+
+		if (!top_win_pstate->fb)
+			return;
+
+		if (top_win_pstate->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = true;
+		else
+			premulti_en = false;
+
+		src_pixel_alpha_en = is_alpha_support(top_win_pstate->fb->format->format);
+	}
+
+	if (!bottom_win_pstate->fb)
+		return;
+
+	alpha_config.src_premulti_en = premulti_en;
+	alpha_config.dst_premulti_en = false;
+	alpha_config.src_pixel_alpha_en = src_pixel_alpha_en;
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	alpha_config.src_glb_alpha_value = src_glb_alpha_val;
+	alpha_config.dst_glb_alpha_value = dst_glb_alpha_val;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	alpha.src_color_ctrl.bits.src_dst_swap = swap;
+	vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+	vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+	vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+	vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+}
+
+static void vop2_setup_alpha(struct vop2_video_port *vp,
+			     const struct vop2_zpos *vop2_zpos, int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t src_color_ctrl_offset = vop2->data->ctrl->src_color_ctrl.offset;
+	uint32_t dst_color_ctrl_offset = vop2->data->ctrl->dst_color_ctrl.offset;
+	uint32_t src_alpha_ctrl_offset = vop2->data->ctrl->src_alpha_ctrl.offset;
+	uint32_t dst_alpha_ctrl_offset = vop2->data->ctrl->dst_alpha_ctrl.offset;
+	const struct vop2_zpos *zpos;
+	struct drm_framebuffer *fb;
+	struct vop2_alpha_config alpha_config;
+	struct vop2_alpha alpha;
+	struct vop2_win *win;
+	struct drm_plane *plane;
+	int pixel_alpha_en;
+	int premulti_en;
+	int mixer_id;
+	uint32_t offset;
+	int i;
+	bool bottom_layer_alpha_en = false;
+	uint32_t dst_global_alpha = 0xffff;
+
+	drm_atomic_crtc_for_each_plane(plane, &vp->crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (plane->state->zpos == 0 && !is_opaque(plane->state->alpha) &&
+		    !vop2_cluster_window(win)) {
+			/*
+			 * If bottom layer have global alpha effect [except cluster layer,
+			 * because cluster have deal with bottom layer global alpha value
+			 * at cluster mix], bottom layer mix need deal with global alpha.
+			 */
+			bottom_layer_alpha_en = true;
+			dst_global_alpha = plane->state->alpha;
+			break;
+		}
+	}
+
+	mixer_id = vop2_find_start_mixer_id_for_vp(vop2, vp->id);
+	alpha_config.dst_pixel_alpha_en = true; /* alpha value need transfer to next mix */
+	for (i = 1; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		fb = plane->state->fb;
+		if (plane->state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI)
+			premulti_en = 1;
+		else
+			premulti_en = 0;
+		pixel_alpha_en = is_alpha_support(fb->format->format);
+
+		alpha_config.src_premulti_en = premulti_en;
+		if (bottom_layer_alpha_en && i == 1) {/* Cd = Cs + (1 - As) * Cd * Agd */
+			alpha_config.dst_premulti_en = false;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = dst_global_alpha;
+		} else if (vop2_cluster_window(win)) {/* Mix output data only have pixel alpha */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = true;
+			alpha_config.src_glb_alpha_value = 0xffff;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		} else {/* Cd = Cs + (1 - As) * Cd */
+			alpha_config.dst_premulti_en = true;
+			alpha_config.src_pixel_alpha_en = pixel_alpha_en;
+			alpha_config.src_glb_alpha_value =  plane->state->alpha;
+			alpha_config.dst_glb_alpha_value = 0xffff;
+		}
+		vop2_parse_alpha(&alpha_config, &alpha);
+
+		offset = (mixer_id + i - 1) * 0x10;
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_color_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+
+		if (i == 1) {
+			if (bottom_layer_alpha_en) {
+				/* Transfer pixel alpha to hdr mix */
+				alpha_config.src_premulti_en = premulti_en;
+				alpha_config.dst_premulti_en = true;
+				alpha_config.src_pixel_alpha_en = true;
+				alpha_config.src_glb_alpha_value = 0xffff;
+				alpha_config.dst_glb_alpha_value = 0xffff;
+				vop2_parse_alpha(&alpha_config, &alpha);
+
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl,
+					       alpha.src_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_color_ctrl,
+					       alpha.dst_color_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_src_alpha_ctrl,
+					       alpha.src_alpha_ctrl.val);
+				vop2_write(vop2, &vp->regs->hdr_dst_alpha_ctrl,
+					       alpha.dst_alpha_ctrl.val);
+			} else {
+				vop2_write(vop2, &vp->regs->hdr_src_color_ctrl, 0);
+			}
+		}
+	}
+
+	/* Transfer pixel alpha value to next mix */
+	alpha_config.src_premulti_en = true;
+	alpha_config.dst_premulti_en = true;
+	alpha_config.src_pixel_alpha_en = false;
+	alpha_config.src_glb_alpha_value = 0xffff;
+	alpha_config.dst_glb_alpha_value = 0xffff;
+	vop2_parse_alpha(&alpha_config, &alpha);
+
+	for (; i < hweight32(vp->win_mask); i++) {
+		offset = (mixer_id + i - 1) * 0x10;
+
+		vop2_writel(vop2, src_color_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_color_ctrl_offset + offset, alpha.dst_color_ctrl.val);
+		vop2_writel(vop2, src_alpha_ctrl_offset + offset, alpha.src_alpha_ctrl.val);
+		vop2_writel(vop2, dst_alpha_ctrl_offset + offset, alpha.dst_alpha_ctrl.val);
+	}
+}
+
+static void vop2_setup_layer_mixer_for_vp(struct vop2_video_port *vp,
+					  const struct vop2_zpos *vop2_zpos,
+					  int nr_layers)
+{
+	struct vop2_video_port *vpt;
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_zpos *zpos;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint16_t port_mux_cfg = 0;
+	uint8_t port_mux;
+	uint8_t used_layers = 0;
+	int i, nlayer;
+
+	for (i = 0; i < vop2_data->nr_vps - 1; i++) {
+		vpt = &vop2->vps[i];
+		used_layers += hweight32(vpt->win_mask);
+
+		if (used_layers == 0)
+			port_mux = 8;
+		else
+			port_mux = used_layers - 1;
+
+		port_mux_cfg |= port_mux << (vpt->id * 4);
+
+		if (port_mux > vop2_data->nr_mixers)
+			vpt->bg_ovl_dly = 0;
+		else
+			vpt->bg_ovl_dly = (vop2_data->nr_mixers - port_mux) << 1;
+	}
+
+	if (vop2_data->nr_vps >= 1)
+		port_mux_cfg |= 7 << (4 * (vop2_data->nr_vps - 1));
+
+	nlayer = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		int j;
+
+		vpt = &vop2->vps[i];
+
+		for (j = 0; j < vpt->nr_layers; j++) {
+			layer = &vop2->layers[nlayer];
+			zpos = &vpt->zpos[j];
+			win = zpos->win;
+
+			vop2_write(vop2, &vop2->data->ctrl->win_vp_id[win->data->phys_id], vpt->id);
+			vop2_write(vop2, &layer->regs->layer_sel, win->data->layer_sel_id);
+			nlayer++;
+		}
+	}
+
+	for (; nlayer < vop2_data->nr_layers; nlayer++) {
+		layer = &vop2->layers[nlayer];
+
+		vop2_write(vop2, &layer->regs->layer_sel, 5);
+	}
+
+	vop2_write(vop2, &vop2->data->ctrl->ovl_cfg_done_port, vp->id);
+	vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg_done_imd, 0);
+
+	spin_lock(&vop2->reg_lock);
+	if (vop2->port_mux_cfg != port_mux_cfg) {
+		vop2_write(vop2, &vop2->data->ctrl->ovl_port_mux_cfg, port_mux_cfg);
+		vp->skip_vsync = true;
+		vop2_cfg_done(vp);
+		vop2->port_mux_cfg = port_mux_cfg;
+		vop2_wait_for_port_mux_done(vop2);
+	}
+	spin_unlock(&vop2->reg_lock);
+}
+
+/*
+ * HDR window is fixed(not move in the overlay path with port_mux change)
+ * and is the slowest window. And the bg is the fastest. So other windows
+ * and bg need to add delay number to keep align with the slowest window.
+ * The delay number list in the trm is a relative value for port_mux set at
+ * last level.
+ */
+static void vop2_setup_dly_for_vp(struct vop2_video_port *vp)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id];
+	struct drm_crtc *crtc = &vp->crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	uint16_t hsync_len = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
+	uint16_t hdisplay = adjusted_mode->crtc_hdisplay;
+	uint32_t bg_dly = vp_data->pre_scan_max_dly[0];
+	uint32_t pre_scan_dly;
+
+	bg_dly = vp_data->pre_scan_max_dly[3];
+	bg_dly -= vp->bg_ovl_dly;
+
+	pre_scan_dly = bg_dly + (hdisplay >> 1) - 1;
+	pre_scan_dly = (pre_scan_dly << 16) | hsync_len;
+	vop2_write(vop2, &vp->regs->bg_dly, bg_dly);
+	vop2_write(vop2, &vp->regs->pre_scan_htiming, pre_scan_dly);
+}
+
+static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
+				      int nr_layers)
+{
+	struct vop2 *vop2 = vp->vop2;
+	const struct vop2_zpos *zpos;
+	struct drm_plane *plane;
+	struct vop2_win *win;
+	uint32_t dly;
+	int i = 0;
+
+	for (i = 0; i < nr_layers; i++) {
+		zpos = &vop2_zpos[i];
+		win = zpos->win;
+		plane = &win->base;
+		dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
+
+		if (vop2_cluster_window(win))
+			dly |= dly << 8;
+
+		vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
+	}
+
+}
+static void vop2_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	struct vop2_zpos *vop2_zpos = vp->zpos;
+	struct vop2_cluster cluster;
+	uint8_t nr_layers = 0;
+
+	/* Process cluster sub windows overlay. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+		struct vop2_win *main_win;
+
+		win->two_win_mode = false;
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_SUB))
+			continue;
+		main_win = vop2_find_win_by_phys_id(vop2, win->data->phys_id);
+		cluster.main = main_win;
+		cluster.sub = win;
+		win->two_win_mode = true;
+		main_win->two_win_mode = true;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+
+	vp->win_mask = 0;
+
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		/*
+		 * Sub win of a cluster will be handled by pre overlay module automatically
+		 * win in multi area share the same overlay zorder with it's parent.
+		 */
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+		vp->win_mask |=  BIT(win->data->phys_id);
+		win->vp_mask = BIT(vp->id);
+		vop2_zpos[nr_layers].win = win;
+		vop2_zpos[nr_layers].zpos = plane->state->zpos;
+		vop2_zpos[nr_layers].plane = plane;
+		nr_layers++;
+		drm_dbg(vop2->drm, "%s active zpos:%d for vp%d\n",
+			     win->data->name, plane->state->zpos, vp->id);
+	}
+
+	vp->nr_layers = nr_layers;
+
+	drm_dbg(vop2->drm, "vp%d: %d windows, active layers %d\n",
+		      vp->id, hweight32(vp->win_mask), nr_layers);
+	if (nr_layers) {
+		sort(vop2_zpos, nr_layers, sizeof(vop2_zpos[0]), vop2_zpos_cmp, NULL);
+
+		vop2_setup_layer_mixer_for_vp(vp, vop2_zpos, nr_layers);
+		vop2_setup_alpha(vp, vop2_zpos, nr_layers);
+		vop2_setup_dly_for_vp(vp);
+		vop2_setup_dly_for_window(vp, vop2_zpos, nr_layers);
+	}
+
+	/* The pre alpha overlay of Cluster still need process in one win mode. */
+	drm_atomic_crtc_for_each_plane(plane, crtc) {
+		struct vop2_win *win = to_vop2_win(plane);
+
+		if (!(win->data->feature & WIN_FEATURE_CLUSTER_MAIN))
+			continue;
+		if (win->two_win_mode)
+			continue;
+		cluster.main = win;
+		cluster.sub = NULL;
+		vop2_setup_cluster_alpha(vop2, &cluster);
+	}
+}
+
+static void vop2_cfg_update(struct drm_crtc *crtc,
+			    struct drm_crtc_state *old_crtc_state)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+	struct vop2 *vop2 = vp->vop2;
+	uint32_t val;
+	bool yuv_overlay = is_yuv_output(vcstate->bus_format);
+
+	spin_lock(&vop2->reg_lock);
+
+	vop2_write(vop2, &vp->regs->overlay_mode, yuv_overlay);
+
+	if (yuv_overlay)
+		val = 0x20010200;
+	else
+		val = 0;
+
+	vop2_write(vop2, &vp->regs->dsp_background, val);
+
+	vop2_post_config(crtc);
+
+	spin_unlock(&vop2->reg_lock);
+}
+
+static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *old_cstate = drm_atomic_get_old_crtc_state(state, crtc);
+	struct drm_atomic_state *old_state = old_cstate->state;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	struct drm_plane_state *old_pstate;
+	struct vop2 *vop2 = vp->vop2;
+	struct drm_plane *plane;
+	unsigned long flags;
+	int i;
+
+	vop2_cfg_update(crtc, old_cstate);
+
+	if (crtc->state->color_mgmt_changed || crtc->state->active_changed) {
+		if (crtc->state->gamma_lut)
+			vop2_crtc_load_lut(crtc, crtc->state->gamma_lut->data);
+	} else {
+		vop2_write(vop2, &vp->regs->cubic_lut_update_en, 0);
+	}
+
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	vop2_cfg_done(vp);
+
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	/*
+	 * There is a (rather unlikely) possibility that a vblank interrupt
+	 * fired before we set the cfg_done bit. To avoid spuriously
+	 * signalling flip completion we need to wait for it to finish.
+	 */
+	vop2_wait_for_irq_handler(crtc);
+
+	/*
+	 * move here is to make sure current fs call function is complete,
+	 * so when layer_sel_update is true, we can skip current vblank correctly.
+	 */
+	vp->layer_sel_update = false;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		WARN_ON(vp->event);
+
+		vp->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+
+	for_each_old_plane_in_state(old_state, plane, old_pstate, i) {
+		if (!old_pstate->fb)
+			continue;
+
+		if (old_pstate->fb == plane->state->fb)
+			continue;
+
+		drm_framebuffer_get(old_pstate->fb);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		drm_flip_work_queue(&vp->fb_unref_work, old_pstate->fb);
+		set_bit(VOP_PENDING_FB_UNREF, &vp->pending);
+	}
+}
+
+static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = {
+	.mode_fixup = vop2_crtc_mode_fixup,
+	.atomic_check = vop2_crtc_atomic_check,
+	.atomic_begin = vop2_crtc_atomic_begin,
+	.atomic_flush = vop2_crtc_atomic_flush,
+	.atomic_enable = vop2_crtc_atomic_enable,
+	.atomic_disable = vop2_crtc_atomic_disable,
+};
+
+static void vop2_crtc_reset(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state);
+
+	if (crtc->state) {
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+		kfree(vcstate);
+	}
+
+	vcstate = kzalloc(sizeof(*vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return;
+	crtc->state = &vcstate->base;
+	crtc->state->crtc = crtc;
+}
+
+static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *vcstate, *old_vcstate;
+
+	old_vcstate = to_rockchip_crtc_state(crtc->state);
+	vcstate = kmemdup(old_vcstate, sizeof(*old_vcstate), GFP_KERNEL);
+	if (!vcstate)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &vcstate->base);
+
+	return &vcstate->base;
+}
+
+static void vop2_crtc_destroy_state(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state);
+
+	__drm_atomic_helper_crtc_destroy_state(&vcstate->base);
+	kfree(vcstate);
+}
+
+static const struct drm_crtc_funcs vop2_crtc_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.destroy = drm_crtc_cleanup,
+	.reset = vop2_crtc_reset,
+	.atomic_duplicate_state = vop2_crtc_duplicate_state,
+	.atomic_destroy_state = vop2_crtc_destroy_state,
+	.enable_vblank = vop2_crtc_enable_vblank,
+	.disable_vblank = vop2_crtc_disable_vblank,
+};
+
+static void vop2_fb_unref_worker(struct drm_flip_work *work, void *val)
+{
+	struct vop2_video_port *vp = container_of(work, struct vop2_video_port, fb_unref_work);
+	struct drm_framebuffer *fb = val;
+
+	drm_crtc_vblank_put(&vp->crtc);
+	drm_framebuffer_put(fb);
+}
+
+static void vop2_handle_vblank(struct vop2 *vop2, struct drm_crtc *crtc)
+{
+	struct drm_device *drm = vop2->drm;
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	if (vp->event) {
+		drm_crtc_send_vblank_event(crtc, vp->event);
+		drm_crtc_vblank_put(crtc);
+		vp->event = NULL;
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+
+	if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vp->pending))
+		drm_flip_work_commit(&vp->fb_unref_work, system_unbound_wq);
+}
+
+static uint32_t vop2_read_and_clear_active_vp_irqs(struct vop2 *vop2, int vp_id)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	const struct vop_intr *intr;
+	int val;
+
+	vp_data = &vop2_data->vp[vp_id];
+	intr = vp_data->intr;
+	val = vop2_get_intr_type(vop2, intr, &intr->status, VOP2_INTR_MASK);
+	if (val)
+		vop2_intr_set_type(vop2, intr, &intr->clear, val, 1);
+	return val;
+}
+
+static irqreturn_t vop2_isr(int irq, void *data)
+{
+	struct vop2 *vop2 = data;
+	struct drm_crtc *crtc;
+	struct vop2_video_port *vp;
+	const struct vop2_data *vop2_data = vop2->data;
+	size_t vp_max = min_t(size_t, vop2_data->nr_vps, ROCKCHIP_MAX_CRTC);
+	size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM);
+	uint32_t vp_irqs[ROCKCHIP_MAX_CRTC];
+	uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM];
+	uint32_t active_irqs;
+	unsigned long flags;
+	int ret = IRQ_NONE;
+	int i;
+
+	/*
+	 * The irq is shared with the iommu. If the runtime-pm state of the
+	 * vop2-device is disabled the irq has to be targeted at the iommu.
+	 */
+	if (!pm_runtime_get_if_in_use(vop2->dev))
+		return IRQ_NONE;
+
+	/*
+	 * interrupt register has interrupt status, enable and clear bits, we
+	 * must hold irq_lock to avoid a race with enable/disable_vblank().
+	 */
+	spin_lock_irqsave(&vop2->irq_lock, flags);
+	for (i = 0; i < vp_max; i++)
+		vp_irqs[i] = vop2_read_and_clear_active_vp_irqs(vop2, i);
+	for (i = 0; i < axi_max; i++)
+		axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i);
+	spin_unlock_irqrestore(&vop2->irq_lock, flags);
+
+	for (i = 0; i < vp_max; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		active_irqs = vp_irqs[i];
+		if (active_irqs & DSP_HOLD_VALID_INTR) {
+			complete(&vp->dsp_hold_completion);
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & FS_FIELD_INTR) {
+			if (likely(!vp->skip_vsync) || (vp->layer_sel_update == false)) {
+				drm_crtc_handle_vblank(crtc);
+				vop2_handle_vblank(vop2, crtc);
+			}
+			ret = IRQ_HANDLED;
+		}
+
+		if (active_irqs & POST_BUF_EMPTY_INTR) {
+			drm_err_ratelimited(vop2->drm,
+					    "POST_BUF_EMPTY irq err at vp%d\n",
+					    vp->id);
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	for (i = 0; i < axi_max; i++) {
+		active_irqs = axi_irqs[i];
+
+		if (active_irqs & BUS_ERROR_INTR) {
+			drm_err_ratelimited(vop2->drm, "BUS_ERROR irq err\n");
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	pm_runtime_put(vop2->dev);
+
+	return ret;
+}
+
+static int vop2_plane_init(struct vop2 *vop2, struct vop2_win *win, unsigned long possible_crtcs)
+{
+	const struct vop2_win_data *win_data = win->data;
+	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) | BIT(DRM_MODE_BLEND_PREMULTI) |
+				  BIT(DRM_MODE_BLEND_COVERAGE);
+	int ret;
+
+	ret = drm_universal_plane_init(vop2->drm, &win->base, possible_crtcs,
+				       &vop2_plane_funcs, win_data->formats, win_data->nformats,
+				       win_data->format_modifiers, win_data->type, win_data->name);
+	if (ret) {
+		drm_err(vop2->drm, "failed to initialize plane %d\n", ret);
+		return ret;
+	}
+
+	drm_plane_helper_add(&win->base, &vop2_plane_helper_funcs);
+
+	if (win->data->supported_rotations)
+		drm_plane_create_rotation_property(&win->base, DRM_MODE_ROTATE_0,
+						   DRM_MODE_ROTATE_0 | win->data->supported_rotations);
+	drm_plane_create_alpha_property(&win->base);
+	drm_plane_create_blend_mode_property(&win->base, blend_caps);
+	drm_plane_create_zpos_property(&win->base, win->win_id, 0, vop2->registered_num_wins - 1);
+
+	return 0;
+}
+
+static int vop2_gamma_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_video_port_data *vp_data;
+	struct vop2_video_port *vp;
+	struct drm_crtc *crtc;
+	int i = 0;
+	uint32_t lut_len = 0;
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		vp = &vop2->vps[i];
+		crtc = &vp->crtc;
+		if (!crtc->dev)
+			continue;
+		vp_data = &vop2_data->vp[vp->id];
+		lut_len = vp_data->gamma_lut_len;
+		vp->gamma_lut_len = vp_data->gamma_lut_len;
+
+		drm_mode_crtc_set_gamma_size(crtc, lut_len);
+		drm_crtc_enable_color_mgmt(crtc, 0, false, lut_len);
+	}
+
+	return 0;
+}
+
+static int vop2_create_crtc(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	struct drm_device *drm = vop2->drm;
+	struct device *dev = vop2->dev;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct device_node *port;
+	struct vop2_win *win = NULL;
+	struct vop2_video_port *vp;
+	const struct vop2_video_port_data *vp_data;
+	uint32_t possible_crtcs;
+	int i, nvp = 0;
+	int ret;
+
+	for (i = 0; i < vop2->registered_num_wins; i++) {
+		win = &vop2->win[i];
+
+		if (win->data->feature & WIN_FEATURE_CLUSTER_SUB)
+			continue;
+
+		if (win->type == DRM_PLANE_TYPE_PRIMARY) {
+			if (nvp < vop2_data->nr_vps) {
+				vp = &vop2->vps[nvp];
+
+				possible_crtcs = BIT(vop2_data->vp[i].id);
+				vp->primary_plane = win;
+
+				nvp++;
+			} else {
+				/* change the unused primary window to overlay window */
+				win->type = DRM_PLANE_TYPE_OVERLAY;
+			}
+		}
+
+		if (win->type == DRM_PLANE_TYPE_OVERLAY)
+			possible_crtcs = (1 << vop2_data->nr_vps) - 1;
+		ret = vop2_plane_init(vop2, win, possible_crtcs);
+
+		if (ret) {
+			drm_err(vop2->drm, "failed to init plane %s: %d\n", win->data->name, ret);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < vop2_data->nr_vps; i++) {
+		char dclk_name[9];
+
+		vp_data = &vop2_data->vp[i];
+		vp = &vop2->vps[i];
+		vp->vop2 = vop2;
+		vp->id = vp_data->id;
+		vp->regs = vp_data->regs;
+
+		vp->zpos = devm_kzalloc(vop2->dev, vop2->data->win_size * sizeof(*vp->zpos), GFP_KERNEL);
+		if (!vp->zpos)
+			return -ENOMEM;
+
+		snprintf(dclk_name, sizeof(dclk_name), "dclk_vp%d", vp->id);
+		vp->dclk = devm_clk_get(vop2->dev, dclk_name);
+		if (IS_ERR(vp->dclk)) {
+			drm_err(vop2->drm, "failed to get %s\n", dclk_name);
+			return PTR_ERR(vp->dclk);
+		}
+
+		crtc = &vp->crtc;
+
+		port = of_graph_get_port_by_id(dev->of_node, i);
+		if (!port) {
+			drm_err(vop2->drm, "no port node found for video_port%d\n", i);
+			return -ENOENT;
+		}
+		crtc->port = port;
+
+		plane = &vp->primary_plane->base;
+
+		ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &vop2_crtc_funcs,
+						"video_port%d", vp->id);
+		if (ret) {
+			drm_err(vop2->drm, "crtc init for video_port%d failed\n", i);
+			return ret;
+		}
+
+		drm_crtc_helper_add(crtc, &vop2_crtc_helper_funcs);
+
+		drm_flip_work_init(&vp->fb_unref_work, "fb_unref", vop2_fb_unref_worker);
+
+		init_completion(&vp->dsp_hold_completion);
+		init_completion(&vp->line_flag_completion);
+	}
+
+	return 0;
+}
+
+static void vop2_destroy_crtc(struct drm_crtc *crtc)
+{
+	struct vop2_video_port *vp = to_vop2_video_port(crtc);
+
+	of_node_put(crtc->port);
+
+	/*
+	 * Destroy CRTC after vop2_plane_destroy() since vop2_disable_plane()
+	 * references the CRTC.
+	 */
+	drm_crtc_cleanup(crtc);
+	drm_flip_work_cleanup(&vp->fb_unref_work);
+}
+
+static int vop2_win_init(struct vop2 *vop2)
+{
+	const struct vop2_data *vop2_data = vop2->data;
+	const struct vop2_layer_data *layer_data;
+	struct vop2_win *win;
+	struct vop2_layer *layer;
+	uint8_t plane_id = 0;
+	unsigned int i;
+
+	for (i = 0; i < vop2_data->win_size; i++) {
+		const struct vop2_win_data *win_data = &vop2_data->win[i];
+
+		win = &vop2->win[i];
+		win->data = win_data;
+		win->type = win_data->type;
+		win->regs = win_data->regs;
+		win->offset = win_data->base;
+		win->win_id = i;
+		win->plane_id = plane_id++;
+		win->zpos = i;
+		win->vop2 = vop2;
+	}
+
+	vop2->registered_num_wins = vop2_data->win_size;
+
+	for (i = 0; i < vop2_data->nr_layers; i++) {
+		layer = &vop2->layers[i];
+		layer_data = &vop2_data->layer[i];
+		layer->id = layer_data->id;
+		layer->regs = layer_data->regs;
+	}
+
+	return 0;
+}
+
+static int vop2_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct vop2_data *vop2_data;
+	struct drm_device *drm = data;
+	struct vop2 *vop2;
+	struct resource *res;
+	size_t alloc_size;
+	int ret;
+
+	vop2_data = of_device_get_match_data(dev);
+	if (!vop2_data)
+		return -ENODEV;
+
+	/* Allocate vop2 struct and its vop2_win array */
+	alloc_size = sizeof(*vop2) + sizeof(*vop2->win) * vop2_data->win_size;
+	vop2 = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
+	if (!vop2)
+		return -ENOMEM;
+
+	vop2->dev = dev;
+	vop2->data = vop2_data;
+	vop2->drm = drm;
+
+	dev_set_drvdata(dev, vop2);
+
+	ret = vop2_win_init(vop2);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
+	if (!res) {
+		drm_err(vop2->drm, "failed to get vop2 register byname\n");
+		return -EINVAL;
+	}
+	vop2->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vop2->regs))
+		return PTR_ERR(vop2->regs);
+	vop2->len = resource_size(res);
+
+	vop2->regsbak = devm_kzalloc(dev, vop2->len, GFP_KERNEL);
+	if (!vop2->regsbak)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gamma_lut");
+	if (res) {
+		vop2->lut_regs = devm_ioremap_resource(dev, res);
+		if (IS_ERR(vop2->lut_regs))
+			return PTR_ERR(vop2->lut_regs);
+	}
+
+	vop2->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
+
+	vop2->hclk = devm_clk_get(vop2->dev, "hclk_vop");
+	if (IS_ERR(vop2->hclk)) {
+		drm_err(vop2->drm, "failed to get hclk source\n");
+		return PTR_ERR(vop2->hclk);
+	}
+
+	vop2->aclk = devm_clk_get(vop2->dev, "aclk_vop");
+	if (IS_ERR(vop2->aclk)) {
+		drm_err(vop2->drm, "failed to get aclk source\n");
+		return PTR_ERR(vop2->aclk);
+	}
+
+	vop2->irq = platform_get_irq(pdev, 0);
+	if (vop2->irq < 0) {
+		drm_err(vop2->drm, "cannot find irq for vop2\n");
+		return vop2->irq;
+	}
+
+	spin_lock_init(&vop2->reg_lock);
+	spin_lock_init(&vop2->irq_lock);
+	mutex_init(&vop2->vop2_lock);
+
+	ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2);
+	if (ret)
+		return ret;
+
+	ret = rockchip_drm_dma_attach_device(vop2->drm, vop2->dev);
+	if (ret) {
+		drm_err(vop2->drm, "failed to attach dma mapping, %d\n", ret);
+		return ret;
+	}
+
+	ret = vop2_create_crtc(vop2);
+	if (ret)
+		return ret;
+
+	ret = vop2_gamma_init(vop2);
+	if (ret)
+		return ret;
+
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+}
+
+static void vop2_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct vop2 *vop2 = dev_get_drvdata(dev);
+	struct drm_device *drm = vop2->drm;
+	struct list_head *plane_list = &drm->mode_config.plane_list;
+	struct list_head *crtc_list = &drm->mode_config.crtc_list;
+	struct drm_crtc *crtc, *tmpc;
+	struct drm_plane *plane, *tmpp;
+
+	rockchip_drm_dma_detach_device(vop2->drm, vop2->dev);
+
+	pm_runtime_disable(dev);
+
+	list_for_each_entry_safe(plane, tmpp, plane_list, head)
+		drm_plane_cleanup(plane);
+
+	list_for_each_entry_safe(crtc, tmpc, crtc_list, head)
+		vop2_destroy_crtc(crtc);
+}
+
+const struct component_ops vop2_component_ops = {
+	.bind = vop2_bind,
+	.unbind = vop2_unbind,
+};
+EXPORT_SYMBOL_GPL(vop2_component_ops);
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
new file mode 100644
index 0000000000000..669c7b6fd9eab
--- /dev/null
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -0,0 +1,916 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Rockchip Electronics Co.Ltd
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_print.h>
+
+#include "rockchip_drm_vop.h"
+#include "rockchip_vop_reg.h"
+
+#define _VOP_REG(off, _mask, _shift, _write_mask) \
+	{ \
+		.offset = off, \
+		.mask = _mask, \
+		.shift = _shift, \
+		.write_mask = _write_mask, \
+	}
+
+#define VOP_REG(off, _mask, _shift) \
+		_VOP_REG(off, _mask, _shift, false)
+
+#define VOP_REG_MASK(off, _mask, s) \
+		_VOP_REG(off, _mask, s, true)
+
+static const uint32_t formats_win_full_10bit[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+};
+
+static const uint32_t formats_win_full_10bit_yuyv[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV24,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_VYUY,
+};
+
+static const uint32_t formats_win_lite[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR565,
+};
+
+static const u32 formats_wb[] = {
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_NV12,
+};
+
+static const uint64_t format_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const uint64_t format_modifiers_afbc[] = {
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR),
+
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_CBR |
+				AFBC_FORMAT_MOD_SPARSE),
+
+	/* SPLIT mandates SPARSE, RGB modes mandates YTR */
+	DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 |
+				AFBC_FORMAT_MOD_YTR |
+				AFBC_FORMAT_MOD_SPARSE |
+				AFBC_FORMAT_MOD_SPLIT),
+	DRM_FORMAT_MOD_INVALID,
+};
+
+static const int rk3568_vop_axi_intrs[] = {
+	0,
+	BUS_ERROR_INTR,
+	0,
+	WB_UV_FIFO_FULL_INTR,
+	WB_YRGB_FIFO_FULL_INTR,
+	WB_COMPLETE_INTR,
+
+};
+
+static const struct vop_intr rk3568_vop_axi_intr[] = {
+	{
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS0_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS0_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS0_INT_CLR, 0xfe, 0),
+	}, {
+		.intrs = rk3568_vop_axi_intrs,
+		.nintrs = ARRAY_SIZE(rk3568_vop_axi_intrs),
+		.status = VOP_REG(RK3568_SYS1_INT_STATUS, 0xfe, 0),
+		.enable = VOP_REG_MASK(RK3568_SYS1_INT_EN, 0xfe, 0),
+		.clear = VOP_REG_MASK(RK3568_SYS1_INT_CLR, 0xfe, 0),
+	},
+};
+
+static const int rk3568_vop_intrs[] = {
+	FS_INTR,
+	FS_NEW_INTR,
+	LINE_FLAG_INTR,
+	LINE_FLAG1_INTR,
+	POST_BUF_EMPTY_INTR,
+	FS_FIELD_INTR,
+	DSP_HOLD_VALID_INTR,
+};
+
+static const struct vop_intr rk3568_vp0_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP0_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP0_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP0_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP0_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp1_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP1_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP1_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP1_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP1_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop_intr rk3568_vp2_intr = {
+	.intrs = rk3568_vop_intrs,
+	.nintrs = ARRAY_SIZE(rk3568_vop_intrs),
+	.line_flag_num[0] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 0),
+	.line_flag_num[1] = VOP_REG(RK3568_VP2_LINE_FLAG, 0x1fff, 16),
+	.status = VOP_REG(RK3568_VP2_INT_STATUS, 0xffff, 0),
+	.enable = VOP_REG_MASK(RK3568_VP2_INT_EN, 0xffff, 0),
+	.clear = VOP_REG_MASK(RK3568_VP2_INT_CLR, 0xffff, 0),
+};
+
+static const struct vop2_wb_regs rk3568_vop_wb_regs = {
+	.enable = VOP_REG(RK3568_WB_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_WB_CTRL, 0x7, 1),
+	.dither_en = VOP_REG(RK3568_WB_CTRL, 0x1, 4),
+	.r2y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 5),
+	.scale_x_en = VOP_REG(RK3568_WB_CTRL, 0x1, 7),
+	.scale_y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 8),
+	.axi_yrgb_id = VOP_REG(RK3568_WB_CTRL, 0xff, 19),
+	.axi_uv_id = VOP_REG(RK3568_WB_CTRL, 0x1f, 27),
+	.scale_x_factor = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3fff, 16),
+	.yrgb_mst = VOP_REG(RK3568_WB_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_WB_CBR_MST, 0xffffffff, 0),
+	.vp_id = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 8),
+	.fifo_throd = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3ff, 0),
+};
+
+static const struct vop2_wb_data rk3568_vop_wb_data = {
+	.formats = formats_wb,
+	.nformats = ARRAY_SIZE(formats_wb),
+	.max_output = { 1920, 1080 },
+	.regs = &rk3568_vop_wb_regs,
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp0_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0),
+	.dsp_background = VOP_REG(RK3568_VP0_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 0),
+	.out_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP0_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP0_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP0_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP0_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP0_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP0_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP0_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP0_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP0_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP0_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP0_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP0_MIPI_CTRL, 0x1, 21),
+	.dsp_lut_en = VOP_REG(RK3568_VP0_DSP_CTRL, 0x1, 28),
+	.hdr10_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 4),
+	.hdr_lut_update_en = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 0),
+	.hdr_lut_mode = VOP_REG(RK3568_HDR_LUT_CTRL, 0x1, 1),
+	.hdr_lut_mst = VOP_REG(RK3568_HDR_LUT_MST, 0xffffffff, 0),
+	.sdr2hdr_eotf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 0),
+	.sdr2hdr_r2r_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 1),
+	.sdr2hdr_r2r_mode = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 2),
+	.sdr2hdr_oetf_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 3),
+	.sdr2hdr_bypass_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 8),
+	.sdr2hdr_auto_gating_en = VOP_REG(RK3568_SDR2HDR_CTRL, 0x1, 9),
+	.sdr2hdr_path_en = VOP_REG(RK3568_OVL_CTRL, 0x1, 5),
+	.hdr2sdr_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 0),
+	.hdr2sdr_bypass_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 8),
+	.hdr2sdr_auto_gating_en = VOP_REG(RK3568_HDR2SDR_CTRL, 0x1, 9),
+	.hdr2sdr_src_min = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 0),
+	.hdr2sdr_src_max = VOP_REG(RK3568_HDR2SDR_SRC_RANGE, 0x3fff, 16),
+	.hdr2sdr_normfaceetf = VOP_REG(RK3568_HDR2SDR_NORMFACEETF, 0x7ff, 0),
+	.hdr2sdr_dst_min = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 0),
+	.hdr2sdr_dst_max = VOP_REG(RK3568_HDR2SDR_DST_RANGE, 0xffff, 16),
+	.hdr2sdr_normfacgamma = VOP_REG(RK3568_HDR2SDR_NORMFACCGAMMA, 0xffff, 0),
+	.hdr2sdr_eetf_oetf_y0_offset = RK3568_HDR_EETF_OETF_Y0,
+	.hdr2sdr_sat_y0_offset = RK3568_HDR_SAT_Y0,
+	.sdr2hdr_eotf_oetf_y0_offset = RK3568_HDR_EOTF_OETF_Y0,
+	.sdr2hdr_oetf_dx_pow1_offset = RK3568_HDR_OETF_DX_POW1,
+	.sdr2hdr_oetf_xn1_offset = RK3568_HDR_OETF_XN1,
+	.hdr_src_color_ctrl = VOP_REG(RK3568_HDR0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_dst_color_ctrl = VOP_REG(RK3568_HDR0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.hdr_src_alpha_ctrl = VOP_REG(RK3568_HDR0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.hdr_dst_alpha_ctrl = VOP_REG(RK3568_HDR0_DST_ALPHA_CTRL, 0xffffffff, 0),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP0_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP0_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP0_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP0_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP0_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP0_BCSH_COLOR_BAR, 0x1, 31),
+
+	.cubic_lut_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 0),
+	.cubic_lut_update_en = VOP_REG(RK3568_VP0_3D_LUT_CTRL, 0x1, 2),
+	.cubic_lut_mst = VOP_REG(RK3568_VP0_3D_LUT_MST, 0xffffffff, 0),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp1_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 1),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 1),
+	.dsp_background = VOP_REG(RK3568_VP1_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 4),
+	.out_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP1_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP1_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.htotal_pw = VOP_REG(RK3568_VP1_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP1_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP1_POST_SCL_CTRL, 0x3, 0),
+	.hact_st_end = VOP_REG(RK3568_VP1_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP1_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP1_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP1_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP1_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP1_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP1_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP1_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP1_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP1_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP1_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP1_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP1_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP1_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_regs rk3568_vop_vp2_regs = {
+	.cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 2),
+	.overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 2),
+	.dsp_background = VOP_REG(RK3568_VP2_DSP_BG, 0x3fffffff, 0),
+	.port_mux = VOP_REG(RK3568_OVL_PORT_SEL, 0xf, 8),
+	.out_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0xf, 0),
+	.standby = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 31),
+	.core_dclk_div = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 4),
+	.dclk_div2 = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 4),
+	.dclk_div2_phase_lock = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 5),
+	.p2i_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 5),
+	.dsp_filed_pol = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 6),
+	.dsp_interlace = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 7),
+	.dsp_data_swap = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1f, 8),
+	.post_dsp_out_r2y = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 15),
+	.pre_scan_htiming = VOP_REG(RK3568_VP2_PRE_SCAN_HTIMING, 0x1fff1fff, 0),
+	.bg_dly = VOP_REG(RK3568_VP2_BG_MIX_CTRL, 0xff, 24),
+	.hpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
+	.vpost_st_end = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
+	.post_scl_factor = VOP_REG(RK3568_VP2_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
+	.post_scl_ctrl = VOP_REG(RK3568_VP2_POST_SCL_CTRL, 0x3, 0),
+	.htotal_pw = VOP_REG(RK3568_VP2_DSP_HTOTAL_HS_END, 0x1fff1fff, 0),
+	.hact_st_end = VOP_REG(RK3568_VP2_DSP_HACT_ST_END, 0x1fff1fff, 0),
+	.vtotal_pw = VOP_REG(RK3568_VP2_DSP_VTOTAL_VS_END, 0x1fff1fff, 0),
+	.vact_st_end = VOP_REG(RK3568_VP2_DSP_VACT_ST_END, 0x1fff1fff, 0),
+	.vact_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VACT_ST_END_F1, 0x1fff1fff, 0),
+	.vs_st_end_f1 = VOP_REG(RK3568_VP2_DSP_VS_ST_END_F1, 0x1fff1fff, 0),
+	.vpost_st_end_f1 = VOP_REG(RK3568_VP2_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
+	.pre_dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 16),
+	.dither_down_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 17),
+	.dither_down_sel = VOP_REG(RK3568_VP2_DSP_CTRL, 0x3, 18),
+	.dither_down_mode = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 20),
+	.mipi_dual_en = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 20),
+	.mipi_dual_channel_swap = VOP_REG(RK3568_VP2_MIPI_CTRL, 0x1, 21),
+
+	.bcsh_brightness = VOP_REG(RK3568_VP2_BCSH_BCS, 0xff, 0),
+	.bcsh_contrast = VOP_REG(RK3568_VP2_BCSH_BCS, 0x1ff, 8),
+	.bcsh_sat_con = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3ff, 20),
+	.bcsh_out_mode = VOP_REG(RK3568_VP2_BCSH_BCS, 0x3, 30),
+	.bcsh_sin_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 0),
+	.bcsh_cos_hue = VOP_REG(RK3568_VP2_BCSH_H, 0x1ff, 16),
+	.bcsh_r2y_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 6),
+	.bcsh_r2y_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 4),
+	.bcsh_y2r_csc_mode = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x3, 2),
+	.bcsh_y2r_en = VOP_REG(RK3568_VP2_BCSH_CTRL, 0x1, 0),
+	.bcsh_en = VOP_REG(RK3568_VP2_BCSH_COLOR_BAR, 0x1, 31),
+	.dsp_lut_en = VOP_REG(RK3568_VP2_DSP_CTRL, 0x1, 28),
+};
+
+static const struct vop2_video_port_data rk3568_vop_video_ports[] = {
+	{
+		.id = 0,
+		.feature = VOP_FEATURE_OUTPUT_10BIT,
+		.gamma_lut_len = 1024,
+		.cubic_lut_len = 729, /* 9x9x9 */
+		.max_output = { 4096, 2304 },
+		.pre_scan_max_dly = { 69, 53, 53, 42 },
+		.intr = &rk3568_vp0_intr,
+		.regs = &rk3568_vop_vp0_regs,
+	}, {
+		.id = 1,
+		.gamma_lut_len = 1024,
+		.max_output = { 2048, 1536 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp1_intr,
+		.regs = &rk3568_vop_vp1_regs,
+	}, {
+		.id = 2,
+		.gamma_lut_len = 1024,
+		.max_output = { 1920, 1080 },
+		.pre_scan_max_dly = { 40, 40, 40, 40 },
+		.intr = &rk3568_vp2_intr,
+		.regs = &rk3568_vop_vp2_regs,
+	},
+};
+
+const struct vop2_layer_regs rk3568_vop_layer0_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 0)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer1_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 4)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer2_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 8)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer3_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 12)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer4_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 16)
+};
+
+const struct vop2_layer_regs rk3568_vop_layer5_regs = {
+	.layer_sel = VOP_REG(RK3568_OVL_LAYER_SEL, 0x7, 20)
+};
+
+static const struct vop2_layer_data rk3568_vop_layers[] = {
+	{
+		.id = 0,
+		.regs = &rk3568_vop_layer0_regs,
+	}, {
+		.id = 1,
+		.regs = &rk3568_vop_layer1_regs,
+	}, {
+		.id = 2,
+		.regs = &rk3568_vop_layer2_regs,
+	}, {
+		.id = 3,
+		.regs = &rk3568_vop_layer3_regs,
+	}, {
+		.id = 4,
+		.regs = &rk3568_vop_layer4_regs,
+	}, {
+		.id = 5,
+		.regs = &rk3568_vop_layer5_regs,
+	},
+};
+
+static const struct vop2_cluster_regs rk3568_vop_cluster0 =  {
+	.afbc_enable = VOP_REG(RK3568_CLUSTER_CTRL, 0x1, 1),
+	.enable = VOP_REG(RK3568_CLUSTER_CTRL, 1, 0),
+	.lb_mode = VOP_REG(RK3568_CLUSTER_CTRL, 0xf, 4),
+};
+
+static const struct vop_afbc rk3568_cluster0_afbc = {
+	.format = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1f, 2),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 9),
+	.uv_swap = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 10),
+	.auto_gating_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL, 0x1, 4),
+	.half_block_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 7),
+	.block_split_en = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_CTRL, 0x1, 8),
+	.hdr_ptr = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_HDR_PTR, 0xffffffff, 0),
+	.pic_size = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE, 0xffffffff, 0),
+	.pic_vir_width = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 0),
+	.tile_num = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH, 0xffff, 16),
+	.pic_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET, 0xffffffff, 0),
+	.dsp_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET, 0xffffffff, 0),
+	.transform_offset = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_TRANSFORM_OFFSET, 0xffffffff, 0),
+	.rotate_90 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 0),
+	.rotate_270 = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 1),
+	.xmirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 2),
+	.ymirror = VOP_REG(RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE, 0x1, 3),
+};
+
+static const struct vop2_scl_regs rk3568_cluster0_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB, 0xffff, 16),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 14),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 12),
+	.bic_coe_sel = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x3, 2),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 28),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_CLUSTER_WIN_CTRL1, 0x1, 29),
+};
+
+static const struct vop2_scl_regs rk3568_esmart_win_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION0_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION0_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area1_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION1_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION1_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION1_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area2_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION2_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION2_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION2_CTRL, 0x1, 11),
+};
+
+static const struct vop2_scl_regs rk3568_area3_scl = {
+	.scale_yrgb_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(RK3568_SMART_REGION3_SCL_FACTOR_CBR, 0xffff, 16),
+	.yrgb_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 0),
+	.yrgb_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 2),
+	.yrgb_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 4),
+	.yrgb_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 6),
+	.cbcr_hor_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 8),
+	.cbcr_hscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 10),
+	.cbcr_ver_scl_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 12),
+	.cbcr_vscl_filter_mode = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 14),
+	.bic_coe_sel = VOP_REG(RK3568_SMART_REGION3_SCL_CTRL, 0x3, 16),
+	.vsd_yrgb_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 8),
+	.vsd_yrgb_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 9),
+	.vsd_cbcr_gt2 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 10),
+	.vsd_cbcr_gt4 = VOP_REG(RK3568_SMART_REGION3_CTRL, 0x1, 11),
+};
+
+static const struct vop2_win_regs rk3568_cluster0_win_data = {
+	.scl = &rk3568_cluster0_win_scl,
+	.afbc = &rk3568_cluster0_afbc,
+	.cluster = &rk3568_vop_cluster0,
+	.enable = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 0),
+	.format = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1f, 1),
+	.rb_swap = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 14),
+	.dither_up = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 18),
+	.act_info = VOP_REG(RK3568_CLUSTER_WIN_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_CLUSTER_WIN_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_CLUSTER_WIN_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_CLUSTER_WIN_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_CLUSTER_WIN_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 19),
+	.yrgb_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_CLUSTER_WIN_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 8),
+	.r2y_en = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x1, 9),
+	.csc_mode = VOP_REG(RK3568_CLUSTER_WIN_CTRL0, 0x3, 10),
+};
+
+static const struct vop2_win_regs rk3568_esmart_win_data = {
+	.scl = &rk3568_esmart_win_scl,
+	.enable = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 0),
+	.format = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1f, 1),
+	.dither_up = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 12),
+	.rb_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 14),
+	.uv_swap = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 16),
+	.act_info = VOP_REG(RK3568_SMART_REGION0_ACT_INFO, 0x1fff1fff, 0),
+	.dsp_info = VOP_REG(RK3568_SMART_REGION0_DSP_INFO, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3568_SMART_REGION0_DSP_ST, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3568_SMART_REGION0_YRGB_MST, 0xffffffff, 0),
+	.uv_mst = VOP_REG(RK3568_SMART_REGION0_CBR_MST, 0xffffffff, 0),
+	.yuv_clip = VOP_REG(RK3568_SMART_REGION0_CTRL, 0x1, 17),
+	.yrgb_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 0),
+	.uv_vir = VOP_REG(RK3568_SMART_REGION0_VIR, 0xffff, 16),
+	.y2r_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 0),
+	.r2y_en = VOP_REG(RK3568_SMART_CTRL0, 0x1, 1),
+	.csc_mode = VOP_REG(RK3568_SMART_CTRL0, 0x3, 2),
+	.ymirror = VOP_REG(RK3568_SMART_CTRL1, 0x1, 31),
+	.color_key = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x3fffffff, 0),
+	.color_key_en = VOP_REG(RK3568_SMART_COLOR_KEY_CTRL, 0x1, 31),
+};
+
+/*
+ * rk3568 vop with 2 cluster, 2 esmart win, 2 smart win.
+ * Every cluster can work as 4K win or split into two win.
+ * All win in cluster support AFBCD.
+ *
+ * Every esmart win and smart win support 4 Multi-region.
+ *
+ * Scale filter mode:
+ *
+ * * Cluster:  bicubic for horizontal scale up, others use bilinear
+ * * ESmart:
+ *    * nearest-neighbor/bilinear/bicubic for scale up
+ *    * nearest-neighbor/bilinear/average for scale down
+ *
+ *
+ * @TODO describe the wind like cpu-map dt nodes;
+ */
+static const struct vop2_win_data rk3568_vop_win_data[] = {
+	{
+		.name = "Smart0-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART0,
+		.base = 0x1c00,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.layer_sel_id = 3,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Smart1-win0",
+		.phys_id = ROCKCHIP_VOP2_SMART1,
+		.formats = formats_win_lite,
+		.nformats = ARRAY_SIZE(formats_win_lite),
+		.format_modifiers = format_modifiers,
+		.base = 0x1e00,
+		.layer_sel_id = 7,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart1-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART1,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1a00,
+		.layer_sel_id = 6,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MIRROR | WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Esmart0-win0",
+		.phys_id = ROCKCHIP_VOP2_ESMART0,
+		.formats = formats_win_full_10bit_yuyv,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit_yuyv),
+		.format_modifiers = format_modifiers,
+		.base = 0x1800,
+		.layer_sel_id = 2,
+		.supported_rotations = DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_esmart_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 8,
+		.max_downscale_factor = 8,
+		.dly = { 20, 47, 41 },
+		.feature = WIN_FEATURE_MULTI_AREA,
+	}, {
+		.name = "Cluster0-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1000,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 0,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN,
+	}, {
+		.name = "Cluster0-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER0,
+		.base = 0x1080,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB,
+	}, {
+		.name = "Cluster1-win0",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.base = 0x1200,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.layer_sel_id = 1,
+		.supported_rotations = DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270 |
+					DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.dly = { 0, 27, 21 },
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_MAIN | WIN_FEATURE_MIRROR,
+	}, {
+		.name = "Cluster1-win1",
+		.phys_id = ROCKCHIP_VOP2_CLUSTER1,
+		.layer_sel_id = -1,
+		.formats = formats_win_full_10bit,
+		.nformats = ARRAY_SIZE(formats_win_full_10bit),
+		.format_modifiers = format_modifiers_afbc,
+		.base = 0x1280,
+		.supported_rotations = DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y,
+		.hsu_filter_mode = VOP2_SCALE_UP_BIC,
+		.hsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.vsu_filter_mode = VOP2_SCALE_UP_BIL,
+		.vsd_filter_mode = VOP2_SCALE_DOWN_BIL,
+		.regs = &rk3568_cluster0_win_data,
+		.type = DRM_PLANE_TYPE_OVERLAY,
+		.max_upscale_factor = 4,
+		.max_downscale_factor = 4,
+		.feature = WIN_FEATURE_AFBDC | WIN_FEATURE_CLUSTER_SUB | WIN_FEATURE_MIRROR,
+	},
+};
+
+static const struct vop_grf_ctrl rk3568_grf_ctrl = {
+	.grf_bt656_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 1),
+	.grf_bt1120_clk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 2),
+	.grf_dclk_inv = VOP_REG(RK3568_GRF_VO_CON1, 0x1, 3),
+};
+
+static const struct vop2_ctrl rk3568_vop_ctrl = {
+	.cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15),
+	.wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14),
+	.auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31),
+	.ovl_cfg_done_port = VOP_REG(RK3568_OVL_CTRL, 0x3, 30),
+	.ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28),
+	.ovl_port_mux_cfg = VOP_REG(RK3568_OVL_PORT_SEL, 0xffff, 0),
+	.if_ctrl_cfg_done_imd = VOP_REG(RK3568_DSP_IF_POL, 0x1, 28),
+	.version = VOP_REG(RK3568_VERSION_INFO, 0xffff, 16),
+	.lut_dma_en = VOP_REG(RK3568_SYS_AXI_LUT_CTRL, 0x1, 0),
+	.cluster0_src_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_dst_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
+	.cluster0_src_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.cluster0_dst_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.src_color_ctrl = VOP_REG(RK3568_MIX0_SRC_COLOR_CTRL, 0xffffffff, 0),
+	.dst_color_ctrl = VOP_REG(RK3568_MIX0_DST_COLOR_CTRL, 0xffffffff, 0),
+	.src_alpha_ctrl = VOP_REG(RK3568_MIX0_SRC_ALPHA_CTRL, 0xffffffff, 0),
+	.dst_alpha_ctrl = VOP_REG(RK3568_MIX0_DST_ALPHA_CTRL, 0xffffffff, 0),
+	.rgb_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 0),
+	.hdmi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 1),
+	.edp0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 3),
+	.mipi0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 4),
+	.mipi1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 20),
+	.lvds0_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 5),
+	.lvds1_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 24),
+	.bt1120_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 6),
+	.bt656_en = VOP_REG(RK3568_DSP_IF_EN, 0x1, 7),
+	.rgb_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 8),
+	.hdmi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 10),
+	.edp0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 14),
+	.mipi0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 16),
+	.mipi1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 21),
+	.lvds0_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 18),
+	.lvds1_mux = VOP_REG(RK3568_DSP_IF_EN, 0x3, 25),
+	.lvds_dual_en = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 0),
+	.lvds_dual_mode = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 1),
+	.lvds_dual_channel_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 2),
+	.bt656_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 5),
+	.bt1120_yc_swap = VOP_REG(RK3568_DSP_IF_CTRL, 0x1, 9),
+	.gamma_port_sel = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 0),
+	.lvds_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 0),
+	.lvds_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 3),
+	.hdmi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 4),
+	.hdmi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 7),
+	.edp_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x3, 12),
+	.edp_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 15),
+	.mipi_pin_pol = VOP_REG(RK3568_DSP_IF_POL, 0x7, 16),
+	.mipi_dclk_pol = VOP_REG(RK3568_DSP_IF_POL, 0x1, 19),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 16),
+	.win_vp_id[ROCKCHIP_VOP2_CLUSTER1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 18),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 24),
+	.win_vp_id[ROCKCHIP_VOP2_ESMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 26),
+	.win_vp_id[ROCKCHIP_VOP2_SMART0] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 28),
+	.win_vp_id[ROCKCHIP_VOP2_SMART1] = VOP_REG(RK3568_OVL_PORT_SEL, 0x3, 30),
+	.win_dly[0] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 0),
+	.win_dly[1] = VOP_REG(RK3568_CLUSTER_DLY_NUM, 0xffff, 16),
+	.win_dly[2] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 0),
+	.win_dly[3] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 8),
+	.win_dly[4] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 16),
+	.win_dly[5] = VOP_REG(RK3568_SMART_DLY_NUM, 0xff, 24),
+	.otp_en = VOP_REG(RK3568_OTP_WIN_EN, 0x1, 0),
+};
+
+static const struct vop2_data rk3568_vop = {
+	.nr_vps = 3,
+	.nr_mixers = 5,
+	.nr_gammas = 1,
+	.max_input = { 4096, 2304 },
+	.max_output = { 4096, 2304 },
+	.ctrl = &rk3568_vop_ctrl,
+	.grf_ctrl = &rk3568_grf_ctrl,
+	.axi_intr = rk3568_vop_axi_intr,
+	.nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr),
+	.vp = rk3568_vop_video_ports,
+	.wb = &rk3568_vop_wb_data,
+	.layer = rk3568_vop_layers,
+	.nr_layers = ARRAY_SIZE(rk3568_vop_layers),
+	.win = rk3568_vop_win_data,
+	.win_size = ARRAY_SIZE(rk3568_vop_win_data),
+	.soc_id = 3568,
+};
+
+static const struct of_device_id vop2_dt_match[] = {
+	{
+		.compatible = "rockchip,rk3568-vop",
+		.data = &rk3568_vop
+	}, {
+	},
+};
+MODULE_DEVICE_TABLE(of, vop2_dt_match);
+
+static int vop2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+
+	return component_add(dev, &vop2_component_ops);
+}
+
+static int vop2_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vop2_component_ops);
+
+	return 0;
+}
+
+struct platform_driver vop2_platform_driver = {
+	.probe = vop2_probe,
+	.remove = vop2_remove,
+	.driver = {
+		.name = "rockchip-vop2",
+		.of_match_table = of_match_ptr(vop2_dt_match),
+	},
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:40     ` Heiko Stübner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 14:40 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Sascha Hauer

Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> With upcoming VOP2 support VOP won't be the only choice anymore, so make
> the VOP driver optional.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/configs/multi_v7_defconfig         | 1 +
>  arch/arm64/configs/defconfig                | 1 +
>  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
>  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
>  5 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index c951aeed2138c..fc123e8f3e2f9 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
>  CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
>  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index f2e2b9bdd7024..a623386473dc9 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_EXYNOS_MIC=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_CDN_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 9f1ecefc39332..a1c4158259099 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
>  
>  if DRM_ROCKCHIP
>  
> +config ROCKCHIP_VOP
> +	bool "Rockchip VOP driver"

would this benefit from a default-y ?
For builds reusing preexisting .configs.


Heiko

> +	help
> +	  This selects support for the VOP driver. You should enable it
> +	  on all older SoCs up to RK3399.
> +
>  config ROCKCHIP_ANALOGIX_DP
>  	bool "Rockchip specific extensions for Analogix DP driver"
> +	depends on ROCKCHIP_VOP
>  	help
>  	  This selects support for Rockchip SoC specific extensions
>  	  for the Analogix Core DP driver. If you want to enable DP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -4,9 +4,10 @@
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>  
>  rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
> -		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
> +		rockchip_drm_gem.o
>  rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  
> +rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index e4ebe60b3cc1a..64fa5fd62c01a 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
>  	int ret;
>  
>  	num_rockchip_sub_drivers = 0;
> -	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
> +	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
>  				CONFIG_ROCKCHIP_LVDS);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
> 





^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:40     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 14:40 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sascha Hauer,
	Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	linux-arm-kernel

Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> With upcoming VOP2 support VOP won't be the only choice anymore, so make
> the VOP driver optional.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/configs/multi_v7_defconfig         | 1 +
>  arch/arm64/configs/defconfig                | 1 +
>  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
>  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
>  5 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index c951aeed2138c..fc123e8f3e2f9 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
>  CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
>  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index f2e2b9bdd7024..a623386473dc9 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_EXYNOS_MIC=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_CDN_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 9f1ecefc39332..a1c4158259099 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
>  
>  if DRM_ROCKCHIP
>  
> +config ROCKCHIP_VOP
> +	bool "Rockchip VOP driver"

would this benefit from a default-y ?
For builds reusing preexisting .configs.


Heiko

> +	help
> +	  This selects support for the VOP driver. You should enable it
> +	  on all older SoCs up to RK3399.
> +
>  config ROCKCHIP_ANALOGIX_DP
>  	bool "Rockchip specific extensions for Analogix DP driver"
> +	depends on ROCKCHIP_VOP
>  	help
>  	  This selects support for Rockchip SoC specific extensions
>  	  for the Analogix Core DP driver. If you want to enable DP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -4,9 +4,10 @@
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>  
>  rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
> -		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
> +		rockchip_drm_gem.o
>  rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  
> +rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index e4ebe60b3cc1a..64fa5fd62c01a 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
>  	int ret;
>  
>  	num_rockchip_sub_drivers = 0;
> -	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
> +	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
>  				CONFIG_ROCKCHIP_LVDS);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
> 





^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:40     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 14:40 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Sascha Hauer

Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> With upcoming VOP2 support VOP won't be the only choice anymore, so make
> the VOP driver optional.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/configs/multi_v7_defconfig         | 1 +
>  arch/arm64/configs/defconfig                | 1 +
>  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
>  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
>  5 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index c951aeed2138c..fc123e8f3e2f9 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
>  CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
>  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index f2e2b9bdd7024..a623386473dc9 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_EXYNOS_MIC=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_CDN_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 9f1ecefc39332..a1c4158259099 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
>  
>  if DRM_ROCKCHIP
>  
> +config ROCKCHIP_VOP
> +	bool "Rockchip VOP driver"

would this benefit from a default-y ?
For builds reusing preexisting .configs.


Heiko

> +	help
> +	  This selects support for the VOP driver. You should enable it
> +	  on all older SoCs up to RK3399.
> +
>  config ROCKCHIP_ANALOGIX_DP
>  	bool "Rockchip specific extensions for Analogix DP driver"
> +	depends on ROCKCHIP_VOP
>  	help
>  	  This selects support for Rockchip SoC specific extensions
>  	  for the Analogix Core DP driver. If you want to enable DP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -4,9 +4,10 @@
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>  
>  rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
> -		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
> +		rockchip_drm_gem.o
>  rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  
> +rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index e4ebe60b3cc1a..64fa5fd62c01a 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
>  	int ret;
>  
>  	num_rockchip_sub_drivers = 0;
> -	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
> +	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
>  				CONFIG_ROCKCHIP_LVDS);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
> 





_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:40     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 14:40 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Sascha Hauer

Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> With upcoming VOP2 support VOP won't be the only choice anymore, so make
> the VOP driver optional.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm/configs/multi_v7_defconfig         | 1 +
>  arch/arm64/configs/defconfig                | 1 +
>  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
>  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
>  5 files changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> index c951aeed2138c..fc123e8f3e2f9 100644
> --- a/arch/arm/configs/multi_v7_defconfig
> +++ b/arch/arm/configs/multi_v7_defconfig
> @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
>  CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
>  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index f2e2b9bdd7024..a623386473dc9 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
>  CONFIG_DRM_EXYNOS_HDMI=y
>  CONFIG_DRM_EXYNOS_MIC=y
>  CONFIG_DRM_ROCKCHIP=m
> +CONFIG_ROCKCHIP_VOP=y
>  CONFIG_ROCKCHIP_ANALOGIX_DP=y
>  CONFIG_ROCKCHIP_CDN_DP=y
>  CONFIG_ROCKCHIP_DW_HDMI=y
> diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> index 9f1ecefc39332..a1c4158259099 100644
> --- a/drivers/gpu/drm/rockchip/Kconfig
> +++ b/drivers/gpu/drm/rockchip/Kconfig
> @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
>  
>  if DRM_ROCKCHIP
>  
> +config ROCKCHIP_VOP
> +	bool "Rockchip VOP driver"

would this benefit from a default-y ?
For builds reusing preexisting .configs.


Heiko

> +	help
> +	  This selects support for the VOP driver. You should enable it
> +	  on all older SoCs up to RK3399.
> +
>  config ROCKCHIP_ANALOGIX_DP
>  	bool "Rockchip specific extensions for Analogix DP driver"
> +	depends on ROCKCHIP_VOP
>  	help
>  	  This selects support for Rockchip SoC specific extensions
>  	  for the Analogix Core DP driver. If you want to enable DP
> diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile
> index 17a9e7eb2130d..cd6e7bb5ce9c5 100644
> --- a/drivers/gpu/drm/rockchip/Makefile
> +++ b/drivers/gpu/drm/rockchip/Makefile
> @@ -4,9 +4,10 @@
>  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>  
>  rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
> -		rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o
> +		rockchip_drm_gem.o
>  rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
>  
> +rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += rockchip_drm_vop.o rockchip_vop_reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
>  rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index e4ebe60b3cc1a..64fa5fd62c01a 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -473,7 +473,7 @@ static int __init rockchip_drm_init(void)
>  	int ret;
>  
>  	num_rockchip_sub_drivers = 0;
> -	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
> +	ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
>  				CONFIG_ROCKCHIP_LVDS);
>  	ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
> 





_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
  2021-11-17 14:40     ` Heiko Stübner
  (?)
  (?)
@ 2021-11-17 14:50       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:50 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > the VOP driver optional.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/configs/multi_v7_defconfig         | 1 +
> >  arch/arm64/configs/defconfig                | 1 +
> >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> >  5 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > index c951aeed2138c..fc123e8f3e2f9 100644
> > --- a/arch/arm/configs/multi_v7_defconfig
> > +++ b/arch/arm/configs/multi_v7_defconfig
> > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> >  CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index f2e2b9bdd7024..a623386473dc9 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_EXYNOS_MIC=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_CDN_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > index 9f1ecefc39332..a1c4158259099 100644
> > --- a/drivers/gpu/drm/rockchip/Kconfig
> > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> >  
> >  if DRM_ROCKCHIP
> >  
> > +config ROCKCHIP_VOP
> > +	bool "Rockchip VOP driver"
> 
> would this benefit from a default-y ?
> For builds reusing preexisting .configs.

I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
That won't help users of custom configs of course.

I don't know what's preferred in such cases, I can change to default-y
if you like.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:50       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:50 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > the VOP driver optional.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/configs/multi_v7_defconfig         | 1 +
> >  arch/arm64/configs/defconfig                | 1 +
> >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> >  5 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > index c951aeed2138c..fc123e8f3e2f9 100644
> > --- a/arch/arm/configs/multi_v7_defconfig
> > +++ b/arch/arm/configs/multi_v7_defconfig
> > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> >  CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index f2e2b9bdd7024..a623386473dc9 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_EXYNOS_MIC=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_CDN_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > index 9f1ecefc39332..a1c4158259099 100644
> > --- a/drivers/gpu/drm/rockchip/Kconfig
> > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> >  
> >  if DRM_ROCKCHIP
> >  
> > +config ROCKCHIP_VOP
> > +	bool "Rockchip VOP driver"
> 
> would this benefit from a default-y ?
> For builds reusing preexisting .configs.

I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
That won't help users of custom configs of course.

I don't know what's preferred in such cases, I can change to default-y
if you like.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:50       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:50 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > the VOP driver optional.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/configs/multi_v7_defconfig         | 1 +
> >  arch/arm64/configs/defconfig                | 1 +
> >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> >  5 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > index c951aeed2138c..fc123e8f3e2f9 100644
> > --- a/arch/arm/configs/multi_v7_defconfig
> > +++ b/arch/arm/configs/multi_v7_defconfig
> > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> >  CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index f2e2b9bdd7024..a623386473dc9 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_EXYNOS_MIC=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_CDN_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > index 9f1ecefc39332..a1c4158259099 100644
> > --- a/drivers/gpu/drm/rockchip/Kconfig
> > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> >  
> >  if DRM_ROCKCHIP
> >  
> > +config ROCKCHIP_VOP
> > +	bool "Rockchip VOP driver"
> 
> would this benefit from a default-y ?
> For builds reusing preexisting .configs.

I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
That won't help users of custom configs of course.

I don't know what's preferred in such cases, I can change to default-y
if you like.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 14:50       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 14:50 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, kernel,
	linux-arm-kernel

On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > the VOP driver optional.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm/configs/multi_v7_defconfig         | 1 +
> >  arch/arm64/configs/defconfig                | 1 +
> >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> >  5 files changed, 12 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > index c951aeed2138c..fc123e8f3e2f9 100644
> > --- a/arch/arm/configs/multi_v7_defconfig
> > +++ b/arch/arm/configs/multi_v7_defconfig
> > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> >  CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > index f2e2b9bdd7024..a623386473dc9 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> >  CONFIG_DRM_EXYNOS_HDMI=y
> >  CONFIG_DRM_EXYNOS_MIC=y
> >  CONFIG_DRM_ROCKCHIP=m
> > +CONFIG_ROCKCHIP_VOP=y
> >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> >  CONFIG_ROCKCHIP_CDN_DP=y
> >  CONFIG_ROCKCHIP_DW_HDMI=y
> > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > index 9f1ecefc39332..a1c4158259099 100644
> > --- a/drivers/gpu/drm/rockchip/Kconfig
> > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> >  
> >  if DRM_ROCKCHIP
> >  
> > +config ROCKCHIP_VOP
> > +	bool "Rockchip VOP driver"
> 
> would this benefit from a default-y ?
> For builds reusing preexisting .configs.

I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
That won't help users of custom configs of course.

I don't know what's preferred in such cases, I can change to default-y
if you like.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 14:54   ` Rob Herring
  -1 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 14:54 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.

Can you outline what exactly you want to disable? I don't think
'status' is the right way. I think between the parent device being
disabled, an incomplete graph and user configuration choice that
should be enough to disable parts.

Rob

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:54   ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 14:54 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.

Can you outline what exactly you want to disable? I don't think
'status' is the right way. I think between the parent device being
disabled, an incomplete graph and user configuration choice that
should be enough to disable parts.

Rob

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:54   ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 14:54 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.

Can you outline what exactly you want to disable? I don't think
'status' is the right way. I think between the parent device being
disabled, an incomplete graph and user configuration choice that
should be enough to disable parts.

Rob

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 14:54   ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 14:54 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.

Can you outline what exactly you want to disable? I don't think
'status' is the right way. I think between the parent device being
disabled, an incomplete graph and user configuration choice that
should be enough to disable parts.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 15:13     ` Rob Herring
  -1 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:13 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> Add support for the HDMI port found on RK3568.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 6ebf7c14e096a..53be61a7ce595 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -472,18 +472,36 @@ vp0: port@0 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <0>;
> +
> +                               vp0_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp0>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp1: port@1 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <1>;
> +
> +                               vp1_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp1>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp2: port@2 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <2>;
> +
> +                               vp2_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp2>;
> +                                       status = "disabled";
> +                               };
>                         };
>                 };
>         };
> @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
>                 status = "disabled";
>         };
>
> +       hdmi: hdmi@fe0a0000 {
> +               compatible = "rockchip,rk3568-dw-hdmi";
> +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&cru PCLK_HDMI_HOST>,
> +                        <&cru CLK_HDMI_SFR>,
> +                        <&cru CLK_HDMI_CEC>,
> +                        <&cru HCLK_VOP>;
> +               clock-names = "iahb", "isfr", "cec", "hclk";
> +               power-domains = <&power RK3568_PD_VO>;
> +               reg-io-width = <4>;
> +               rockchip,grf = <&grf>;
> +               #sound-dai-cells = <0>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> +               status = "disabled";
> +
> +               ports {
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       hdmi_in: port@0 {


The schema says there is only 1 'port' node. Please run schema
validation when making DT changes.

However, an HDMI bridge should also define an output port to a
connector node (or another bridge). So the fix is to allow 'port@0'
and add an output port.

> +                               reg = <0>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               hdmi_in_vp0: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&vp0_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp1: endpoint@1 {
> +                                       reg = <1>;
> +                                       remote-endpoint = <&vp1_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp2: endpoint@2 {
> +                                       reg = <2>;
> +                                       remote-endpoint = <&vp2_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +                       };
> +               };
> +       };
> +
>         qos_gpu: qos@fe128000 {
>                 compatible = "rockchip,rk3568-qos", "syscon";
>                 reg = <0x0 0xfe128000 0x0 0x20>;
> --
> 2.30.2
>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 15:13     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:13 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> Add support for the HDMI port found on RK3568.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 6ebf7c14e096a..53be61a7ce595 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -472,18 +472,36 @@ vp0: port@0 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <0>;
> +
> +                               vp0_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp0>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp1: port@1 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <1>;
> +
> +                               vp1_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp1>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp2: port@2 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <2>;
> +
> +                               vp2_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp2>;
> +                                       status = "disabled";
> +                               };
>                         };
>                 };
>         };
> @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
>                 status = "disabled";
>         };
>
> +       hdmi: hdmi@fe0a0000 {
> +               compatible = "rockchip,rk3568-dw-hdmi";
> +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&cru PCLK_HDMI_HOST>,
> +                        <&cru CLK_HDMI_SFR>,
> +                        <&cru CLK_HDMI_CEC>,
> +                        <&cru HCLK_VOP>;
> +               clock-names = "iahb", "isfr", "cec", "hclk";
> +               power-domains = <&power RK3568_PD_VO>;
> +               reg-io-width = <4>;
> +               rockchip,grf = <&grf>;
> +               #sound-dai-cells = <0>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> +               status = "disabled";
> +
> +               ports {
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       hdmi_in: port@0 {


The schema says there is only 1 'port' node. Please run schema
validation when making DT changes.

However, an HDMI bridge should also define an output port to a
connector node (or another bridge). So the fix is to allow 'port@0'
and add an output port.

> +                               reg = <0>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               hdmi_in_vp0: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&vp0_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp1: endpoint@1 {
> +                                       reg = <1>;
> +                                       remote-endpoint = <&vp1_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp2: endpoint@2 {
> +                                       reg = <2>;
> +                                       remote-endpoint = <&vp2_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +                       };
> +               };
> +       };
> +
>         qos_gpu: qos@fe128000 {
>                 compatible = "rockchip,rk3568-qos", "syscon";
>                 reg = <0x0 0xfe128000 0x0 0x20>;
> --
> 2.30.2
>

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 15:13     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:13 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> Add support for the HDMI port found on RK3568.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 6ebf7c14e096a..53be61a7ce595 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -472,18 +472,36 @@ vp0: port@0 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <0>;
> +
> +                               vp0_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp0>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp1: port@1 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <1>;
> +
> +                               vp1_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp1>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp2: port@2 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <2>;
> +
> +                               vp2_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp2>;
> +                                       status = "disabled";
> +                               };
>                         };
>                 };
>         };
> @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
>                 status = "disabled";
>         };
>
> +       hdmi: hdmi@fe0a0000 {
> +               compatible = "rockchip,rk3568-dw-hdmi";
> +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&cru PCLK_HDMI_HOST>,
> +                        <&cru CLK_HDMI_SFR>,
> +                        <&cru CLK_HDMI_CEC>,
> +                        <&cru HCLK_VOP>;
> +               clock-names = "iahb", "isfr", "cec", "hclk";
> +               power-domains = <&power RK3568_PD_VO>;
> +               reg-io-width = <4>;
> +               rockchip,grf = <&grf>;
> +               #sound-dai-cells = <0>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> +               status = "disabled";
> +
> +               ports {
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       hdmi_in: port@0 {


The schema says there is only 1 'port' node. Please run schema
validation when making DT changes.

However, an HDMI bridge should also define an output port to a
connector node (or another bridge). So the fix is to allow 'port@0'
and add an output port.

> +                               reg = <0>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               hdmi_in_vp0: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&vp0_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp1: endpoint@1 {
> +                                       reg = <1>;
> +                                       remote-endpoint = <&vp1_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp2: endpoint@2 {
> +                                       reg = <2>;
> +                                       remote-endpoint = <&vp2_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +                       };
> +               };
> +       };
> +
>         qos_gpu: qos@fe128000 {
>                 compatible = "rockchip,rk3568-qos", "syscon";
>                 reg = <0x0 0xfe128000 0x0 0x20>;
> --
> 2.30.2
>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-11-17 15:13     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:13 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> Add support for the HDMI port found on RK3568.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 6ebf7c14e096a..53be61a7ce595 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -472,18 +472,36 @@ vp0: port@0 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <0>;
> +
> +                               vp0_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp0>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp1: port@1 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <1>;
> +
> +                               vp1_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp1>;
> +                                       status = "disabled";
> +                               };
>                         };
>
>                         vp2: port@2 {
>                                 #address-cells = <1>;
>                                 #size-cells = <0>;
>                                 reg = <2>;
> +
> +                               vp2_out_hdmi: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&hdmi_in_vp2>;
> +                                       status = "disabled";
> +                               };
>                         };
>                 };
>         };
> @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
>                 status = "disabled";
>         };
>
> +       hdmi: hdmi@fe0a0000 {
> +               compatible = "rockchip,rk3568-dw-hdmi";
> +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&cru PCLK_HDMI_HOST>,
> +                        <&cru CLK_HDMI_SFR>,
> +                        <&cru CLK_HDMI_CEC>,
> +                        <&cru HCLK_VOP>;
> +               clock-names = "iahb", "isfr", "cec", "hclk";
> +               power-domains = <&power RK3568_PD_VO>;
> +               reg-io-width = <4>;
> +               rockchip,grf = <&grf>;
> +               #sound-dai-cells = <0>;
> +               pinctrl-names = "default";
> +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> +               status = "disabled";
> +
> +               ports {
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +
> +                       hdmi_in: port@0 {


The schema says there is only 1 'port' node. Please run schema
validation when making DT changes.

However, an HDMI bridge should also define an output port to a
connector node (or another bridge). So the fix is to allow 'port@0'
and add an output port.

> +                               reg = <0>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +
> +                               hdmi_in_vp0: endpoint@0 {
> +                                       reg = <0>;
> +                                       remote-endpoint = <&vp0_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp1: endpoint@1 {
> +                                       reg = <1>;
> +                                       remote-endpoint = <&vp1_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +
> +                               hdmi_in_vp2: endpoint@2 {
> +                                       reg = <2>;
> +                                       remote-endpoint = <&vp2_out_hdmi>;
> +                                       status = "disabled";
> +                               };
> +                       };
> +               };
> +       };
> +
>         qos_gpu: qos@fe128000 {
>                 compatible = "rockchip,rk3568-qos", "syscon";
>                 reg = <0x0 0xfe128000 0x0 0x20>;
> --
> 2.30.2
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
  2021-11-17 14:50       ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 15:16         ` Heiko Stübner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 15:16 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Mittwoch, 17. November 2021, 15:50:54 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> > Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > > the VOP driver optional.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm/configs/multi_v7_defconfig         | 1 +
> > >  arch/arm64/configs/defconfig                | 1 +
> > >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> > >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> > >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> > >  5 files changed, 12 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > > index c951aeed2138c..fc123e8f3e2f9 100644
> > > --- a/arch/arm/configs/multi_v7_defconfig
> > > +++ b/arch/arm/configs/multi_v7_defconfig
> > > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> > >  CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > > index f2e2b9bdd7024..a623386473dc9 100644
> > > --- a/arch/arm64/configs/defconfig
> > > +++ b/arch/arm64/configs/defconfig
> > > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_EXYNOS_MIC=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_CDN_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > > index 9f1ecefc39332..a1c4158259099 100644
> > > --- a/drivers/gpu/drm/rockchip/Kconfig
> > > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> > >  
> > >  if DRM_ROCKCHIP
> > >  
> > > +config ROCKCHIP_VOP
> > > +	bool "Rockchip VOP driver"
> > 
> > would this benefit from a default-y ?
> > For builds reusing preexisting .configs.
> 
> I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
> CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
> That won't help users of custom configs of course.
> 
> I don't know what's preferred in such cases, I can change to default-y
> if you like.

default-y would keep the behaviour identical for all existing configs I
guess and right now vop(1) is still the most used variant and will stay
that way for a while longer, so I guess my preference would be for going
that route - also so that we don't drown in "my display stopped working"
during 5.17 ;-)


Heiko



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 15:16         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 15:16 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Mittwoch, 17. November 2021, 15:50:54 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> > Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > > the VOP driver optional.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm/configs/multi_v7_defconfig         | 1 +
> > >  arch/arm64/configs/defconfig                | 1 +
> > >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> > >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> > >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> > >  5 files changed, 12 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > > index c951aeed2138c..fc123e8f3e2f9 100644
> > > --- a/arch/arm/configs/multi_v7_defconfig
> > > +++ b/arch/arm/configs/multi_v7_defconfig
> > > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> > >  CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > > index f2e2b9bdd7024..a623386473dc9 100644
> > > --- a/arch/arm64/configs/defconfig
> > > +++ b/arch/arm64/configs/defconfig
> > > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_EXYNOS_MIC=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_CDN_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > > index 9f1ecefc39332..a1c4158259099 100644
> > > --- a/drivers/gpu/drm/rockchip/Kconfig
> > > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> > >  
> > >  if DRM_ROCKCHIP
> > >  
> > > +config ROCKCHIP_VOP
> > > +	bool "Rockchip VOP driver"
> > 
> > would this benefit from a default-y ?
> > For builds reusing preexisting .configs.
> 
> I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
> CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
> That won't help users of custom configs of course.
> 
> I don't know what's preferred in such cases, I can change to default-y
> if you like.

default-y would keep the behaviour identical for all existing configs I
guess and right now vop(1) is still the most used variant and will stay
that way for a while longer, so I guess my preference would be for going
that route - also so that we don't drown in "my display stopped working"
during 5.17 ;-)


Heiko



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 15:16         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 15:16 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, kernel,
	linux-arm-kernel

Am Mittwoch, 17. November 2021, 15:50:54 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> > Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > > the VOP driver optional.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm/configs/multi_v7_defconfig         | 1 +
> > >  arch/arm64/configs/defconfig                | 1 +
> > >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> > >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> > >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> > >  5 files changed, 12 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > > index c951aeed2138c..fc123e8f3e2f9 100644
> > > --- a/arch/arm/configs/multi_v7_defconfig
> > > +++ b/arch/arm/configs/multi_v7_defconfig
> > > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> > >  CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > > index f2e2b9bdd7024..a623386473dc9 100644
> > > --- a/arch/arm64/configs/defconfig
> > > +++ b/arch/arm64/configs/defconfig
> > > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_EXYNOS_MIC=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_CDN_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > > index 9f1ecefc39332..a1c4158259099 100644
> > > --- a/drivers/gpu/drm/rockchip/Kconfig
> > > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> > >  
> > >  if DRM_ROCKCHIP
> > >  
> > > +config ROCKCHIP_VOP
> > > +	bool "Rockchip VOP driver"
> > 
> > would this benefit from a default-y ?
> > For builds reusing preexisting .configs.
> 
> I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
> CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
> That won't help users of custom configs of course.
> 
> I don't know what's preferred in such cases, I can change to default-y
> if you like.

default-y would keep the behaviour identical for all existing configs I
guess and right now vop(1) is still the most used variant and will stay
that way for a while longer, so I guess my preference would be for going
that route - also so that we don't drown in "my display stopped working"
during 5.17 ;-)


Heiko



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 11/12] drm/rockchip: Make VOP driver optional
@ 2021-11-17 15:16         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-17 15:16 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Mittwoch, 17. November 2021, 15:50:54 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 03:40:26PM +0100, Heiko Stübner wrote:
> > Am Mittwoch, 17. November 2021, 15:33:46 CET schrieb Sascha Hauer:
> > > With upcoming VOP2 support VOP won't be the only choice anymore, so make
> > > the VOP driver optional.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm/configs/multi_v7_defconfig         | 1 +
> > >  arch/arm64/configs/defconfig                | 1 +
> > >  drivers/gpu/drm/rockchip/Kconfig            | 7 +++++++
> > >  drivers/gpu/drm/rockchip/Makefile           | 3 ++-
> > >  drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 2 +-
> > >  5 files changed, 12 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
> > > index c951aeed2138c..fc123e8f3e2f9 100644
> > > --- a/arch/arm/configs/multi_v7_defconfig
> > > +++ b/arch/arm/configs/multi_v7_defconfig
> > > @@ -667,6 +667,7 @@ CONFIG_DRM_EXYNOS_DPI=y
> > >  CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > >  CONFIG_ROCKCHIP_DW_MIPI_DSI=y
> > > diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> > > index f2e2b9bdd7024..a623386473dc9 100644
> > > --- a/arch/arm64/configs/defconfig
> > > +++ b/arch/arm64/configs/defconfig
> > > @@ -682,6 +682,7 @@ CONFIG_DRM_EXYNOS_DSI=y
> > >  CONFIG_DRM_EXYNOS_HDMI=y
> > >  CONFIG_DRM_EXYNOS_MIC=y
> > >  CONFIG_DRM_ROCKCHIP=m
> > > +CONFIG_ROCKCHIP_VOP=y
> > >  CONFIG_ROCKCHIP_ANALOGIX_DP=y
> > >  CONFIG_ROCKCHIP_CDN_DP=y
> > >  CONFIG_ROCKCHIP_DW_HDMI=y
> > > diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
> > > index 9f1ecefc39332..a1c4158259099 100644
> > > --- a/drivers/gpu/drm/rockchip/Kconfig
> > > +++ b/drivers/gpu/drm/rockchip/Kconfig
> > > @@ -21,8 +21,15 @@ config DRM_ROCKCHIP
> > >  
> > >  if DRM_ROCKCHIP
> > >  
> > > +config ROCKCHIP_VOP
> > > +	bool "Rockchip VOP driver"
> > 
> > would this benefit from a default-y ?
> > For builds reusing preexisting .configs.
> 
> I enabled CONFIG_ROCKCHIP_VOP for all configs in the tree that enable
> CONFIG_DRM_ROCKCHIP, so defconfig users shouldn't see any surprises.
> That won't help users of custom configs of course.
> 
> I don't know what's preferred in such cases, I can change to default-y
> if you like.

default-y would keep the behaviour identical for all existing configs I
guess and right now vop(1) is still the most used variant and will stay
that way for a while longer, so I guess my preference would be for going
that route - also so that we don't drown in "my display stopped working"
during 5.17 ;-)


Heiko



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 15:19     ` Rob Herring
  -1 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:19 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>         status = "okay";
>  };
>
> +&hdmi {
> +       status = "okay";
> +       avdd-0v9-supply = <&vdda0v9_image>;
> +       avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>  &i2c0 {
>         status = "okay";
>
> @@ -390,3 +396,21 @@ &sdmmc0 {
>  &uart2 {
>         status = "okay";
>  };
> +
> +&vop {
> +       status = "okay";
> +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +       status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +       status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +       status = "okay";
> +};

You can accomplish the same thing already with:

&vp0_out_hdmi {
  remote-endpoint = <&hdmi_in_vp0>;
};

or:

&vp0_out_hdmi {
  /delete-property/ remote-endpoint;
};

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:19     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:19 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>         status = "okay";
>  };
>
> +&hdmi {
> +       status = "okay";
> +       avdd-0v9-supply = <&vdda0v9_image>;
> +       avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>  &i2c0 {
>         status = "okay";
>
> @@ -390,3 +396,21 @@ &sdmmc0 {
>  &uart2 {
>         status = "okay";
>  };
> +
> +&vop {
> +       status = "okay";
> +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +       status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +       status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +       status = "okay";
> +};

You can accomplish the same thing already with:

&vp0_out_hdmi {
  remote-endpoint = <&hdmi_in_vp0>;
};

or:

&vp0_out_hdmi {
  /delete-property/ remote-endpoint;
};

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:19     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:19 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>         status = "okay";
>  };
>
> +&hdmi {
> +       status = "okay";
> +       avdd-0v9-supply = <&vdda0v9_image>;
> +       avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>  &i2c0 {
>         status = "okay";
>
> @@ -390,3 +396,21 @@ &sdmmc0 {
>  &uart2 {
>         status = "okay";
>  };
> +
> +&vop {
> +       status = "okay";
> +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +       status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +       status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +       status = "okay";
> +};

You can accomplish the same thing already with:

&vp0_out_hdmi {
  remote-endpoint = <&hdmi_in_vp0>;
};

or:

&vp0_out_hdmi {
  /delete-property/ remote-endpoint;
};

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:19     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 15:19 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
>
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>         status = "okay";
>  };
>
> +&hdmi {
> +       status = "okay";
> +       avdd-0v9-supply = <&vdda0v9_image>;
> +       avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>  &i2c0 {
>         status = "okay";
>
> @@ -390,3 +396,21 @@ &sdmmc0 {
>  &uart2 {
>         status = "okay";
>  };
> +
> +&vop {
> +       status = "okay";
> +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +       status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +       status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +       status = "okay";
> +};

You can accomplish the same thing already with:

&vp0_out_hdmi {
  remote-endpoint = <&hdmi_in_vp0>;
};

or:

&vp0_out_hdmi {
  /delete-property/ remote-endpoint;
};

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 15:20     ` Michael Riesch
  -1 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:20 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Sandy Huang, Heiko Stübner, Peter Geis

Hi Sascha,

On 11/17/21 3:33 PM, Sascha Hauer wrote:
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>   1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>   	status = "okay";
>   };
>   
> +&hdmi {
> +	status = "okay";
> +	avdd-0v9-supply = <&vdda0v9_image>;
> +	avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>   &i2c0 {
>   	status = "okay";
>   
> @@ -390,3 +396,21 @@ &sdmmc0 {
>   &uart2 {
>   	status = "okay";
>   };
> +
> +&vop {
> +	status = "okay";
> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};

Minor nitpick: This should probably be sorted alphabetically.

Best regards,
Michael

> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:20     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:20 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Sandy Huang, Heiko Stübner, Peter Geis

Hi Sascha,

On 11/17/21 3:33 PM, Sascha Hauer wrote:
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>   1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>   	status = "okay";
>   };
>   
> +&hdmi {
> +	status = "okay";
> +	avdd-0v9-supply = <&vdda0v9_image>;
> +	avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>   &i2c0 {
>   	status = "okay";
>   
> @@ -390,3 +396,21 @@ &sdmmc0 {
>   &uart2 {
>   	status = "okay";
>   };
> +
> +&vop {
> +	status = "okay";
> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};

Minor nitpick: This should probably be sorted alphabetically.

Best regards,
Michael

> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:20     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:20 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	kernel, Peter Geis, linux-arm-kernel

Hi Sascha,

On 11/17/21 3:33 PM, Sascha Hauer wrote:
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>   1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>   	status = "okay";
>   };
>   
> +&hdmi {
> +	status = "okay";
> +	avdd-0v9-supply = <&vdda0v9_image>;
> +	avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>   &i2c0 {
>   	status = "okay";
>   
> @@ -390,3 +396,21 @@ &sdmmc0 {
>   &uart2 {
>   	status = "okay";
>   };
> +
> +&vop {
> +	status = "okay";
> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};

Minor nitpick: This should probably be sorted alphabetically.

Best regards,
Michael

> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-11-17 15:20     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:20 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Sandy Huang, Heiko Stübner, Peter Geis

Hi Sascha,

On 11/17/21 3:33 PM, Sascha Hauer wrote:
> This enabled the VOP2 display controller along with hdmi and the
> required port routes which is enough to get a picture out of the
> hdmi port of the board.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
>   1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> index 184e2aa2416af..156e001492173 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
>   	status = "okay";
>   };
>   
> +&hdmi {
> +	status = "okay";
> +	avdd-0v9-supply = <&vdda0v9_image>;
> +	avdd-1v8-supply = <&vcca1v8_image>;
> +};
> +
>   &i2c0 {
>   	status = "okay";
>   
> @@ -390,3 +396,21 @@ &sdmmc0 {
>   &uart2 {
>   	status = "okay";
>   };
> +
> +&vop {
> +	status = "okay";
> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};

Minor nitpick: This should probably be sorted alphabetically.

Best regards,
Michael

> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-17 14:54   ` Rob Herring
  (?)
  (?)
@ 2021-11-17 15:41     ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 15:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 08:54:37AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> 
> Can you outline what exactly you want to disable? I don't think
> 'status' is the right way. I think between the parent device being
> disabled, an incomplete graph and user configuration choice that
> should be enough to disable parts.

The VOP2 on the RK3568 has three CRTCS, or video ports (VP) in Rockchip
nomenclature. Each of them can be connected to the different outputs,
like HDMI, MIPI-DSI and so on. In the device tree the CRTCs are
described as of-graph ports with links to the HDMI, MIPI-DSI nodes.
An example limited to HDMI looks like this:

	vop: vop@fe040000 {
		compatible = "rockchip,rk3568-vop";
		vop_out: ports {
			vp0: port@0 {
				vp0_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp0>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp1: port@1 {
				vp1_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp1>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp2: port@2 {
				...
			};
		};
	};

	hdmi: hdmi@fe0a0000 {
		compatible = "rockchip,rk3568-dw-hdmi";
		ports {
			hdmi_in: port@0 {
				hdmi_in_vp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&vp0_out_hdmi>;
					status = "disabled";
				};

				hdmi_in_vp1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&vp1_out_hdmi>;
					status = "disabled";
				};

				...
			};
		};
	};

Theoretically every VP can be routed to every output, but depending on
the board there are some constraints. For example for the three vps
there are only two PLLs for the pixel clock, and the HDMI port is
hardwired to one single PLL. To avoid different VPs setting conflicting
rates on a PLL we can only allow a subset of the possible routes.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 15:41     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 15:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 08:54:37AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> 
> Can you outline what exactly you want to disable? I don't think
> 'status' is the right way. I think between the parent device being
> disabled, an incomplete graph and user configuration choice that
> should be enough to disable parts.

The VOP2 on the RK3568 has three CRTCS, or video ports (VP) in Rockchip
nomenclature. Each of them can be connected to the different outputs,
like HDMI, MIPI-DSI and so on. In the device tree the CRTCs are
described as of-graph ports with links to the HDMI, MIPI-DSI nodes.
An example limited to HDMI looks like this:

	vop: vop@fe040000 {
		compatible = "rockchip,rk3568-vop";
		vop_out: ports {
			vp0: port@0 {
				vp0_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp0>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp1: port@1 {
				vp1_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp1>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp2: port@2 {
				...
			};
		};
	};

	hdmi: hdmi@fe0a0000 {
		compatible = "rockchip,rk3568-dw-hdmi";
		ports {
			hdmi_in: port@0 {
				hdmi_in_vp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&vp0_out_hdmi>;
					status = "disabled";
				};

				hdmi_in_vp1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&vp1_out_hdmi>;
					status = "disabled";
				};

				...
			};
		};
	};

Theoretically every VP can be routed to every output, but depending on
the board there are some constraints. For example for the three vps
there are only two PLLs for the pixel clock, and the HDMI port is
hardwired to one single PLL. To avoid different VPs setting conflicting
rates on a PLL we can only allow a subset of the possible routes.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 15:41     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 15:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 08:54:37AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> 
> Can you outline what exactly you want to disable? I don't think
> 'status' is the right way. I think between the parent device being
> disabled, an incomplete graph and user configuration choice that
> should be enough to disable parts.

The VOP2 on the RK3568 has three CRTCS, or video ports (VP) in Rockchip
nomenclature. Each of them can be connected to the different outputs,
like HDMI, MIPI-DSI and so on. In the device tree the CRTCs are
described as of-graph ports with links to the HDMI, MIPI-DSI nodes.
An example limited to HDMI looks like this:

	vop: vop@fe040000 {
		compatible = "rockchip,rk3568-vop";
		vop_out: ports {
			vp0: port@0 {
				vp0_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp0>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp1: port@1 {
				vp1_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp1>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp2: port@2 {
				...
			};
		};
	};

	hdmi: hdmi@fe0a0000 {
		compatible = "rockchip,rk3568-dw-hdmi";
		ports {
			hdmi_in: port@0 {
				hdmi_in_vp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&vp0_out_hdmi>;
					status = "disabled";
				};

				hdmi_in_vp1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&vp1_out_hdmi>;
					status = "disabled";
				};

				...
			};
		};
	};

Theoretically every VP can be routed to every output, but depending on
the board there are some constraints. For example for the three vps
there are only two PLLs for the pixel clock, and the HDMI port is
hardwired to one single PLL. To avoid different VPs setting conflicting
rates on a PLL we can only allow a subset of the possible routes.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-17 15:41     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 15:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 08:54:37AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> 
> Can you outline what exactly you want to disable? I don't think
> 'status' is the right way. I think between the parent device being
> disabled, an incomplete graph and user configuration choice that
> should be enough to disable parts.

The VOP2 on the RK3568 has three CRTCS, or video ports (VP) in Rockchip
nomenclature. Each of them can be connected to the different outputs,
like HDMI, MIPI-DSI and so on. In the device tree the CRTCs are
described as of-graph ports with links to the HDMI, MIPI-DSI nodes.
An example limited to HDMI looks like this:

	vop: vop@fe040000 {
		compatible = "rockchip,rk3568-vop";
		vop_out: ports {
			vp0: port@0 {
				vp0_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp0>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp1: port@1 {
				vp1_out_hdmi: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&hdmi_in_vp1>;
					status = "disabled";
				};

				... MIPI, dP, ...
			};

			vp2: port@2 {
				...
			};
		};
	};

	hdmi: hdmi@fe0a0000 {
		compatible = "rockchip,rk3568-dw-hdmi";
		ports {
			hdmi_in: port@0 {
				hdmi_in_vp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&vp0_out_hdmi>;
					status = "disabled";
				};

				hdmi_in_vp1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&vp1_out_hdmi>;
					status = "disabled";
				};

				...
			};
		};
	};

Theoretically every VP can be routed to every output, but depending on
the board there are some constraints. For example for the three vps
there are only two PLLs for the pixel clock, and the HDMI port is
hardwired to one single PLL. To avoid different VPs setting conflicting
rates on a PLL we can only allow a subset of the possible routes.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 15:44     ` Michael Riesch
  -1 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:44 UTC (permalink / raw)
  To: dri-devel, devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout, Michael Riesch

Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
Quartz64 Model A.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
---
 .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 4d4b2a301b1a..9fba790c6af4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -205,6 +205,16 @@ &gmac1m0_clkinout
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda_0v9>;
+	avdd-1v8-supply = <&vcc_1v8>;
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -546,3 +556,17 @@ bluetooth {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-17 15:44     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:44 UTC (permalink / raw)
  To: dri-devel, devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
  Cc: benjamin.gaignard, s.hauer, hjc, Michael Riesch, pgwipeout

Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
Quartz64 Model A.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
---
 .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 4d4b2a301b1a..9fba790c6af4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -205,6 +205,16 @@ &gmac1m0_clkinout
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda_0v9>;
+	avdd-1v8-supply = <&vcc_1v8>;
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -546,3 +556,17 @@ bluetooth {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-17 15:44     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:44 UTC (permalink / raw)
  To: dri-devel, devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout, Michael Riesch

Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
Quartz64 Model A.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
---
 .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 4d4b2a301b1a..9fba790c6af4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -205,6 +205,16 @@ &gmac1m0_clkinout
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda_0v9>;
+	avdd-1v8-supply = <&vcc_1v8>;
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -546,3 +556,17 @@ bluetooth {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-17 15:44     ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-17 15:44 UTC (permalink / raw)
  To: dri-devel, devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout, Michael Riesch

Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
Quartz64 Model A.

Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
---
 .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
index 4d4b2a301b1a..9fba790c6af4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
@@ -205,6 +205,16 @@ &gmac1m0_clkinout
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+	avdd-0v9-supply = <&vdda_0v9>;
+	avdd-1v8-supply = <&vcc_1v8>;
+};
+
+&hdmi_in_vp0 {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -546,3 +556,17 @@ bluetooth {
 &uart2 {
 	status = "okay";
 };
+
+&vop {
+	status = "okay";
+	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
+&vp0_out_hdmi {
+	status = "okay";
+};
-- 
2.30.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 201+ messages in thread

* Re: [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 16:10     ` Rob Herring
  -1 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 16:10 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Heiko Stübner, Michael Riesch, Peter Geis,
	linux-arm-kernel, linux-rockchip, Sandy Huang, Benjamin Gaignard,
	kernel, dri-devel

On Wed, 17 Nov 2021 15:33:42 +0100, Sascha Hauer wrote:
> The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
> The binding differs slightly from the existing VOP binding, so add a new
> binding file for it.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
>  1 file changed, 114 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:0: [0, 4261675008, 0, 12288] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:1: [0, 4261691392, 0, 4096] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1556199

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 16:10     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 16:10 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, Peter Geis, kernel,
	linux-arm-kernel

On Wed, 17 Nov 2021 15:33:42 +0100, Sascha Hauer wrote:
> The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
> The binding differs slightly from the existing VOP binding, so add a new
> binding file for it.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
>  1 file changed, 114 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:0: [0, 4261675008, 0, 12288] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:1: [0, 4261691392, 0, 4096] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1556199

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 16:10     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 16:10 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Heiko Stübner, Michael Riesch, Peter Geis,
	linux-arm-kernel, linux-rockchip, Sandy Huang, Benjamin Gaignard,
	kernel, dri-devel

On Wed, 17 Nov 2021 15:33:42 +0100, Sascha Hauer wrote:
> The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
> The binding differs slightly from the existing VOP binding, so add a new
> binding file for it.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
>  1 file changed, 114 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:0: [0, 4261675008, 0, 12288] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:1: [0, 4261691392, 0, 4096] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1556199

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2
@ 2021-11-17 16:10     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-17 16:10 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Heiko Stübner, Michael Riesch, Peter Geis,
	linux-arm-kernel, linux-rockchip, Sandy Huang, Benjamin Gaignard,
	kernel, dri-devel

On Wed, 17 Nov 2021 15:33:42 +0100, Sascha Hauer wrote:
> The VOP2 is found on newer Rockchip SoCs like the rk3568 or the rk3566.
> The binding differs slightly from the existing VOP binding, so add a new
> binding file for it.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip-vop2.yaml       | 114 ++++++++++++++++++
>  1 file changed, 114 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:0: [0, 4261675008, 0, 12288] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.example.dt.yaml: example-0: vop@fe040000:reg:1: [0, 4261691392, 0, 4096] is too long
	From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1556199

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-17 18:05     ` Nicolas Frattaroli
  -1 siblings, 0 replies; 201+ messages in thread
From: Nicolas Frattaroli @ 2021-11-17 18:05 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-rockchip, linux-arm-kernel, linux-rockchip, devicetree,
	kernel, Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> It replaces the VOP unit found in the older Rockchip SoCs.
> 
> This driver has been derived from the downstream Rockchip Kernel and
> heavily modified:
> 
> - All nonstandard DRM properties have been removed
> - dropped struct vop2_plane_state and pass around less data between
>   functions
> - Dropped all DRM_FORMAT_* not known on upstream
> - rework register access to get rid of excessively used macros
> 
> The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> board. Overlay support is tested with the modetest utility. AFBC support
> is still present in the driver, but currently untested due to the lack
> of suitable image sources. Also the driver has been tested with weston
> using pixman and (yet to be upstreamed) panfrost driver support.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---

Hi Sascha,

thank you very much for your work on this! I gave it a try tonight,
and unfortunately it appears to currently always attempt to use
1920x1080p60 as the mode regardless of the monitor. For example,
on an old 720p monitor I had laying around:

	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0

This results in a broken picture (all white with occasional glitches).
Somebody else observed the same behaviour on a 1440p monitor.

Thanks,
Nicolas Frattaroli



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 18:05     ` Nicolas Frattaroli
  0 siblings, 0 replies; 201+ messages in thread
From: Nicolas Frattaroli @ 2021-11-17 18:05 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-rockchip, linux-arm-kernel, linux-rockchip, devicetree,
	kernel, Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> It replaces the VOP unit found in the older Rockchip SoCs.
> 
> This driver has been derived from the downstream Rockchip Kernel and
> heavily modified:
> 
> - All nonstandard DRM properties have been removed
> - dropped struct vop2_plane_state and pass around less data between
>   functions
> - Dropped all DRM_FORMAT_* not known on upstream
> - rework register access to get rid of excessively used macros
> 
> The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> board. Overlay support is tested with the modetest utility. AFBC support
> is still present in the driver, but currently untested due to the lack
> of suitable image sources. Also the driver has been tested with weston
> using pixman and (yet to be upstreamed) panfrost driver support.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---

Hi Sascha,

thank you very much for your work on this! I gave it a try tonight,
and unfortunately it appears to currently always attempt to use
1920x1080p60 as the mode regardless of the monitor. For example,
on an old 720p monitor I had laying around:

	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0

This results in a broken picture (all white with occasional glitches).
Somebody else observed the same behaviour on a 1440p monitor.

Thanks,
Nicolas Frattaroli



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 18:05     ` Nicolas Frattaroli
  0 siblings, 0 replies; 201+ messages in thread
From: Nicolas Frattaroli @ 2021-11-17 18:05 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, Peter Geis, linux-arm-kernel

On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> It replaces the VOP unit found in the older Rockchip SoCs.
> 
> This driver has been derived from the downstream Rockchip Kernel and
> heavily modified:
> 
> - All nonstandard DRM properties have been removed
> - dropped struct vop2_plane_state and pass around less data between
>   functions
> - Dropped all DRM_FORMAT_* not known on upstream
> - rework register access to get rid of excessively used macros
> 
> The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> board. Overlay support is tested with the modetest utility. AFBC support
> is still present in the driver, but currently untested due to the lack
> of suitable image sources. Also the driver has been tested with weston
> using pixman and (yet to be upstreamed) panfrost driver support.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---

Hi Sascha,

thank you very much for your work on this! I gave it a try tonight,
and unfortunately it appears to currently always attempt to use
1920x1080p60 as the mode regardless of the monitor. For example,
on an old 720p monitor I had laying around:

	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0

This results in a broken picture (all white with occasional glitches).
Somebody else observed the same behaviour on a 1440p monitor.

Thanks,
Nicolas Frattaroli



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 18:05     ` Nicolas Frattaroli
  0 siblings, 0 replies; 201+ messages in thread
From: Nicolas Frattaroli @ 2021-11-17 18:05 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-rockchip, linux-arm-kernel, linux-rockchip, devicetree,
	kernel, Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> It replaces the VOP unit found in the older Rockchip SoCs.
> 
> This driver has been derived from the downstream Rockchip Kernel and
> heavily modified:
> 
> - All nonstandard DRM properties have been removed
> - dropped struct vop2_plane_state and pass around less data between
>   functions
> - Dropped all DRM_FORMAT_* not known on upstream
> - rework register access to get rid of excessively used macros
> 
> The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> board. Overlay support is tested with the modetest utility. AFBC support
> is still present in the driver, but currently untested due to the lack
> of suitable image sources. Also the driver has been tested with weston
> using pixman and (yet to be upstreamed) panfrost driver support.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---

Hi Sascha,

thank you very much for your work on this! I gave it a try tonight,
and unfortunately it appears to currently always attempt to use
1920x1080p60 as the mode regardless of the monitor. For example,
on an old 720p monitor I had laying around:

	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0

This results in a broken picture (all white with occasional glitches).
Somebody else observed the same behaviour on a 1440p monitor.

Thanks,
Nicolas Frattaroli



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
  2021-11-17 18:05     ` Nicolas Frattaroli
                       ` (2 preceding siblings ...)
  (?)
@ 2021-11-17 18:38     ` Dan Johansen
  -1 siblings, 0 replies; 201+ messages in thread
From: Dan Johansen @ 2021-11-17 18:38 UTC (permalink / raw)
  To: linux-rockchip

Den 17.11.2021 kl. 19.05 skrev Nicolas Frattaroli:
> On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
>> The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
>> It replaces the VOP unit found in the older Rockchip SoCs.
>>
>> This driver has been derived from the downstream Rockchip Kernel and
>> heavily modified:
>>
>> - All nonstandard DRM properties have been removed
>> - dropped struct vop2_plane_state and pass around less data between
>>    functions
>> - Dropped all DRM_FORMAT_* not known on upstream
>> - rework register access to get rid of excessively used macros
>>
>> The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
>> board. Overlay support is tested with the modetest utility. AFBC support
>> is still present in the driver, but currently untested due to the lack
>> of suitable image sources. Also the driver has been tested with weston
>> using pixman and (yet to be upstreamed) panfrost driver support.
>>
>> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
>> ---
> Hi Sascha,
>
> thank you very much for your work on this! I gave it a try tonight,
> and unfortunately it appears to currently always attempt to use
> 1920x1080p60 as the mode regardless of the monitor. For example,
> on an old 720p monitor I had laying around:
>
> 	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0
>
> This results in a broken picture (all white with occasional glitches).
> Somebody else observed the same behaviour on a 1440p monitor.

Yes, my 1440p Dell screen showed white noise picture and so does my Sony 
Bravia 1080p TV, but that is likely not running at 60 hertz.

In any case, nice work as I've heard it works on regular 1080p monitors.

>
> Thanks,
> Nicolas Frattaroli
>
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
-- 
Kind regards
*Dan Johansen*
Project lead of the *Manjaro ARM* project
Manjaro-ARM <https://manjaro.org>

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
  2021-11-17 18:05     ` Nicolas Frattaroli
  (?)
  (?)
@ 2021-11-17 19:45       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 19:45 UTC (permalink / raw)
  To: Nicolas Frattaroli
  Cc: dri-devel, linux-rockchip, linux-arm-kernel, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 07:05:33PM +0100, Nicolas Frattaroli wrote:
> On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> > It replaces the VOP unit found in the older Rockchip SoCs.
> > 
> > This driver has been derived from the downstream Rockchip Kernel and
> > heavily modified:
> > 
> > - All nonstandard DRM properties have been removed
> > - dropped struct vop2_plane_state and pass around less data between
> >   functions
> > - Dropped all DRM_FORMAT_* not known on upstream
> > - rework register access to get rid of excessively used macros
> > 
> > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> > board. Overlay support is tested with the modetest utility. AFBC support
> > is still present in the driver, but currently untested due to the lack
> > of suitable image sources. Also the driver has been tested with weston
> > using pixman and (yet to be upstreamed) panfrost driver support.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> 
> Hi Sascha,
> 
> thank you very much for your work on this! I gave it a try tonight,
> and unfortunately it appears to currently always attempt to use
> 1920x1080p60 as the mode regardless of the monitor. For example,
> on an old 720p monitor I had laying around:
> 
> 	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0
> 
> This results in a broken picture (all white with occasional glitches).
> Somebody else observed the same behaviour on a 1440p monitor.

Unfortunately all my monitors I have here have exactly 1920x1080p60, so
I didn't notice. Anyway, when I try another mode like 1280x1024 which
should be supported as well then my monitor responds with "out of
range", so something is indeed fishy here.

I'll have a look into it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 19:45       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 19:45 UTC (permalink / raw)
  To: Nicolas Frattaroli
  Cc: dri-devel, linux-rockchip, linux-arm-kernel, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 07:05:33PM +0100, Nicolas Frattaroli wrote:
> On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> > It replaces the VOP unit found in the older Rockchip SoCs.
> > 
> > This driver has been derived from the downstream Rockchip Kernel and
> > heavily modified:
> > 
> > - All nonstandard DRM properties have been removed
> > - dropped struct vop2_plane_state and pass around less data between
> >   functions
> > - Dropped all DRM_FORMAT_* not known on upstream
> > - rework register access to get rid of excessively used macros
> > 
> > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> > board. Overlay support is tested with the modetest utility. AFBC support
> > is still present in the driver, but currently untested due to the lack
> > of suitable image sources. Also the driver has been tested with weston
> > using pixman and (yet to be upstreamed) panfrost driver support.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> 
> Hi Sascha,
> 
> thank you very much for your work on this! I gave it a try tonight,
> and unfortunately it appears to currently always attempt to use
> 1920x1080p60 as the mode regardless of the monitor. For example,
> on an old 720p monitor I had laying around:
> 
> 	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0
> 
> This results in a broken picture (all white with occasional glitches).
> Somebody else observed the same behaviour on a 1440p monitor.

Unfortunately all my monitors I have here have exactly 1920x1080p60, so
I didn't notice. Anyway, when I try another mode like 1280x1024 which
should be supported as well then my monitor responds with "out of
range", so something is indeed fishy here.

I'll have a look into it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 19:45       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 19:45 UTC (permalink / raw)
  To: Nicolas Frattaroli
  Cc: dri-devel, linux-rockchip, linux-arm-kernel, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 07:05:33PM +0100, Nicolas Frattaroli wrote:
> On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> > It replaces the VOP unit found in the older Rockchip SoCs.
> > 
> > This driver has been derived from the downstream Rockchip Kernel and
> > heavily modified:
> > 
> > - All nonstandard DRM properties have been removed
> > - dropped struct vop2_plane_state and pass around less data between
> >   functions
> > - Dropped all DRM_FORMAT_* not known on upstream
> > - rework register access to get rid of excessively used macros
> > 
> > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> > board. Overlay support is tested with the modetest utility. AFBC support
> > is still present in the driver, but currently untested due to the lack
> > of suitable image sources. Also the driver has been tested with weston
> > using pixman and (yet to be upstreamed) panfrost driver support.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> 
> Hi Sascha,
> 
> thank you very much for your work on this! I gave it a try tonight,
> and unfortunately it appears to currently always attempt to use
> 1920x1080p60 as the mode regardless of the monitor. For example,
> on an old 720p monitor I had laying around:
> 
> 	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0
> 
> This results in a broken picture (all white with occasional glitches).
> Somebody else observed the same behaviour on a 1440p monitor.

Unfortunately all my monitors I have here have exactly 1920x1080p60, so
I didn't notice. Anyway, when I try another mode like 1280x1024 which
should be supported as well then my monitor responds with "out of
range", so something is indeed fishy here.

I'll have a look into it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-17 19:45       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-17 19:45 UTC (permalink / raw)
  To: Nicolas Frattaroli
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

On Wed, Nov 17, 2021 at 07:05:33PM +0100, Nicolas Frattaroli wrote:
> On Mittwoch, 17. November 2021 15:33:47 CET Sascha Hauer wrote:
> > The VOP2 unit is found on Rockchip SoCs beginning with rk3566/rk3568.
> > It replaces the VOP unit found in the older Rockchip SoCs.
> > 
> > This driver has been derived from the downstream Rockchip Kernel and
> > heavily modified:
> > 
> > - All nonstandard DRM properties have been removed
> > - dropped struct vop2_plane_state and pass around less data between
> >   functions
> > - Dropped all DRM_FORMAT_* not known on upstream
> > - rework register access to get rid of excessively used macros
> > 
> > The driver is tested with HDMI and MIPI-DSI display on a RK3568-EVB
> > board. Overlay support is tested with the modetest utility. AFBC support
> > is still present in the driver, but currently untested due to the lack
> > of suitable image sources. Also the driver has been tested with weston
> > using pixman and (yet to be upstreamed) panfrost driver support.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> 
> Hi Sascha,
> 
> thank you very much for your work on this! I gave it a try tonight,
> and unfortunately it appears to currently always attempt to use
> 1920x1080p60 as the mode regardless of the monitor. For example,
> on an old 720p monitor I had laying around:
> 
> 	[  225.732342] rockchip-drm display-subsystem: [drm] Update mode to 1920x1080p60, type: 11 for vp0, output 0x00000800  HDMI0
> 
> This results in a broken picture (all white with occasional glitches).
> Somebody else observed the same behaviour on a 1440p monitor.

Unfortunately all my monitors I have here have exactly 1920x1080p60, so
I didn't notice. Anyway, when I try another mode like 1280x1024 which
should be supported as well then my monitor responds with "out of
range", so something is indeed fishy here.

I'll have a look into it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-18  1:27   ` Kever Yang
  -1 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18  1:27 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, 闫孝军

Hi Sascha Hauer,

On 2021/11/17 下午10:33, Sascha Hauer wrote:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel

Yes, you do know this is from Rockchip kernel.

Could you point me out where is the information about original author  
in your commit?

>   and heavily polished, most non
> standard features have been removed for now.

I don't agree with this, we do believe you have do some clean up to meet 
the requirement

of upstream, but all the framework and feature implement are from 
Rockchip engineer,

we have made a great effort to make everything work which block us to 
upstream this driver for now.


NAK for this series.


- Kever




^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  1:27   ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18  1:27 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, 闫孝军

Hi Sascha Hauer,

On 2021/11/17 下午10:33, Sascha Hauer wrote:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel

Yes, you do know this is from Rockchip kernel.

Could you point me out where is the information about original author  
in your commit?

>   and heavily polished, most non
> standard features have been removed for now.

I don't agree with this, we do believe you have do some clean up to meet 
the requirement

of upstream, but all the framework and feature implement are from 
Rockchip engineer,

we have made a great effort to make everything work which block us to 
upstream this driver for now.


NAK for this series.


- Kever




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  1:27   ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18  1:27 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis, 闫孝军

Hi Sascha Hauer,

On 2021/11/17 下午10:33, Sascha Hauer wrote:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel

Yes, you do know this is from Rockchip kernel.

Could you point me out where is the information about original author  
in your commit?

>   and heavily polished, most non
> standard features have been removed for now.

I don't agree with this, we do believe you have do some clean up to meet 
the requirement

of upstream, but all the framework and feature implement are from 
Rockchip engineer,

we have made a great effort to make everything work which block us to 
upstream this driver for now.


NAK for this series.


- Kever




_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  1:27   ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18  1:27 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	Peter Geis, linux-arm-kernel

Hi Sascha Hauer,

On 2021/11/17 下午10:33, Sascha Hauer wrote:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel

Yes, you do know this is from Rockchip kernel.

Could you point me out where is the information about original author  
in your commit?

>   and heavily polished, most non
> standard features have been removed for now.

I don't agree with this, we do believe you have do some clean up to meet 
the requirement

of upstream, but all the framework and feature implement are from 
Rockchip engineer,

we have made a great effort to make everything work which block us to 
upstream this driver for now.


NAK for this series.


- Kever




^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18  1:27   ` Kever Yang
  (?)
  (?)
@ 2021-11-18  9:26     ` Heiko Stübner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-18  9:26 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel, Kever Yang
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	闫孝军

Hi Kever,

Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> Hi Sascha Hauer,
> 
> On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel
> 
> Yes, you do know this is from Rockchip kernel.
> 
> Could you point me out where is the information about original author  
> in your commit?

The copyrights for added files seem to have stayed intact.
For example the added rockchip_drm_vop2.c file in patch12
does contain the copyright as

	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
	Author: Andy Yan <andy.yan@rock-chips.com>


We can of course debate if the commit-author should also be set to
Andy or another Rockchip engineer, with Sascha adding a 
"Co-developed-by" with his credentials.

That's probably a nice compromise, I guess.


> >   and heavily polished, most non
> > standard features have been removed for now.
> 
> I don't agree with this, we do believe you have do some clean up to meet 
> the requirement
> 
> of upstream, but all the framework and feature implement are from 
> Rockchip engineer,
> 
> we have made a great effort to make everything work which block us to 
> upstream this driver for now.

I don't fully understand what you mean here (language barrier probably),
but dropping non-essential functionality in a first round is pretty common
to at least get basic functionality working for everyone. With the special
features getting added again in later patches over time. This happenened
on the old vop as well.

And of course, having a kernel that can "just" do normal graphics without
the additional features is still preferable over having _NO_ graphics support
at all ;-)


> NAK for this series.

As you might've seen from previous graphics related patches, there
is a big number of people _and companies_ that seems to want/need
to work with the rk3566/rk3568 with a kernel based on mainline.

--> Most likely even in real products!

While Rockchip did say that they want to upstream VOP2 support, there
has been _NO_ movement or even information at all on this over at least
the last year(!), so it's pretty understandable that developers will do this
themself at some point, because they don't want to wait anymore for
something that might never happen.

So a simple "NAK" without additional information is not really helpful here.

If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
plans on upstreaming at least basic graphis support themself.

The kernel is often called a do-ocracy - the one who does the work, gets
to decide. So if you really don't like Sascha's series at all, I do expect
Rockchip to step up and provide a solution themself - and in a usable
timeframe.


Heiko



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:26     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-18  9:26 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel, Kever Yang
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	闫孝军

Hi Kever,

Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> Hi Sascha Hauer,
> 
> On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel
> 
> Yes, you do know this is from Rockchip kernel.
> 
> Could you point me out where is the information about original author  
> in your commit?

The copyrights for added files seem to have stayed intact.
For example the added rockchip_drm_vop2.c file in patch12
does contain the copyright as

	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
	Author: Andy Yan <andy.yan@rock-chips.com>


We can of course debate if the commit-author should also be set to
Andy or another Rockchip engineer, with Sascha adding a 
"Co-developed-by" with his credentials.

That's probably a nice compromise, I guess.


> >   and heavily polished, most non
> > standard features have been removed for now.
> 
> I don't agree with this, we do believe you have do some clean up to meet 
> the requirement
> 
> of upstream, but all the framework and feature implement are from 
> Rockchip engineer,
> 
> we have made a great effort to make everything work which block us to 
> upstream this driver for now.

I don't fully understand what you mean here (language barrier probably),
but dropping non-essential functionality in a first round is pretty common
to at least get basic functionality working for everyone. With the special
features getting added again in later patches over time. This happenened
on the old vop as well.

And of course, having a kernel that can "just" do normal graphics without
the additional features is still preferable over having _NO_ graphics support
at all ;-)


> NAK for this series.

As you might've seen from previous graphics related patches, there
is a big number of people _and companies_ that seems to want/need
to work with the rk3566/rk3568 with a kernel based on mainline.

--> Most likely even in real products!

While Rockchip did say that they want to upstream VOP2 support, there
has been _NO_ movement or even information at all on this over at least
the last year(!), so it's pretty understandable that developers will do this
themself at some point, because they don't want to wait anymore for
something that might never happen.

So a simple "NAK" without additional information is not really helpful here.

If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
plans on upstreaming at least basic graphis support themself.

The kernel is often called a do-ocracy - the one who does the work, gets
to decide. So if you really don't like Sascha's series at all, I do expect
Rockchip to step up and provide a solution themself - and in a usable
timeframe.


Heiko



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:26     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-18  9:26 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel, Kever Yang
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi Kever,

Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> Hi Sascha Hauer,
> 
> On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel
> 
> Yes, you do know this is from Rockchip kernel.
> 
> Could you point me out where is the information about original author  
> in your commit?

The copyrights for added files seem to have stayed intact.
For example the added rockchip_drm_vop2.c file in patch12
does contain the copyright as

	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
	Author: Andy Yan <andy.yan@rock-chips.com>


We can of course debate if the commit-author should also be set to
Andy or another Rockchip engineer, with Sascha adding a 
"Co-developed-by" with his credentials.

That's probably a nice compromise, I guess.


> >   and heavily polished, most non
> > standard features have been removed for now.
> 
> I don't agree with this, we do believe you have do some clean up to meet 
> the requirement
> 
> of upstream, but all the framework and feature implement are from 
> Rockchip engineer,
> 
> we have made a great effort to make everything work which block us to 
> upstream this driver for now.

I don't fully understand what you mean here (language barrier probably),
but dropping non-essential functionality in a first round is pretty common
to at least get basic functionality working for everyone. With the special
features getting added again in later patches over time. This happenened
on the old vop as well.

And of course, having a kernel that can "just" do normal graphics without
the additional features is still preferable over having _NO_ graphics support
at all ;-)


> NAK for this series.

As you might've seen from previous graphics related patches, there
is a big number of people _and companies_ that seems to want/need
to work with the rk3566/rk3568 with a kernel based on mainline.

--> Most likely even in real products!

While Rockchip did say that they want to upstream VOP2 support, there
has been _NO_ movement or even information at all on this over at least
the last year(!), so it's pretty understandable that developers will do this
themself at some point, because they don't want to wait anymore for
something that might never happen.

So a simple "NAK" without additional information is not really helpful here.

If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
plans on upstreaming at least basic graphis support themself.

The kernel is often called a do-ocracy - the one who does the work, gets
to decide. So if you really don't like Sascha's series at all, I do expect
Rockchip to step up and provide a solution themself - and in a usable
timeframe.


Heiko



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:26     ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-18  9:26 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel, Kever Yang
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	闫孝军

Hi Kever,

Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> Hi Sascha Hauer,
> 
> On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel
> 
> Yes, you do know this is from Rockchip kernel.
> 
> Could you point me out where is the information about original author  
> in your commit?

The copyrights for added files seem to have stayed intact.
For example the added rockchip_drm_vop2.c file in patch12
does contain the copyright as

	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
	Author: Andy Yan <andy.yan@rock-chips.com>


We can of course debate if the commit-author should also be set to
Andy or another Rockchip engineer, with Sascha adding a 
"Co-developed-by" with his credentials.

That's probably a nice compromise, I guess.


> >   and heavily polished, most non
> > standard features have been removed for now.
> 
> I don't agree with this, we do believe you have do some clean up to meet 
> the requirement
> 
> of upstream, but all the framework and feature implement are from 
> Rockchip engineer,
> 
> we have made a great effort to make everything work which block us to 
> upstream this driver for now.

I don't fully understand what you mean here (language barrier probably),
but dropping non-essential functionality in a first round is pretty common
to at least get basic functionality working for everyone. With the special
features getting added again in later patches over time. This happenened
on the old vop as well.

And of course, having a kernel that can "just" do normal graphics without
the additional features is still preferable over having _NO_ graphics support
at all ;-)


> NAK for this series.

As you might've seen from previous graphics related patches, there
is a big number of people _and companies_ that seems to want/need
to work with the rk3566/rk3568 with a kernel based on mainline.

--> Most likely even in real products!

While Rockchip did say that they want to upstream VOP2 support, there
has been _NO_ movement or even information at all on this over at least
the last year(!), so it's pretty understandable that developers will do this
themself at some point, because they don't want to wait anymore for
something that might never happen.

So a simple "NAK" without additional information is not really helpful here.

If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
plans on upstreaming at least basic graphis support themself.

The kernel is often called a do-ocracy - the one who does the work, gets
to decide. So if you really don't like Sascha's series at all, I do expect
Rockchip to step up and provide a solution themself - and in a usable
timeframe.


Heiko



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18  9:26     ` Heiko Stübner
  (?)
  (?)
@ 2021-11-18  9:53       ` Daniel Stone
  -1 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18  9:53 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Sascha Hauer, dri-devel, Kever Yang, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi,

On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > I don't agree with this, we do believe you have do some clean up to meet
> > the requirement
> >
> > of upstream, but all the framework and feature implement are from
> > Rockchip engineer,
> >
> > we have made a great effort to make everything work which block us to
> > upstream this driver for now.
>
> I don't fully understand what you mean here (language barrier probably),
> but dropping non-essential functionality in a first round is pretty common
> to at least get basic functionality working for everyone. With the special
> features getting added again in later patches over time. This happenened
> on the old vop as well.
>
> And of course, having a kernel that can "just" do normal graphics without
> the additional features is still preferable over having _NO_ graphics support
> at all ;-)
>
> > NAK for this series.
>
> As you might've seen from previous graphics related patches, there
> is a big number of people _and companies_ that seems to want/need
> to work with the rk3566/rk3568 with a kernel based on mainline.
>
> --> Most likely even in real products!

Yes, we've been trying to ship a real product based on RK356x. We
started by using the vendor VOP2 driver, but it is broken beyond
belief. The driver needs a fundamental ground-up rework, and all the
additional features get in the way of doing this core rework to make
it actually function correctly.

So, NAK to the NAK. I would like to see the VOP2 support start simple,
with more features being added one by one.

> While Rockchip did say that they want to upstream VOP2 support, there
> has been _NO_ movement or even information at all on this over at least
> the last year(!), so it's pretty understandable that developers will do this
> themself at some point, because they don't want to wait anymore for
> something that might never happen.
>
> So a simple "NAK" without additional information is not really helpful here.
>
> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
> plans on upstreaming at least basic graphis support themself.
>
> The kernel is often called a do-ocracy - the one who does the work, gets
> to decide. So if you really don't like Sascha's series at all, I do expect
> Rockchip to step up and provide a solution themself - and in a usable
> timeframe.

Exactly what Heiko said. If you would like to upstream the driver then
that would be fantastic to see, but I'm afraid you do not get to
prevent someone else from doing the work themselves.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:53       ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18  9:53 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Sascha Hauer, dri-devel, Kever Yang, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi,

On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > I don't agree with this, we do believe you have do some clean up to meet
> > the requirement
> >
> > of upstream, but all the framework and feature implement are from
> > Rockchip engineer,
> >
> > we have made a great effort to make everything work which block us to
> > upstream this driver for now.
>
> I don't fully understand what you mean here (language barrier probably),
> but dropping non-essential functionality in a first round is pretty common
> to at least get basic functionality working for everyone. With the special
> features getting added again in later patches over time. This happenened
> on the old vop as well.
>
> And of course, having a kernel that can "just" do normal graphics without
> the additional features is still preferable over having _NO_ graphics support
> at all ;-)
>
> > NAK for this series.
>
> As you might've seen from previous graphics related patches, there
> is a big number of people _and companies_ that seems to want/need
> to work with the rk3566/rk3568 with a kernel based on mainline.
>
> --> Most likely even in real products!

Yes, we've been trying to ship a real product based on RK356x. We
started by using the vendor VOP2 driver, but it is broken beyond
belief. The driver needs a fundamental ground-up rework, and all the
additional features get in the way of doing this core rework to make
it actually function correctly.

So, NAK to the NAK. I would like to see the VOP2 support start simple,
with more features being added one by one.

> While Rockchip did say that they want to upstream VOP2 support, there
> has been _NO_ movement or even information at all on this over at least
> the last year(!), so it's pretty understandable that developers will do this
> themself at some point, because they don't want to wait anymore for
> something that might never happen.
>
> So a simple "NAK" without additional information is not really helpful here.
>
> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
> plans on upstreaming at least basic graphis support themself.
>
> The kernel is often called a do-ocracy - the one who does the work, gets
> to decide. So if you really don't like Sascha's series at all, I do expect
> Rockchip to step up and provide a solution themself - and in a usable
> timeframe.

Exactly what Heiko said. If you would like to upstream the driver then
that would be fantastic to see, but I'm afraid you do not get to
prevent someone else from doing the work themselves.

Cheers,
Daniel

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:53       ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18  9:53 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: devicetree, Benjamin Gaignard, kernel, Sascha Hauer, Kever Yang,
	dri-devel, Sandy Huang, linux-rockchip, Michael Riesch,
	Peter Geis, 闫孝军,
	linux-arm-kernel

Hi,

On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > I don't agree with this, we do believe you have do some clean up to meet
> > the requirement
> >
> > of upstream, but all the framework and feature implement are from
> > Rockchip engineer,
> >
> > we have made a great effort to make everything work which block us to
> > upstream this driver for now.
>
> I don't fully understand what you mean here (language barrier probably),
> but dropping non-essential functionality in a first round is pretty common
> to at least get basic functionality working for everyone. With the special
> features getting added again in later patches over time. This happenened
> on the old vop as well.
>
> And of course, having a kernel that can "just" do normal graphics without
> the additional features is still preferable over having _NO_ graphics support
> at all ;-)
>
> > NAK for this series.
>
> As you might've seen from previous graphics related patches, there
> is a big number of people _and companies_ that seems to want/need
> to work with the rk3566/rk3568 with a kernel based on mainline.
>
> --> Most likely even in real products!

Yes, we've been trying to ship a real product based on RK356x. We
started by using the vendor VOP2 driver, but it is broken beyond
belief. The driver needs a fundamental ground-up rework, and all the
additional features get in the way of doing this core rework to make
it actually function correctly.

So, NAK to the NAK. I would like to see the VOP2 support start simple,
with more features being added one by one.

> While Rockchip did say that they want to upstream VOP2 support, there
> has been _NO_ movement or even information at all on this over at least
> the last year(!), so it's pretty understandable that developers will do this
> themself at some point, because they don't want to wait anymore for
> something that might never happen.
>
> So a simple "NAK" without additional information is not really helpful here.
>
> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
> plans on upstreaming at least basic graphis support themself.
>
> The kernel is often called a do-ocracy - the one who does the work, gets
> to decide. So if you really don't like Sascha's series at all, I do expect
> Rockchip to step up and provide a solution themself - and in a usable
> timeframe.

Exactly what Heiko said. If you would like to upstream the driver then
that would be fantastic to see, but I'm afraid you do not get to
prevent someone else from doing the work themselves.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18  9:53       ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18  9:53 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Sascha Hauer, dri-devel, Kever Yang, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi,

On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > I don't agree with this, we do believe you have do some clean up to meet
> > the requirement
> >
> > of upstream, but all the framework and feature implement are from
> > Rockchip engineer,
> >
> > we have made a great effort to make everything work which block us to
> > upstream this driver for now.
>
> I don't fully understand what you mean here (language barrier probably),
> but dropping non-essential functionality in a first round is pretty common
> to at least get basic functionality working for everyone. With the special
> features getting added again in later patches over time. This happenened
> on the old vop as well.
>
> And of course, having a kernel that can "just" do normal graphics without
> the additional features is still preferable over having _NO_ graphics support
> at all ;-)
>
> > NAK for this series.
>
> As you might've seen from previous graphics related patches, there
> is a big number of people _and companies_ that seems to want/need
> to work with the rk3566/rk3568 with a kernel based on mainline.
>
> --> Most likely even in real products!

Yes, we've been trying to ship a real product based on RK356x. We
started by using the vendor VOP2 driver, but it is broken beyond
belief. The driver needs a fundamental ground-up rework, and all the
additional features get in the way of doing this core rework to make
it actually function correctly.

So, NAK to the NAK. I would like to see the VOP2 support start simple,
with more features being added one by one.

> While Rockchip did say that they want to upstream VOP2 support, there
> has been _NO_ movement or even information at all on this over at least
> the last year(!), so it's pretty understandable that developers will do this
> themself at some point, because they don't want to wait anymore for
> something that might never happen.
>
> So a simple "NAK" without additional information is not really helpful here.
>
> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
> plans on upstreaming at least basic graphis support themself.
>
> The kernel is often called a do-ocracy - the one who does the work, gets
> to decide. So if you really don't like Sascha's series at all, I do expect
> Rockchip to step up and provide a solution themself - and in a usable
> timeframe.

Exactly what Heiko said. If you would like to upstream the driver then
that would be fantastic to see, but I'm afraid you do not get to
prevent someone else from doing the work themselves.

Cheers,
Daniel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18  9:26     ` Heiko Stübner
  (?)
  (?)
@ 2021-11-18 10:03       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-18 10:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, Kever Yang, linux-arm-kernel, linux-rockchip,
	devicetree, kernel, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis, 闫孝军

On Thu, Nov 18, 2021 at 10:26:29AM +0100, Heiko Stübner wrote:
> Hi Kever,
> 
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > Hi Sascha Hauer,
> > 
> > On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > > This series adds initial graphics support for the Rockchip RK356[68]
> > > SoCs.  Graphics support is based around the VOP2 controller which
> > > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > > has been tested with HDMI support included in this series and MIPI-DSI
> > > which is not included because it needs some more work. The driver is
> > > taken from the downstream Rockchip kernel
> > 
> > Yes, you do know this is from Rockchip kernel.
> > 
> > Could you point me out where is the information about original author  
> > in your commit?
> 
> The copyrights for added files seem to have stayed intact.
> For example the added rockchip_drm_vop2.c file in patch12
> does contain the copyright as
> 
> 	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
> 	Author: Andy Yan <andy.yan@rock-chips.com>
> 
> 
> We can of course debate if the commit-author should also be set to
> Andy or another Rockchip engineer, with Sascha adding a 
> "Co-developed-by" with his credentials.
> 
> That's probably a nice compromise, I guess.

The commit author was merely lost while copying the driver file into my git.
Changing it back to Andy is fine with me, I didn't mean to steal anyones
credits.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:03       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-18 10:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Kever Yang, dri-devel,
	Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	闫孝军,
	linux-arm-kernel

On Thu, Nov 18, 2021 at 10:26:29AM +0100, Heiko Stübner wrote:
> Hi Kever,
> 
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > Hi Sascha Hauer,
> > 
> > On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > > This series adds initial graphics support for the Rockchip RK356[68]
> > > SoCs.  Graphics support is based around the VOP2 controller which
> > > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > > has been tested with HDMI support included in this series and MIPI-DSI
> > > which is not included because it needs some more work. The driver is
> > > taken from the downstream Rockchip kernel
> > 
> > Yes, you do know this is from Rockchip kernel.
> > 
> > Could you point me out where is the information about original author  
> > in your commit?
> 
> The copyrights for added files seem to have stayed intact.
> For example the added rockchip_drm_vop2.c file in patch12
> does contain the copyright as
> 
> 	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
> 	Author: Andy Yan <andy.yan@rock-chips.com>
> 
> 
> We can of course debate if the commit-author should also be set to
> Andy or another Rockchip engineer, with Sascha adding a 
> "Co-developed-by" with his credentials.
> 
> That's probably a nice compromise, I guess.

The commit author was merely lost while copying the driver file into my git.
Changing it back to Andy is fine with me, I didn't mean to steal anyones
credits.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:03       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-18 10:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, Kever Yang, linux-arm-kernel, linux-rockchip,
	devicetree, kernel, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis, 闫孝军

On Thu, Nov 18, 2021 at 10:26:29AM +0100, Heiko Stübner wrote:
> Hi Kever,
> 
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > Hi Sascha Hauer,
> > 
> > On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > > This series adds initial graphics support for the Rockchip RK356[68]
> > > SoCs.  Graphics support is based around the VOP2 controller which
> > > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > > has been tested with HDMI support included in this series and MIPI-DSI
> > > which is not included because it needs some more work. The driver is
> > > taken from the downstream Rockchip kernel
> > 
> > Yes, you do know this is from Rockchip kernel.
> > 
> > Could you point me out where is the information about original author  
> > in your commit?
> 
> The copyrights for added files seem to have stayed intact.
> For example the added rockchip_drm_vop2.c file in patch12
> does contain the copyright as
> 
> 	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
> 	Author: Andy Yan <andy.yan@rock-chips.com>
> 
> 
> We can of course debate if the commit-author should also be set to
> Andy or another Rockchip engineer, with Sascha adding a 
> "Co-developed-by" with his credentials.
> 
> That's probably a nice compromise, I guess.

The commit author was merely lost while copying the driver file into my git.
Changing it back to Andy is fine with me, I didn't mean to steal anyones
credits.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:03       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-18 10:03 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: dri-devel, Kever Yang, linux-arm-kernel, linux-rockchip,
	devicetree, kernel, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis, 闫孝军

On Thu, Nov 18, 2021 at 10:26:29AM +0100, Heiko Stübner wrote:
> Hi Kever,
> 
> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
> > Hi Sascha Hauer,
> > 
> > On 2021/11/17 下午10:33, Sascha Hauer wrote:
> > > This series adds initial graphics support for the Rockchip RK356[68]
> > > SoCs.  Graphics support is based around the VOP2 controller which
> > > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > > has been tested with HDMI support included in this series and MIPI-DSI
> > > which is not included because it needs some more work. The driver is
> > > taken from the downstream Rockchip kernel
> > 
> > Yes, you do know this is from Rockchip kernel.
> > 
> > Could you point me out where is the information about original author  
> > in your commit?
> 
> The copyrights for added files seem to have stayed intact.
> For example the added rockchip_drm_vop2.c file in patch12
> does contain the copyright as
> 
> 	Copyright (c) 2020 Rockchip Electronics Co., Ltd.
> 	Author: Andy Yan <andy.yan@rock-chips.com>
> 
> 
> We can of course debate if the commit-author should also be set to
> Andy or another Rockchip engineer, with Sascha adding a 
> "Co-developed-by" with his credentials.
> 
> That's probably a nice compromise, I guess.

The commit author was merely lost while copying the driver file into my git.
Changing it back to Andy is fine with me, I didn't mean to steal anyones
credits.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18  9:53       ` Daniel Stone
  (?)
  (?)
@ 2021-11-18 10:50         ` Kever Yang
  -1 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18 10:50 UTC (permalink / raw)
  To: Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	闫孝军,
	linux-arm-kernel


On 2021/11/18 下午5:53, Daniel Stone wrote:
> Hi,
>
> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>> I don't agree with this, we do believe you have do some clean up to meet
>>> the requirement
>>>
>>> of upstream, but all the framework and feature implement are from
>>> Rockchip engineer,
>>>
>>> we have made a great effort to make everything work which block us to
>>> upstream this driver for now.
>> I don't fully understand what you mean here (language barrier probably),
>> but dropping non-essential functionality in a first round is pretty common
>> to at least get basic functionality working for everyone. With the special
>> features getting added again in later patches over time. This happenened
>> on the old vop as well.
>>
>> And of course, having a kernel that can "just" do normal graphics without
>> the additional features is still preferable over having _NO_ graphics support
>> at all ;-)
>>
>>> NAK for this series.
>> As you might've seen from previous graphics related patches, there
>> is a big number of people _and companies_ that seems to want/need
>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>
>> --> Most likely even in real products!
> Yes, we've been trying to ship a real product based on RK356x. We
> started by using the vendor VOP2 driver, but it is broken beyond
> belief. The driver needs a fundamental ground-up rework, and all the
> additional features get in the way of doing this core rework to make
> it actually function correctly.
>
> So, NAK to the NAK. I would like to see the VOP2 support start simple,
> with more features being added one by one.
>
>> While Rockchip did say that they want to upstream VOP2 support, there
>> has been _NO_ movement or even information at all on this over at least
>> the last year(!), so it's pretty understandable that developers will do this
>> themself at some point, because they don't want to wait anymore for
>> something that might never happen.
>>
>> So a simple "NAK" without additional information is not really helpful here.
>>
>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>> plans on upstreaming at least basic graphis support themself.
>>
>> The kernel is often called a do-ocracy - the one who does the work, gets
>> to decide. So if you really don't like Sascha's series at all, I do expect
>> Rockchip to step up and provide a solution themself - and in a usable
>> timeframe.
> Exactly what Heiko said. If you would like to upstream the driver then
> that would be fantastic to see, but I'm afraid you do not get to
> prevent someone else from doing the work themselves.

First of all, we never stop any one to doing there work on upstream if 
the source code is write totally by themselves.

Second, there are also many modules are upstream by developers based on 
Rockchip source code, please note that
all of them have basic respect to our work, they do communicate with us 
first.


But this committer do not take any respect to our engineers and their 
hard working:
- He didn't contact with us;
- There isn't  any information about original author in the commit message;
     As I have known, if I use source code from another developer, I 
need to at least add a "Signed-off-by" with original author;
- This commit and mail does not even have a 'CC' to original author.

I NAK because I  think this is not part of the  open source spirit, and 
this kind of  behavior should not be encouraged.


Thanks,
- Kever



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:50         ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18 10:50 UTC (permalink / raw)
  To: Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	闫孝军,
	linux-arm-kernel


On 2021/11/18 下午5:53, Daniel Stone wrote:
> Hi,
>
> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>> I don't agree with this, we do believe you have do some clean up to meet
>>> the requirement
>>>
>>> of upstream, but all the framework and feature implement are from
>>> Rockchip engineer,
>>>
>>> we have made a great effort to make everything work which block us to
>>> upstream this driver for now.
>> I don't fully understand what you mean here (language barrier probably),
>> but dropping non-essential functionality in a first round is pretty common
>> to at least get basic functionality working for everyone. With the special
>> features getting added again in later patches over time. This happenened
>> on the old vop as well.
>>
>> And of course, having a kernel that can "just" do normal graphics without
>> the additional features is still preferable over having _NO_ graphics support
>> at all ;-)
>>
>>> NAK for this series.
>> As you might've seen from previous graphics related patches, there
>> is a big number of people _and companies_ that seems to want/need
>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>
>> --> Most likely even in real products!
> Yes, we've been trying to ship a real product based on RK356x. We
> started by using the vendor VOP2 driver, but it is broken beyond
> belief. The driver needs a fundamental ground-up rework, and all the
> additional features get in the way of doing this core rework to make
> it actually function correctly.
>
> So, NAK to the NAK. I would like to see the VOP2 support start simple,
> with more features being added one by one.
>
>> While Rockchip did say that they want to upstream VOP2 support, there
>> has been _NO_ movement or even information at all on this over at least
>> the last year(!), so it's pretty understandable that developers will do this
>> themself at some point, because they don't want to wait anymore for
>> something that might never happen.
>>
>> So a simple "NAK" without additional information is not really helpful here.
>>
>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>> plans on upstreaming at least basic graphis support themself.
>>
>> The kernel is often called a do-ocracy - the one who does the work, gets
>> to decide. So if you really don't like Sascha's series at all, I do expect
>> Rockchip to step up and provide a solution themself - and in a usable
>> timeframe.
> Exactly what Heiko said. If you would like to upstream the driver then
> that would be fantastic to see, but I'm afraid you do not get to
> prevent someone else from doing the work themselves.

First of all, we never stop any one to doing there work on upstream if 
the source code is write totally by themselves.

Second, there are also many modules are upstream by developers based on 
Rockchip source code, please note that
all of them have basic respect to our work, they do communicate with us 
first.


But this committer do not take any respect to our engineers and their 
hard working:
- He didn't contact with us;
- There isn't  any information about original author in the commit message;
     As I have known, if I use source code from another developer, I 
need to at least add a "Signed-off-by" with original author;
- This commit and mail does not even have a 'CC' to original author.

I NAK because I  think this is not part of the  open source spirit, and 
this kind of  behavior should not be encouraged.


Thanks,
- Kever



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:50         ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18 10:50 UTC (permalink / raw)
  To: Daniel Stone, Heiko Stübner
  Cc: devicetree, Benjamin Gaignard, kernel, Sascha Hauer, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, Peter Geis,
	闫孝军,
	linux-arm-kernel


On 2021/11/18 下午5:53, Daniel Stone wrote:
> Hi,
>
> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>> I don't agree with this, we do believe you have do some clean up to meet
>>> the requirement
>>>
>>> of upstream, but all the framework and feature implement are from
>>> Rockchip engineer,
>>>
>>> we have made a great effort to make everything work which block us to
>>> upstream this driver for now.
>> I don't fully understand what you mean here (language barrier probably),
>> but dropping non-essential functionality in a first round is pretty common
>> to at least get basic functionality working for everyone. With the special
>> features getting added again in later patches over time. This happenened
>> on the old vop as well.
>>
>> And of course, having a kernel that can "just" do normal graphics without
>> the additional features is still preferable over having _NO_ graphics support
>> at all ;-)
>>
>>> NAK for this series.
>> As you might've seen from previous graphics related patches, there
>> is a big number of people _and companies_ that seems to want/need
>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>
>> --> Most likely even in real products!
> Yes, we've been trying to ship a real product based on RK356x. We
> started by using the vendor VOP2 driver, but it is broken beyond
> belief. The driver needs a fundamental ground-up rework, and all the
> additional features get in the way of doing this core rework to make
> it actually function correctly.
>
> So, NAK to the NAK. I would like to see the VOP2 support start simple,
> with more features being added one by one.
>
>> While Rockchip did say that they want to upstream VOP2 support, there
>> has been _NO_ movement or even information at all on this over at least
>> the last year(!), so it's pretty understandable that developers will do this
>> themself at some point, because they don't want to wait anymore for
>> something that might never happen.
>>
>> So a simple "NAK" without additional information is not really helpful here.
>>
>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>> plans on upstreaming at least basic graphis support themself.
>>
>> The kernel is often called a do-ocracy - the one who does the work, gets
>> to decide. So if you really don't like Sascha's series at all, I do expect
>> Rockchip to step up and provide a solution themself - and in a usable
>> timeframe.
> Exactly what Heiko said. If you would like to upstream the driver then
> that would be fantastic to see, but I'm afraid you do not get to
> prevent someone else from doing the work themselves.

First of all, we never stop any one to doing there work on upstream if 
the source code is write totally by themselves.

Second, there are also many modules are upstream by developers based on 
Rockchip source code, please note that
all of them have basic respect to our work, they do communicate with us 
first.


But this committer do not take any respect to our engineers and their 
hard working:
- He didn't contact with us;
- There isn't  any information about original author in the commit message;
     As I have known, if I use source code from another developer, I 
need to at least add a "Signed-off-by" with original author;
- This commit and mail does not even have a 'CC' to original author.

I NAK because I  think this is not part of the  open source spirit, and 
this kind of  behavior should not be encouraged.


Thanks,
- Kever



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 10:50         ` Kever Yang
  0 siblings, 0 replies; 201+ messages in thread
From: Kever Yang @ 2021-11-18 10:50 UTC (permalink / raw)
  To: Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	闫孝军,
	linux-arm-kernel


On 2021/11/18 下午5:53, Daniel Stone wrote:
> Hi,
>
> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>> I don't agree with this, we do believe you have do some clean up to meet
>>> the requirement
>>>
>>> of upstream, but all the framework and feature implement are from
>>> Rockchip engineer,
>>>
>>> we have made a great effort to make everything work which block us to
>>> upstream this driver for now.
>> I don't fully understand what you mean here (language barrier probably),
>> but dropping non-essential functionality in a first round is pretty common
>> to at least get basic functionality working for everyone. With the special
>> features getting added again in later patches over time. This happenened
>> on the old vop as well.
>>
>> And of course, having a kernel that can "just" do normal graphics without
>> the additional features is still preferable over having _NO_ graphics support
>> at all ;-)
>>
>>> NAK for this series.
>> As you might've seen from previous graphics related patches, there
>> is a big number of people _and companies_ that seems to want/need
>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>
>> --> Most likely even in real products!
> Yes, we've been trying to ship a real product based on RK356x. We
> started by using the vendor VOP2 driver, but it is broken beyond
> belief. The driver needs a fundamental ground-up rework, and all the
> additional features get in the way of doing this core rework to make
> it actually function correctly.
>
> So, NAK to the NAK. I would like to see the VOP2 support start simple,
> with more features being added one by one.
>
>> While Rockchip did say that they want to upstream VOP2 support, there
>> has been _NO_ movement or even information at all on this over at least
>> the last year(!), so it's pretty understandable that developers will do this
>> themself at some point, because they don't want to wait anymore for
>> something that might never happen.
>>
>> So a simple "NAK" without additional information is not really helpful here.
>>
>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>> plans on upstreaming at least basic graphis support themself.
>>
>> The kernel is often called a do-ocracy - the one who does the work, gets
>> to decide. So if you really don't like Sascha's series at all, I do expect
>> Rockchip to step up and provide a solution themself - and in a usable
>> timeframe.
> Exactly what Heiko said. If you would like to upstream the driver then
> that would be fantastic to see, but I'm afraid you do not get to
> prevent someone else from doing the work themselves.

First of all, we never stop any one to doing there work on upstream if 
the source code is write totally by themselves.

Second, there are also many modules are upstream by developers based on 
Rockchip source code, please note that
all of them have basic respect to our work, they do communicate with us 
first.


But this committer do not take any respect to our engineers and their 
hard working:
- He didn't contact with us;
- There isn't  any information about original author in the commit message;
     As I have known, if I use source code from another developer, I 
need to at least add a "Signed-off-by" with original author;
- This commit and mail does not even have a 'CC' to original author.

I NAK because I  think this is not part of the  open source spirit, and 
this kind of  behavior should not be encouraged.


Thanks,
- Kever



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18 10:50         ` Kever Yang
  (?)
  (?)
@ 2021-11-18 11:08           ` Michael Riesch
  -1 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-18 11:08 UTC (permalink / raw)
  To: Kever Yang, Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, kernel,
	闫孝军,
	linux-arm-kernel

Hello Kever,

On 11/18/21 11:50 AM, Kever Yang wrote:
> 
> On 2021/11/18 下午5:53, Daniel Stone wrote:
>> Hi,
>>
>> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>>> I don't agree with this, we do believe you have do some clean up to 
>>>> meet
>>>> the requirement
>>>>
>>>> of upstream, but all the framework and feature implement are from
>>>> Rockchip engineer,
>>>>
>>>> we have made a great effort to make everything work which block us to
>>>> upstream this driver for now.
>>> I don't fully understand what you mean here (language barrier probably),
>>> but dropping non-essential functionality in a first round is pretty 
>>> common
>>> to at least get basic functionality working for everyone. With the 
>>> special
>>> features getting added again in later patches over time. This happenened
>>> on the old vop as well.
>>>
>>> And of course, having a kernel that can "just" do normal graphics 
>>> without
>>> the additional features is still preferable over having _NO_ graphics 
>>> support
>>> at all ;-)
>>>
>>>> NAK for this series.
>>> As you might've seen from previous graphics related patches, there
>>> is a big number of people _and companies_ that seems to want/need
>>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>>
>>> --> Most likely even in real products!
>> Yes, we've been trying to ship a real product based on RK356x. We
>> started by using the vendor VOP2 driver, but it is broken beyond
>> belief. The driver needs a fundamental ground-up rework, and all the
>> additional features get in the way of doing this core rework to make
>> it actually function correctly.
>>
>> So, NAK to the NAK. I would like to see the VOP2 support start simple,
>> with more features being added one by one.
>>
>>> While Rockchip did say that they want to upstream VOP2 support, there
>>> has been _NO_ movement or even information at all on this over at least
>>> the last year(!), so it's pretty understandable that developers will 
>>> do this
>>> themself at some point, because they don't want to wait anymore for
>>> something that might never happen.
>>>
>>> So a simple "NAK" without additional information is not really 
>>> helpful here.
>>>
>>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>>> plans on upstreaming at least basic graphis support themself.
>>>
>>> The kernel is often called a do-ocracy - the one who does the work, gets
>>> to decide. So if you really don't like Sascha's series at all, I do 
>>> expect
>>> Rockchip to step up and provide a solution themself - and in a usable
>>> timeframe.
>> Exactly what Heiko said. If you would like to upstream the driver then
>> that would be fantastic to see, but I'm afraid you do not get to
>> prevent someone else from doing the work themselves.
> 
> First of all, we never stop any one to doing there work on upstream if 
> the source code is write totally by themselves.
> 
> Second, there are also many modules are upstream by developers based on 
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us 
> first.
> 
> 
> But this committer do not take any respect to our engineers and their 
> hard working:
> - He didn't contact with us;

I approached Andy Yan and you off-list on October 20, 2021 in this 
regard, as Andy mentioned on linux-rockchip in July 2021 some plans to 
bring the driver mainline. Since there was no response, we asked Sascha 
to make this happen.

> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I 
> need to at least add a "Signed-off-by" with original author;

As has been discussed before, this will be fixed in v2. Simple mistake, 
no harm intended.

> - This commit and mail does not even have a 'CC' to original author.
> 
> I NAK because I  think this is not part of the  open source spirit, and 
> this kind of  behavior should not be encouraged.

It is great to hear that you care about the open source spirit. IMHO 
communication is a big part thereof. If Rockchip would communicate 
better their plans to bring things mainline including a time schedule, 
it would be a lot easier for all of us.

Best regards,
Michael

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 11:08           ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-18 11:08 UTC (permalink / raw)
  To: Kever Yang, Daniel Stone, Heiko Stübner
  Cc: devicetree, Benjamin Gaignard, kernel, Sascha Hauer, Sandy Huang,
	dri-devel, linux-rockchip, Peter Geis, 闫孝军,
	linux-arm-kernel

Hello Kever,

On 11/18/21 11:50 AM, Kever Yang wrote:
> 
> On 2021/11/18 下午5:53, Daniel Stone wrote:
>> Hi,
>>
>> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>>> I don't agree with this, we do believe you have do some clean up to 
>>>> meet
>>>> the requirement
>>>>
>>>> of upstream, but all the framework and feature implement are from
>>>> Rockchip engineer,
>>>>
>>>> we have made a great effort to make everything work which block us to
>>>> upstream this driver for now.
>>> I don't fully understand what you mean here (language barrier probably),
>>> but dropping non-essential functionality in a first round is pretty 
>>> common
>>> to at least get basic functionality working for everyone. With the 
>>> special
>>> features getting added again in later patches over time. This happenened
>>> on the old vop as well.
>>>
>>> And of course, having a kernel that can "just" do normal graphics 
>>> without
>>> the additional features is still preferable over having _NO_ graphics 
>>> support
>>> at all ;-)
>>>
>>>> NAK for this series.
>>> As you might've seen from previous graphics related patches, there
>>> is a big number of people _and companies_ that seems to want/need
>>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>>
>>> --> Most likely even in real products!
>> Yes, we've been trying to ship a real product based on RK356x. We
>> started by using the vendor VOP2 driver, but it is broken beyond
>> belief. The driver needs a fundamental ground-up rework, and all the
>> additional features get in the way of doing this core rework to make
>> it actually function correctly.
>>
>> So, NAK to the NAK. I would like to see the VOP2 support start simple,
>> with more features being added one by one.
>>
>>> While Rockchip did say that they want to upstream VOP2 support, there
>>> has been _NO_ movement or even information at all on this over at least
>>> the last year(!), so it's pretty understandable that developers will 
>>> do this
>>> themself at some point, because they don't want to wait anymore for
>>> something that might never happen.
>>>
>>> So a simple "NAK" without additional information is not really 
>>> helpful here.
>>>
>>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>>> plans on upstreaming at least basic graphis support themself.
>>>
>>> The kernel is often called a do-ocracy - the one who does the work, gets
>>> to decide. So if you really don't like Sascha's series at all, I do 
>>> expect
>>> Rockchip to step up and provide a solution themself - and in a usable
>>> timeframe.
>> Exactly what Heiko said. If you would like to upstream the driver then
>> that would be fantastic to see, but I'm afraid you do not get to
>> prevent someone else from doing the work themselves.
> 
> First of all, we never stop any one to doing there work on upstream if 
> the source code is write totally by themselves.
> 
> Second, there are also many modules are upstream by developers based on 
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us 
> first.
> 
> 
> But this committer do not take any respect to our engineers and their 
> hard working:
> - He didn't contact with us;

I approached Andy Yan and you off-list on October 20, 2021 in this 
regard, as Andy mentioned on linux-rockchip in July 2021 some plans to 
bring the driver mainline. Since there was no response, we asked Sascha 
to make this happen.

> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I 
> need to at least add a "Signed-off-by" with original author;

As has been discussed before, this will be fixed in v2. Simple mistake, 
no harm intended.

> - This commit and mail does not even have a 'CC' to original author.
> 
> I NAK because I  think this is not part of the  open source spirit, and 
> this kind of  behavior should not be encouraged.

It is great to hear that you care about the open source spirit. IMHO 
communication is a big part thereof. If Rockchip would communicate 
better their plans to bring things mainline including a time schedule, 
it would be a lot easier for all of us.

Best regards,
Michael

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 11:08           ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-18 11:08 UTC (permalink / raw)
  To: Kever Yang, Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, kernel,
	闫孝军,
	linux-arm-kernel

Hello Kever,

On 11/18/21 11:50 AM, Kever Yang wrote:
> 
> On 2021/11/18 下午5:53, Daniel Stone wrote:
>> Hi,
>>
>> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>>> I don't agree with this, we do believe you have do some clean up to 
>>>> meet
>>>> the requirement
>>>>
>>>> of upstream, but all the framework and feature implement are from
>>>> Rockchip engineer,
>>>>
>>>> we have made a great effort to make everything work which block us to
>>>> upstream this driver for now.
>>> I don't fully understand what you mean here (language barrier probably),
>>> but dropping non-essential functionality in a first round is pretty 
>>> common
>>> to at least get basic functionality working for everyone. With the 
>>> special
>>> features getting added again in later patches over time. This happenened
>>> on the old vop as well.
>>>
>>> And of course, having a kernel that can "just" do normal graphics 
>>> without
>>> the additional features is still preferable over having _NO_ graphics 
>>> support
>>> at all ;-)
>>>
>>>> NAK for this series.
>>> As you might've seen from previous graphics related patches, there
>>> is a big number of people _and companies_ that seems to want/need
>>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>>
>>> --> Most likely even in real products!
>> Yes, we've been trying to ship a real product based on RK356x. We
>> started by using the vendor VOP2 driver, but it is broken beyond
>> belief. The driver needs a fundamental ground-up rework, and all the
>> additional features get in the way of doing this core rework to make
>> it actually function correctly.
>>
>> So, NAK to the NAK. I would like to see the VOP2 support start simple,
>> with more features being added one by one.
>>
>>> While Rockchip did say that they want to upstream VOP2 support, there
>>> has been _NO_ movement or even information at all on this over at least
>>> the last year(!), so it's pretty understandable that developers will 
>>> do this
>>> themself at some point, because they don't want to wait anymore for
>>> something that might never happen.
>>>
>>> So a simple "NAK" without additional information is not really 
>>> helpful here.
>>>
>>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>>> plans on upstreaming at least basic graphis support themself.
>>>
>>> The kernel is often called a do-ocracy - the one who does the work, gets
>>> to decide. So if you really don't like Sascha's series at all, I do 
>>> expect
>>> Rockchip to step up and provide a solution themself - and in a usable
>>> timeframe.
>> Exactly what Heiko said. If you would like to upstream the driver then
>> that would be fantastic to see, but I'm afraid you do not get to
>> prevent someone else from doing the work themselves.
> 
> First of all, we never stop any one to doing there work on upstream if 
> the source code is write totally by themselves.
> 
> Second, there are also many modules are upstream by developers based on 
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us 
> first.
> 
> 
> But this committer do not take any respect to our engineers and their 
> hard working:
> - He didn't contact with us;

I approached Andy Yan and you off-list on October 20, 2021 in this 
regard, as Andy mentioned on linux-rockchip in July 2021 some plans to 
bring the driver mainline. Since there was no response, we asked Sascha 
to make this happen.

> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I 
> need to at least add a "Signed-off-by" with original author;

As has been discussed before, this will be fixed in v2. Simple mistake, 
no harm intended.

> - This commit and mail does not even have a 'CC' to original author.
> 
> I NAK because I  think this is not part of the  open source spirit, and 
> this kind of  behavior should not be encouraged.

It is great to hear that you care about the open source spirit. IMHO 
communication is a big part thereof. If Rockchip would communicate 
better their plans to bring things mainline including a time schedule, 
it would be a lot easier for all of us.

Best regards,
Michael

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 11:08           ` Michael Riesch
  0 siblings, 0 replies; 201+ messages in thread
From: Michael Riesch @ 2021-11-18 11:08 UTC (permalink / raw)
  To: Kever Yang, Daniel Stone, Heiko Stübner
  Cc: Sascha Hauer, dri-devel, devicetree, Benjamin Gaignard,
	Peter Geis, Sandy Huang, linux-rockchip, kernel,
	闫孝军,
	linux-arm-kernel

Hello Kever,

On 11/18/21 11:50 AM, Kever Yang wrote:
> 
> On 2021/11/18 下午5:53, Daniel Stone wrote:
>> Hi,
>>
>> On Thu, 18 Nov 2021 at 09:26, Heiko Stübner <heiko@sntech.de> wrote:
>>> Am Donnerstag, 18. November 2021, 02:27:10 CET schrieb Kever Yang:
>>>> I don't agree with this, we do believe you have do some clean up to 
>>>> meet
>>>> the requirement
>>>>
>>>> of upstream, but all the framework and feature implement are from
>>>> Rockchip engineer,
>>>>
>>>> we have made a great effort to make everything work which block us to
>>>> upstream this driver for now.
>>> I don't fully understand what you mean here (language barrier probably),
>>> but dropping non-essential functionality in a first round is pretty 
>>> common
>>> to at least get basic functionality working for everyone. With the 
>>> special
>>> features getting added again in later patches over time. This happenened
>>> on the old vop as well.
>>>
>>> And of course, having a kernel that can "just" do normal graphics 
>>> without
>>> the additional features is still preferable over having _NO_ graphics 
>>> support
>>> at all ;-)
>>>
>>>> NAK for this series.
>>> As you might've seen from previous graphics related patches, there
>>> is a big number of people _and companies_ that seems to want/need
>>> to work with the rk3566/rk3568 with a kernel based on mainline.
>>>
>>> --> Most likely even in real products!
>> Yes, we've been trying to ship a real product based on RK356x. We
>> started by using the vendor VOP2 driver, but it is broken beyond
>> belief. The driver needs a fundamental ground-up rework, and all the
>> additional features get in the way of doing this core rework to make
>> it actually function correctly.
>>
>> So, NAK to the NAK. I would like to see the VOP2 support start simple,
>> with more features being added one by one.
>>
>>> While Rockchip did say that they want to upstream VOP2 support, there
>>> has been _NO_ movement or even information at all on this over at least
>>> the last year(!), so it's pretty understandable that developers will 
>>> do this
>>> themself at some point, because they don't want to wait anymore for
>>> something that might never happen.
>>>
>>> So a simple "NAK" without additional information is not really 
>>> helpful here.
>>>
>>> If you don't like Sascha's series, I really want to know _WHEN_ Rockchip
>>> plans on upstreaming at least basic graphis support themself.
>>>
>>> The kernel is often called a do-ocracy - the one who does the work, gets
>>> to decide. So if you really don't like Sascha's series at all, I do 
>>> expect
>>> Rockchip to step up and provide a solution themself - and in a usable
>>> timeframe.
>> Exactly what Heiko said. If you would like to upstream the driver then
>> that would be fantastic to see, but I'm afraid you do not get to
>> prevent someone else from doing the work themselves.
> 
> First of all, we never stop any one to doing there work on upstream if 
> the source code is write totally by themselves.
> 
> Second, there are also many modules are upstream by developers based on 
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us 
> first.
> 
> 
> But this committer do not take any respect to our engineers and their 
> hard working:
> - He didn't contact with us;

I approached Andy Yan and you off-list on October 20, 2021 in this 
regard, as Andy mentioned on linux-rockchip in July 2021 some plans to 
bring the driver mainline. Since there was no response, we asked Sascha 
to make this happen.

> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I 
> need to at least add a "Signed-off-by" with original author;

As has been discussed before, this will be fixed in v2. Simple mistake, 
no harm intended.

> - This commit and mail does not even have a 'CC' to original author.
> 
> I NAK because I  think this is not part of the  open source spirit, and 
> this kind of  behavior should not be encouraged.

It is great to hear that you care about the open source spirit. IMHO 
communication is a big part thereof. If Rockchip would communicate 
better their plans to bring things mainline including a time schedule, 
it would be a lot easier for all of us.

Best regards,
Michael

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18 10:50         ` Kever Yang
  (?)
  (?)
@ 2021-11-18 12:07           ` Daniel Stone
  -1 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 12:07 UTC (permalink / raw)
  To: Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi Kever,

On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
> On 2021/11/18 下午5:53, Daniel Stone wrote:
> > Exactly what Heiko said. If you would like to upstream the driver then
> > that would be fantastic to see, but I'm afraid you do not get to
> > prevent someone else from doing the work themselves.
>
> First of all, we never stop any one to doing there work on upstream if
> the source code is write totally by themselves.
>
> Second, there are also many modules are upstream by developers based on
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us
> first.
>
> But this committer do not take any respect to our engineers and their
> hard working:
> - He didn't contact with us;
> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I
> need to at least add a "Signed-off-by" with original author;
> - This commit and mail does not even have a 'CC' to original author.
>
> I NAK because I  think this is not part of the  open source spirit, and
> this kind of  behavior should not be encouraged.

OK, I see where you're coming from, and I agree that the attribution
should have been handled more carefully.

On the other hand, please consider this from the other perspective.
Sascha has been free to take the downstream Rockchip BSP code and
attempt to upstream it to the Linux kernel, which you are unhappy
about. But then the Rockchip driver was developed totally downstream,
with no attempt to ever communicate with the upstream Linux or DRM/KMS
developers. Rockchip advertises that it is shipped as a Linux kernel
with a KMS driver. But we were never informed, or CCed, or anything.

If you would like the community to more actively work with you - then
please yourself work more actively with the community. The first
commit of the VOP2 driver was in July 2020, and that was of the full
driver so presumably it started quite some time before then. So that
is a minimum of 17 months that you have had to engage with upstream
...

Technically, the driver cannot be upstreamed as-is. It looks as if it
were a pre-atomic driver, that was half-converted to atomic, and then
has been half-converted to atomic helpers as well. Things like
reference counting and global state are not handled correctly at all.
You can see this if you try to run Weston on top of the VOP2 driver:
the framerate is decimated because the event handling massively
over-synchronises, and the event timestamps which arrive are
incorrect. This would be fixed by correctly using the event helpers
that we have had in the tree for years (which would also eliminate the
unnecessary framebuffer reference handling). It also does not work
with the GPU drivers in the tree because it lacks the one-liner to
correctly handle dma_resv synchronisation, which makes it both too
fast as it displays content which is not ready, and too slow because
it can't do it at full frame rate.

Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
also active, but when HDMI is active at the same time as DSI, it just
shows a blank screen. I believe the root cause of this is that the
VOP2 driver does not use any of the atomic state correctly, and
instead stores its own state in driver-global structures, using a lot
of unnecessary mutexes to try to synchronise this state. Not only does
this synchronisation not actually work, but it causes a severe
performance degradation due to mutex contention.

I believe the best path forward to an upstream VOP2 driver is a patch
series consisting of:
  - start from a blank slate, using the atomic framework and helpers
as they were intended to be, with basic support for the VOP2 and one
or two connector types, doing linear XRGB only
  - any cleanups which would enable this to share more code with
  - add YUV support, including planar buffers
  - add AFBC support, with the AFBC enable/disable correctly
synchronised through atomic state (this is necessary since the AFBC
decoder is not directly on the planes per se but shared)
  - add more connector types
  - add writeback support
  - add other Rockchip-specific codepaths such as HDR10

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 12:07           ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 12:07 UTC (permalink / raw)
  To: Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi Kever,

On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
> On 2021/11/18 下午5:53, Daniel Stone wrote:
> > Exactly what Heiko said. If you would like to upstream the driver then
> > that would be fantastic to see, but I'm afraid you do not get to
> > prevent someone else from doing the work themselves.
>
> First of all, we never stop any one to doing there work on upstream if
> the source code is write totally by themselves.
>
> Second, there are also many modules are upstream by developers based on
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us
> first.
>
> But this committer do not take any respect to our engineers and their
> hard working:
> - He didn't contact with us;
> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I
> need to at least add a "Signed-off-by" with original author;
> - This commit and mail does not even have a 'CC' to original author.
>
> I NAK because I  think this is not part of the  open source spirit, and
> this kind of  behavior should not be encouraged.

OK, I see where you're coming from, and I agree that the attribution
should have been handled more carefully.

On the other hand, please consider this from the other perspective.
Sascha has been free to take the downstream Rockchip BSP code and
attempt to upstream it to the Linux kernel, which you are unhappy
about. But then the Rockchip driver was developed totally downstream,
with no attempt to ever communicate with the upstream Linux or DRM/KMS
developers. Rockchip advertises that it is shipped as a Linux kernel
with a KMS driver. But we were never informed, or CCed, or anything.

If you would like the community to more actively work with you - then
please yourself work more actively with the community. The first
commit of the VOP2 driver was in July 2020, and that was of the full
driver so presumably it started quite some time before then. So that
is a minimum of 17 months that you have had to engage with upstream
...

Technically, the driver cannot be upstreamed as-is. It looks as if it
were a pre-atomic driver, that was half-converted to atomic, and then
has been half-converted to atomic helpers as well. Things like
reference counting and global state are not handled correctly at all.
You can see this if you try to run Weston on top of the VOP2 driver:
the framerate is decimated because the event handling massively
over-synchronises, and the event timestamps which arrive are
incorrect. This would be fixed by correctly using the event helpers
that we have had in the tree for years (which would also eliminate the
unnecessary framebuffer reference handling). It also does not work
with the GPU drivers in the tree because it lacks the one-liner to
correctly handle dma_resv synchronisation, which makes it both too
fast as it displays content which is not ready, and too slow because
it can't do it at full frame rate.

Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
also active, but when HDMI is active at the same time as DSI, it just
shows a blank screen. I believe the root cause of this is that the
VOP2 driver does not use any of the atomic state correctly, and
instead stores its own state in driver-global structures, using a lot
of unnecessary mutexes to try to synchronise this state. Not only does
this synchronisation not actually work, but it causes a severe
performance degradation due to mutex contention.

I believe the best path forward to an upstream VOP2 driver is a patch
series consisting of:
  - start from a blank slate, using the atomic framework and helpers
as they were intended to be, with basic support for the VOP2 and one
or two connector types, doing linear XRGB only
  - any cleanups which would enable this to share more code with
  - add YUV support, including planar buffers
  - add AFBC support, with the AFBC enable/disable correctly
synchronised through atomic state (this is necessary since the AFBC
decoder is not directly on the planes per se but shared)
  - add more connector types
  - add writeback support
  - add other Rockchip-specific codepaths such as HDR10

Cheers,
Daniel

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 12:07           ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 12:07 UTC (permalink / raw)
  To: Kever Yang
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, Peter Geis,
	闫孝军,
	kernel, linux-arm-kernel

Hi Kever,

On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
> On 2021/11/18 下午5:53, Daniel Stone wrote:
> > Exactly what Heiko said. If you would like to upstream the driver then
> > that would be fantastic to see, but I'm afraid you do not get to
> > prevent someone else from doing the work themselves.
>
> First of all, we never stop any one to doing there work on upstream if
> the source code is write totally by themselves.
>
> Second, there are also many modules are upstream by developers based on
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us
> first.
>
> But this committer do not take any respect to our engineers and their
> hard working:
> - He didn't contact with us;
> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I
> need to at least add a "Signed-off-by" with original author;
> - This commit and mail does not even have a 'CC' to original author.
>
> I NAK because I  think this is not part of the  open source spirit, and
> this kind of  behavior should not be encouraged.

OK, I see where you're coming from, and I agree that the attribution
should have been handled more carefully.

On the other hand, please consider this from the other perspective.
Sascha has been free to take the downstream Rockchip BSP code and
attempt to upstream it to the Linux kernel, which you are unhappy
about. But then the Rockchip driver was developed totally downstream,
with no attempt to ever communicate with the upstream Linux or DRM/KMS
developers. Rockchip advertises that it is shipped as a Linux kernel
with a KMS driver. But we were never informed, or CCed, or anything.

If you would like the community to more actively work with you - then
please yourself work more actively with the community. The first
commit of the VOP2 driver was in July 2020, and that was of the full
driver so presumably it started quite some time before then. So that
is a minimum of 17 months that you have had to engage with upstream
...

Technically, the driver cannot be upstreamed as-is. It looks as if it
were a pre-atomic driver, that was half-converted to atomic, and then
has been half-converted to atomic helpers as well. Things like
reference counting and global state are not handled correctly at all.
You can see this if you try to run Weston on top of the VOP2 driver:
the framerate is decimated because the event handling massively
over-synchronises, and the event timestamps which arrive are
incorrect. This would be fixed by correctly using the event helpers
that we have had in the tree for years (which would also eliminate the
unnecessary framebuffer reference handling). It also does not work
with the GPU drivers in the tree because it lacks the one-liner to
correctly handle dma_resv synchronisation, which makes it both too
fast as it displays content which is not ready, and too slow because
it can't do it at full frame rate.

Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
also active, but when HDMI is active at the same time as DSI, it just
shows a blank screen. I believe the root cause of this is that the
VOP2 driver does not use any of the atomic state correctly, and
instead stores its own state in driver-global structures, using a lot
of unnecessary mutexes to try to synchronise this state. Not only does
this synchronisation not actually work, but it causes a severe
performance degradation due to mutex contention.

I believe the best path forward to an upstream VOP2 driver is a patch
series consisting of:
  - start from a blank slate, using the atomic framework and helpers
as they were intended to be, with basic support for the VOP2 and one
or two connector types, doing linear XRGB only
  - any cleanups which would enable this to share more code with
  - add YUV support, including planar buffers
  - add AFBC support, with the AFBC enable/disable correctly
synchronised through atomic state (this is necessary since the AFBC
decoder is not directly on the planes per se but shared)
  - add more connector types
  - add writeback support
  - add other Rockchip-specific codepaths such as HDR10

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 12:07           ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 12:07 UTC (permalink / raw)
  To: Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, 闫孝军,
	linux-arm-kernel

Hi Kever,

On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
> On 2021/11/18 下午5:53, Daniel Stone wrote:
> > Exactly what Heiko said. If you would like to upstream the driver then
> > that would be fantastic to see, but I'm afraid you do not get to
> > prevent someone else from doing the work themselves.
>
> First of all, we never stop any one to doing there work on upstream if
> the source code is write totally by themselves.
>
> Second, there are also many modules are upstream by developers based on
> Rockchip source code, please note that
> all of them have basic respect to our work, they do communicate with us
> first.
>
> But this committer do not take any respect to our engineers and their
> hard working:
> - He didn't contact with us;
> - There isn't  any information about original author in the commit message;
>      As I have known, if I use source code from another developer, I
> need to at least add a "Signed-off-by" with original author;
> - This commit and mail does not even have a 'CC' to original author.
>
> I NAK because I  think this is not part of the  open source spirit, and
> this kind of  behavior should not be encouraged.

OK, I see where you're coming from, and I agree that the attribution
should have been handled more carefully.

On the other hand, please consider this from the other perspective.
Sascha has been free to take the downstream Rockchip BSP code and
attempt to upstream it to the Linux kernel, which you are unhappy
about. But then the Rockchip driver was developed totally downstream,
with no attempt to ever communicate with the upstream Linux or DRM/KMS
developers. Rockchip advertises that it is shipped as a Linux kernel
with a KMS driver. But we were never informed, or CCed, or anything.

If you would like the community to more actively work with you - then
please yourself work more actively with the community. The first
commit of the VOP2 driver was in July 2020, and that was of the full
driver so presumably it started quite some time before then. So that
is a minimum of 17 months that you have had to engage with upstream
...

Technically, the driver cannot be upstreamed as-is. It looks as if it
were a pre-atomic driver, that was half-converted to atomic, and then
has been half-converted to atomic helpers as well. Things like
reference counting and global state are not handled correctly at all.
You can see this if you try to run Weston on top of the VOP2 driver:
the framerate is decimated because the event handling massively
over-synchronises, and the event timestamps which arrive are
incorrect. This would be fixed by correctly using the event helpers
that we have had in the tree for years (which would also eliminate the
unnecessary framebuffer reference handling). It also does not work
with the GPU drivers in the tree because it lacks the one-liner to
correctly handle dma_resv synchronisation, which makes it both too
fast as it displays content which is not ready, and too slow because
it can't do it at full frame rate.

Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
also active, but when HDMI is active at the same time as DSI, it just
shows a blank screen. I believe the root cause of this is that the
VOP2 driver does not use any of the atomic state correctly, and
instead stores its own state in driver-global structures, using a lot
of unnecessary mutexes to try to synchronise this state. Not only does
this synchronisation not actually work, but it causes a severe
performance degradation due to mutex contention.

I believe the best path forward to an upstream VOP2 driver is a patch
series consisting of:
  - start from a blank slate, using the atomic framework and helpers
as they were intended to be, with basic support for the VOP2 and one
or two connector types, doing linear XRGB only
  - any cleanups which would enable this to share more code with
  - add YUV support, including planar buffers
  - add AFBC support, with the AFBC enable/disable correctly
synchronised through atomic state (this is necessary since the AFBC
decoder is not directly on the planes per se but shared)
  - add more connector types
  - add writeback support
  - add other Rockchip-specific codepaths such as HDR10

Cheers,
Daniel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18 12:07           ` Daniel Stone
  (?)
  (?)
@ 2021-11-18 13:14             ` Andy Yan
  -1 siblings, 0 replies; 201+ messages in thread
From: Andy Yan @ 2021-11-18 13:14 UTC (permalink / raw)
  To: Daniel Stone, Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, linux-arm-kernel

Hi Daniel:

On 11/18/21 8:07 PM, Daniel Stone wrote:
> Hi Kever,
>
> On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
>> On 2021/11/18 下午5:53, Daniel Stone wrote:
>>> Exactly what Heiko said. If you would like to upstream the driver then
>>> that would be fantastic to see, but I'm afraid you do not get to
>>> prevent someone else from doing the work themselves.
>> First of all, we never stop any one to doing there work on upstream if
>> the source code is write totally by themselves.
>>
>> Second, there are also many modules are upstream by developers based on
>> Rockchip source code, please note that
>> all of them have basic respect to our work, they do communicate with us
>> first.
>>
>> But this committer do not take any respect to our engineers and their
>> hard working:
>> - He didn't contact with us;
>> - There isn't  any information about original author in the commit message;
>>       As I have known, if I use source code from another developer, I
>> need to at least add a "Signed-off-by" with original author;
>> - This commit and mail does not even have a 'CC' to original author.
>>
>> I NAK because I  think this is not part of the  open source spirit, and
>> this kind of  behavior should not be encouraged.
> OK, I see where you're coming from, and I agree that the attribution
> should have been handled more carefully.
>
> On the other hand, please consider this from the other perspective.
> Sascha has been free to take the downstream Rockchip BSP code and
> attempt to upstream it to the Linux kernel, which you are unhappy
> about. But then the Rockchip driver was developed totally downstream,
> with no attempt to ever communicate with the upstream Linux or DRM/KMS
> developers. Rockchip advertises that it is shipped as a Linux kernel
> with a KMS driver. But we were never informed, or CCed, or anything.
>
> If you would like the community to more actively work with you - then
> please yourself work more actively with the community. The first
> commit of the VOP2 driver was in July 2020, and that was of the full
> driver so presumably it started quite some time before then. So that
> is a minimum of 17 months that you have had to engage with upstream
> ...
>
> Technically, the driver cannot be upstreamed as-is. It looks as if it
> were a pre-atomic driver, that was half-converted to atomic, and then
> has been half-converted to atomic helpers as well. Things like
> reference counting and global state are not handled correctly at all.
> You can see this if you try to run Weston on top of the VOP2 driver:
> the framerate is decimated because the event handling massively
> over-synchronises, and the event timestamps which arrive are
> incorrect. This would be fixed by correctly using the event helpers
> that we have had in the tree for years (which would also eliminate the
> unnecessary framebuffer reference handling). It also does not work
> with the GPU drivers in the tree because it lacks the one-liner to
> correctly handle dma_resv synchronisation, which makes it both too
> fast as it displays content which is not ready, and too slow because
> it can't do it at full frame rate.


We have different team run Android , X11, Weston on rk356x, especially 
for android, we can run at 60 fps.

Our vop2 driver is developed on Linux 4.19, am not sure which version of 
kernel you put our drivers on.

>
> Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> also active, but when HDMI is active at the same time as DSI, it just

I am very sure rk3566 evb DSI can work without HDMI.

But take care that the vop on rk3566 has a special limitation: there are 
three

windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they

can't be programed framebuffer address independently , they can only

share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature

on Android.

I have comment these limitation in our driver.

Compared to old vop, vop is strong but a bit complicated, we try very had to

make it work on as much display framework as possible.

We have upstream plane, but I am really in a rush this year. So sorry 
for the late of upstream, but we glad to work with community.

So Sascha, please feel free to go on with your work.

> shows a blank screen. I believe the root cause of this is that the
> VOP2 driver does not use any of the atomic state correctly, and
> instead stores its own state in driver-global structures, using a lot
> of unnecessary mutexes to try to synchronise this state. Not only does
> this synchronisation not actually work, but it causes a severe
> performance degradation due to mutex contention.
>
> I believe the best path forward to an upstream VOP2 driver is a patch
> series consisting of:
>    - start from a blank slate, using the atomic framework and helpers
> as they were intended to be, with basic support for the VOP2 and one
> or two connector types, doing linear XRGB only
>    - any cleanups which would enable this to share more code with
>    - add YUV support, including planar buffers
>    - add AFBC support, with the AFBC enable/disable correctly
> synchronised through atomic state (this is necessary since the AFBC
> decoder is not directly on the planes per se but shared)
>    - add more connector types
>    - add writeback support
>    - add other Rockchip-specific codepaths such as HDR10
>
> Cheers,
> Daniel
>
>
>



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:14             ` Andy Yan
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Yan @ 2021-11-18 13:14 UTC (permalink / raw)
  To: Daniel Stone, Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, linux-arm-kernel

Hi Daniel:

On 11/18/21 8:07 PM, Daniel Stone wrote:
> Hi Kever,
>
> On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
>> On 2021/11/18 下午5:53, Daniel Stone wrote:
>>> Exactly what Heiko said. If you would like to upstream the driver then
>>> that would be fantastic to see, but I'm afraid you do not get to
>>> prevent someone else from doing the work themselves.
>> First of all, we never stop any one to doing there work on upstream if
>> the source code is write totally by themselves.
>>
>> Second, there are also many modules are upstream by developers based on
>> Rockchip source code, please note that
>> all of them have basic respect to our work, they do communicate with us
>> first.
>>
>> But this committer do not take any respect to our engineers and their
>> hard working:
>> - He didn't contact with us;
>> - There isn't  any information about original author in the commit message;
>>       As I have known, if I use source code from another developer, I
>> need to at least add a "Signed-off-by" with original author;
>> - This commit and mail does not even have a 'CC' to original author.
>>
>> I NAK because I  think this is not part of the  open source spirit, and
>> this kind of  behavior should not be encouraged.
> OK, I see where you're coming from, and I agree that the attribution
> should have been handled more carefully.
>
> On the other hand, please consider this from the other perspective.
> Sascha has been free to take the downstream Rockchip BSP code and
> attempt to upstream it to the Linux kernel, which you are unhappy
> about. But then the Rockchip driver was developed totally downstream,
> with no attempt to ever communicate with the upstream Linux or DRM/KMS
> developers. Rockchip advertises that it is shipped as a Linux kernel
> with a KMS driver. But we were never informed, or CCed, or anything.
>
> If you would like the community to more actively work with you - then
> please yourself work more actively with the community. The first
> commit of the VOP2 driver was in July 2020, and that was of the full
> driver so presumably it started quite some time before then. So that
> is a minimum of 17 months that you have had to engage with upstream
> ...
>
> Technically, the driver cannot be upstreamed as-is. It looks as if it
> were a pre-atomic driver, that was half-converted to atomic, and then
> has been half-converted to atomic helpers as well. Things like
> reference counting and global state are not handled correctly at all.
> You can see this if you try to run Weston on top of the VOP2 driver:
> the framerate is decimated because the event handling massively
> over-synchronises, and the event timestamps which arrive are
> incorrect. This would be fixed by correctly using the event helpers
> that we have had in the tree for years (which would also eliminate the
> unnecessary framebuffer reference handling). It also does not work
> with the GPU drivers in the tree because it lacks the one-liner to
> correctly handle dma_resv synchronisation, which makes it both too
> fast as it displays content which is not ready, and too slow because
> it can't do it at full frame rate.


We have different team run Android , X11, Weston on rk356x, especially 
for android, we can run at 60 fps.

Our vop2 driver is developed on Linux 4.19, am not sure which version of 
kernel you put our drivers on.

>
> Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> also active, but when HDMI is active at the same time as DSI, it just

I am very sure rk3566 evb DSI can work without HDMI.

But take care that the vop on rk3566 has a special limitation: there are 
three

windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they

can't be programed framebuffer address independently , they can only

share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature

on Android.

I have comment these limitation in our driver.

Compared to old vop, vop is strong but a bit complicated, we try very had to

make it work on as much display framework as possible.

We have upstream plane, but I am really in a rush this year. So sorry 
for the late of upstream, but we glad to work with community.

So Sascha, please feel free to go on with your work.

> shows a blank screen. I believe the root cause of this is that the
> VOP2 driver does not use any of the atomic state correctly, and
> instead stores its own state in driver-global structures, using a lot
> of unnecessary mutexes to try to synchronise this state. Not only does
> this synchronisation not actually work, but it causes a severe
> performance degradation due to mutex contention.
>
> I believe the best path forward to an upstream VOP2 driver is a patch
> series consisting of:
>    - start from a blank slate, using the atomic framework and helpers
> as they were intended to be, with basic support for the VOP2 and one
> or two connector types, doing linear XRGB only
>    - any cleanups which would enable this to share more code with
>    - add YUV support, including planar buffers
>    - add AFBC support, with the AFBC enable/disable correctly
> synchronised through atomic state (this is necessary since the AFBC
> decoder is not directly on the planes per se but shared)
>    - add more connector types
>    - add writeback support
>    - add other Rockchip-specific codepaths such as HDR10
>
> Cheers,
> Daniel
>
>
>



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:14             ` Andy Yan
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Yan @ 2021-11-18 13:14 UTC (permalink / raw)
  To: Daniel Stone, Kever Yang
  Cc: Heiko Stübner, Sascha Hauer, dri-devel, devicetree,
	Benjamin Gaignard, Peter Geis, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, linux-arm-kernel

Hi Daniel:

On 11/18/21 8:07 PM, Daniel Stone wrote:
> Hi Kever,
>
> On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
>> On 2021/11/18 下午5:53, Daniel Stone wrote:
>>> Exactly what Heiko said. If you would like to upstream the driver then
>>> that would be fantastic to see, but I'm afraid you do not get to
>>> prevent someone else from doing the work themselves.
>> First of all, we never stop any one to doing there work on upstream if
>> the source code is write totally by themselves.
>>
>> Second, there are also many modules are upstream by developers based on
>> Rockchip source code, please note that
>> all of them have basic respect to our work, they do communicate with us
>> first.
>>
>> But this committer do not take any respect to our engineers and their
>> hard working:
>> - He didn't contact with us;
>> - There isn't  any information about original author in the commit message;
>>       As I have known, if I use source code from another developer, I
>> need to at least add a "Signed-off-by" with original author;
>> - This commit and mail does not even have a 'CC' to original author.
>>
>> I NAK because I  think this is not part of the  open source spirit, and
>> this kind of  behavior should not be encouraged.
> OK, I see where you're coming from, and I agree that the attribution
> should have been handled more carefully.
>
> On the other hand, please consider this from the other perspective.
> Sascha has been free to take the downstream Rockchip BSP code and
> attempt to upstream it to the Linux kernel, which you are unhappy
> about. But then the Rockchip driver was developed totally downstream,
> with no attempt to ever communicate with the upstream Linux or DRM/KMS
> developers. Rockchip advertises that it is shipped as a Linux kernel
> with a KMS driver. But we were never informed, or CCed, or anything.
>
> If you would like the community to more actively work with you - then
> please yourself work more actively with the community. The first
> commit of the VOP2 driver was in July 2020, and that was of the full
> driver so presumably it started quite some time before then. So that
> is a minimum of 17 months that you have had to engage with upstream
> ...
>
> Technically, the driver cannot be upstreamed as-is. It looks as if it
> were a pre-atomic driver, that was half-converted to atomic, and then
> has been half-converted to atomic helpers as well. Things like
> reference counting and global state are not handled correctly at all.
> You can see this if you try to run Weston on top of the VOP2 driver:
> the framerate is decimated because the event handling massively
> over-synchronises, and the event timestamps which arrive are
> incorrect. This would be fixed by correctly using the event helpers
> that we have had in the tree for years (which would also eliminate the
> unnecessary framebuffer reference handling). It also does not work
> with the GPU drivers in the tree because it lacks the one-liner to
> correctly handle dma_resv synchronisation, which makes it both too
> fast as it displays content which is not ready, and too slow because
> it can't do it at full frame rate.


We have different team run Android , X11, Weston on rk356x, especially 
for android, we can run at 60 fps.

Our vop2 driver is developed on Linux 4.19, am not sure which version of 
kernel you put our drivers on.

>
> Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> also active, but when HDMI is active at the same time as DSI, it just

I am very sure rk3566 evb DSI can work without HDMI.

But take care that the vop on rk3566 has a special limitation: there are 
three

windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they

can't be programed framebuffer address independently , they can only

share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature

on Android.

I have comment these limitation in our driver.

Compared to old vop, vop is strong but a bit complicated, we try very had to

make it work on as much display framework as possible.

We have upstream plane, but I am really in a rush this year. So sorry 
for the late of upstream, but we glad to work with community.

So Sascha, please feel free to go on with your work.

> shows a blank screen. I believe the root cause of this is that the
> VOP2 driver does not use any of the atomic state correctly, and
> instead stores its own state in driver-global structures, using a lot
> of unnecessary mutexes to try to synchronise this state. Not only does
> this synchronisation not actually work, but it causes a severe
> performance degradation due to mutex contention.
>
> I believe the best path forward to an upstream VOP2 driver is a patch
> series consisting of:
>    - start from a blank slate, using the atomic framework and helpers
> as they were intended to be, with basic support for the VOP2 and one
> or two connector types, doing linear XRGB only
>    - any cleanups which would enable this to share more code with
>    - add YUV support, including planar buffers
>    - add AFBC support, with the AFBC enable/disable correctly
> synchronised through atomic state (this is necessary since the AFBC
> decoder is not directly on the planes per se but shared)
>    - add more connector types
>    - add writeback support
>    - add other Rockchip-specific codepaths such as HDR10
>
> Cheers,
> Daniel
>
>
>



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:14             ` Andy Yan
  0 siblings, 0 replies; 201+ messages in thread
From: Andy Yan @ 2021-11-18 13:14 UTC (permalink / raw)
  To: Daniel Stone, Kever Yang
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, Peter Geis, kernel,
	linux-arm-kernel

Hi Daniel:

On 11/18/21 8:07 PM, Daniel Stone wrote:
> Hi Kever,
>
> On Thu, 18 Nov 2021 at 10:50, Kever Yang <kever.yang@rock-chips.com> wrote:
>> On 2021/11/18 下午5:53, Daniel Stone wrote:
>>> Exactly what Heiko said. If you would like to upstream the driver then
>>> that would be fantastic to see, but I'm afraid you do not get to
>>> prevent someone else from doing the work themselves.
>> First of all, we never stop any one to doing there work on upstream if
>> the source code is write totally by themselves.
>>
>> Second, there are also many modules are upstream by developers based on
>> Rockchip source code, please note that
>> all of them have basic respect to our work, they do communicate with us
>> first.
>>
>> But this committer do not take any respect to our engineers and their
>> hard working:
>> - He didn't contact with us;
>> - There isn't  any information about original author in the commit message;
>>       As I have known, if I use source code from another developer, I
>> need to at least add a "Signed-off-by" with original author;
>> - This commit and mail does not even have a 'CC' to original author.
>>
>> I NAK because I  think this is not part of the  open source spirit, and
>> this kind of  behavior should not be encouraged.
> OK, I see where you're coming from, and I agree that the attribution
> should have been handled more carefully.
>
> On the other hand, please consider this from the other perspective.
> Sascha has been free to take the downstream Rockchip BSP code and
> attempt to upstream it to the Linux kernel, which you are unhappy
> about. But then the Rockchip driver was developed totally downstream,
> with no attempt to ever communicate with the upstream Linux or DRM/KMS
> developers. Rockchip advertises that it is shipped as a Linux kernel
> with a KMS driver. But we were never informed, or CCed, or anything.
>
> If you would like the community to more actively work with you - then
> please yourself work more actively with the community. The first
> commit of the VOP2 driver was in July 2020, and that was of the full
> driver so presumably it started quite some time before then. So that
> is a minimum of 17 months that you have had to engage with upstream
> ...
>
> Technically, the driver cannot be upstreamed as-is. It looks as if it
> were a pre-atomic driver, that was half-converted to atomic, and then
> has been half-converted to atomic helpers as well. Things like
> reference counting and global state are not handled correctly at all.
> You can see this if you try to run Weston on top of the VOP2 driver:
> the framerate is decimated because the event handling massively
> over-synchronises, and the event timestamps which arrive are
> incorrect. This would be fixed by correctly using the event helpers
> that we have had in the tree for years (which would also eliminate the
> unnecessary framebuffer reference handling). It also does not work
> with the GPU drivers in the tree because it lacks the one-liner to
> correctly handle dma_resv synchronisation, which makes it both too
> fast as it displays content which is not ready, and too slow because
> it can't do it at full frame rate.


We have different team run Android , X11, Weston on rk356x, especially 
for android, we can run at 60 fps.

Our vop2 driver is developed on Linux 4.19, am not sure which version of 
kernel you put our drivers on.

>
> Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> also active, but when HDMI is active at the same time as DSI, it just

I am very sure rk3566 evb DSI can work without HDMI.

But take care that the vop on rk3566 has a special limitation: there are 
three

windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they

can't be programed framebuffer address independently , they can only

share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature

on Android.

I have comment these limitation in our driver.

Compared to old vop, vop is strong but a bit complicated, we try very had to

make it work on as much display framework as possible.

We have upstream plane, but I am really in a rush this year. So sorry 
for the late of upstream, but we glad to work with community.

So Sascha, please feel free to go on with your work.

> shows a blank screen. I believe the root cause of this is that the
> VOP2 driver does not use any of the atomic state correctly, and
> instead stores its own state in driver-global structures, using a lot
> of unnecessary mutexes to try to synchronise this state. Not only does
> this synchronisation not actually work, but it causes a severe
> performance degradation due to mutex contention.
>
> I believe the best path forward to an upstream VOP2 driver is a patch
> series consisting of:
>    - start from a blank slate, using the atomic framework and helpers
> as they were intended to be, with basic support for the VOP2 and one
> or two connector types, doing linear XRGB only
>    - any cleanups which would enable this to share more code with
>    - add YUV support, including planar buffers
>    - add AFBC support, with the AFBC enable/disable correctly
> synchronised through atomic state (this is necessary since the AFBC
> decoder is not directly on the planes per se but shared)
>    - add more connector types
>    - add writeback support
>    - add other Rockchip-specific codepaths such as HDR10
>
> Cheers,
> Daniel
>
>
>



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-18 13:14             ` Andy Yan
  (?)
  (?)
@ 2021-11-18 13:24               ` Daniel Stone
  -1 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 13:24 UTC (permalink / raw)
  To: Andy Yan
  Cc: Kever Yang, Heiko Stübner, Sascha Hauer, dri-devel,
	devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, linux-arm-kernel

Hi Andy,

On Thu, 18 Nov 2021 at 13:14, Andy Yan <andy.yan@rock-chips.com> wrote:
> On 11/18/21 8:07 PM, Daniel Stone wrote:
> > Technically, the driver cannot be upstreamed as-is. It looks as if it
> > were a pre-atomic driver, that was half-converted to atomic, and then
> > has been half-converted to atomic helpers as well. Things like
> > reference counting and global state are not handled correctly at all.
> > You can see this if you try to run Weston on top of the VOP2 driver:
> > the framerate is decimated because the event handling massively
> > over-synchronises, and the event timestamps which arrive are
> > incorrect. This would be fixed by correctly using the event helpers
> > that we have had in the tree for years (which would also eliminate the
> > unnecessary framebuffer reference handling). It also does not work
> > with the GPU drivers in the tree because it lacks the one-liner to
> > correctly handle dma_resv synchronisation, which makes it both too
> > fast as it displays content which is not ready, and too slow because
> > it can't do it at full frame rate.
>
> We have different team run Android , X11, Weston on rk356x, especially
> for android, we can run at 60 fps.
>
> Our vop2 driver is developed on Linux 4.19, am not sure which version of
> kernel you put our drivers on.

We forward-ported it to a current mainline kernel and started to work
on fixing some of the issues. When we did this, we went back to the
BSP tree posted on GitHub to test using a pure-BSP environment, and
observed the same breakage there.

> > Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> > also active, but when HDMI is active at the same time as DSI, it just
>
> I am very sure rk3566 evb DSI can work without HDMI.

I'd love to know how. :) Using the meta-rockchip layer as published on
GitHub, we cannot get working DSI without HDMI, using upstream Weston.
When the HDMI connector is disabled, DSI comes up blank. When the HDMI
connector is enabled, DSI works fine but HDMI is blank.

> But take care that the vop on rk3566 has a special limitation: there are
> three windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> can't be programed framebuffer address independently , they can only
> share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature
> on Android.
>
> I have comment these limitation in our driver.

Yeah, we noticed this.

> Compared to old vop, vop is strong but a bit complicated, we try very had to
> make it work on as much display framework as possible.
>
> We have upstream plane, but I am really in a rush this year. So sorry
> for the late of upstream, but we glad to work with community.
>
> So Sascha, please feel free to go on with your work.

Great, thanks. If you agree with the plan I posted, then we can all go
forward with that upstream, doing the development work with ourselves
and Sascha. Hopefully Rockchip will be able to support this effort.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:24               ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 13:24 UTC (permalink / raw)
  To: Andy Yan
  Cc: devicetree, Benjamin Gaignard, Sascha Hauer, Kever Yang,
	dri-devel, Sandy Huang, linux-rockchip, Michael Riesch,
	Peter Geis, kernel, linux-arm-kernel

Hi Andy,

On Thu, 18 Nov 2021 at 13:14, Andy Yan <andy.yan@rock-chips.com> wrote:
> On 11/18/21 8:07 PM, Daniel Stone wrote:
> > Technically, the driver cannot be upstreamed as-is. It looks as if it
> > were a pre-atomic driver, that was half-converted to atomic, and then
> > has been half-converted to atomic helpers as well. Things like
> > reference counting and global state are not handled correctly at all.
> > You can see this if you try to run Weston on top of the VOP2 driver:
> > the framerate is decimated because the event handling massively
> > over-synchronises, and the event timestamps which arrive are
> > incorrect. This would be fixed by correctly using the event helpers
> > that we have had in the tree for years (which would also eliminate the
> > unnecessary framebuffer reference handling). It also does not work
> > with the GPU drivers in the tree because it lacks the one-liner to
> > correctly handle dma_resv synchronisation, which makes it both too
> > fast as it displays content which is not ready, and too slow because
> > it can't do it at full frame rate.
>
> We have different team run Android , X11, Weston on rk356x, especially
> for android, we can run at 60 fps.
>
> Our vop2 driver is developed on Linux 4.19, am not sure which version of
> kernel you put our drivers on.

We forward-ported it to a current mainline kernel and started to work
on fixing some of the issues. When we did this, we went back to the
BSP tree posted on GitHub to test using a pure-BSP environment, and
observed the same breakage there.

> > Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> > also active, but when HDMI is active at the same time as DSI, it just
>
> I am very sure rk3566 evb DSI can work without HDMI.

I'd love to know how. :) Using the meta-rockchip layer as published on
GitHub, we cannot get working DSI without HDMI, using upstream Weston.
When the HDMI connector is disabled, DSI comes up blank. When the HDMI
connector is enabled, DSI works fine but HDMI is blank.

> But take care that the vop on rk3566 has a special limitation: there are
> three windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> can't be programed framebuffer address independently , they can only
> share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature
> on Android.
>
> I have comment these limitation in our driver.

Yeah, we noticed this.

> Compared to old vop, vop is strong but a bit complicated, we try very had to
> make it work on as much display framework as possible.
>
> We have upstream plane, but I am really in a rush this year. So sorry
> for the late of upstream, but we glad to work with community.
>
> So Sascha, please feel free to go on with your work.

Great, thanks. If you agree with the plan I posted, then we can all go
forward with that upstream, doing the development work with ourselves
and Sascha. Hopefully Rockchip will be able to support this effort.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:24               ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 13:24 UTC (permalink / raw)
  To: Andy Yan
  Cc: Kever Yang, Heiko Stübner, Sascha Hauer, dri-devel,
	devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, linux-arm-kernel

Hi Andy,

On Thu, 18 Nov 2021 at 13:14, Andy Yan <andy.yan@rock-chips.com> wrote:
> On 11/18/21 8:07 PM, Daniel Stone wrote:
> > Technically, the driver cannot be upstreamed as-is. It looks as if it
> > were a pre-atomic driver, that was half-converted to atomic, and then
> > has been half-converted to atomic helpers as well. Things like
> > reference counting and global state are not handled correctly at all.
> > You can see this if you try to run Weston on top of the VOP2 driver:
> > the framerate is decimated because the event handling massively
> > over-synchronises, and the event timestamps which arrive are
> > incorrect. This would be fixed by correctly using the event helpers
> > that we have had in the tree for years (which would also eliminate the
> > unnecessary framebuffer reference handling). It also does not work
> > with the GPU drivers in the tree because it lacks the one-liner to
> > correctly handle dma_resv synchronisation, which makes it both too
> > fast as it displays content which is not ready, and too slow because
> > it can't do it at full frame rate.
>
> We have different team run Android , X11, Weston on rk356x, especially
> for android, we can run at 60 fps.
>
> Our vop2 driver is developed on Linux 4.19, am not sure which version of
> kernel you put our drivers on.

We forward-ported it to a current mainline kernel and started to work
on fixing some of the issues. When we did this, we went back to the
BSP tree posted on GitHub to test using a pure-BSP environment, and
observed the same breakage there.

> > Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> > also active, but when HDMI is active at the same time as DSI, it just
>
> I am very sure rk3566 evb DSI can work without HDMI.

I'd love to know how. :) Using the meta-rockchip layer as published on
GitHub, we cannot get working DSI without HDMI, using upstream Weston.
When the HDMI connector is disabled, DSI comes up blank. When the HDMI
connector is enabled, DSI works fine but HDMI is blank.

> But take care that the vop on rk3566 has a special limitation: there are
> three windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> can't be programed framebuffer address independently , they can only
> share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature
> on Android.
>
> I have comment these limitation in our driver.

Yeah, we noticed this.

> Compared to old vop, vop is strong but a bit complicated, we try very had to
> make it work on as much display framework as possible.
>
> We have upstream plane, but I am really in a rush this year. So sorry
> for the late of upstream, but we glad to work with community.
>
> So Sascha, please feel free to go on with your work.

Great, thanks. If you agree with the plan I posted, then we can all go
forward with that upstream, doing the development work with ourselves
and Sascha. Hopefully Rockchip will be able to support this effort.

Cheers,
Daniel

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-18 13:24               ` Daniel Stone
  0 siblings, 0 replies; 201+ messages in thread
From: Daniel Stone @ 2021-11-18 13:24 UTC (permalink / raw)
  To: Andy Yan
  Cc: Kever Yang, Heiko Stübner, Sascha Hauer, dri-devel,
	devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, linux-arm-kernel

Hi Andy,

On Thu, 18 Nov 2021 at 13:14, Andy Yan <andy.yan@rock-chips.com> wrote:
> On 11/18/21 8:07 PM, Daniel Stone wrote:
> > Technically, the driver cannot be upstreamed as-is. It looks as if it
> > were a pre-atomic driver, that was half-converted to atomic, and then
> > has been half-converted to atomic helpers as well. Things like
> > reference counting and global state are not handled correctly at all.
> > You can see this if you try to run Weston on top of the VOP2 driver:
> > the framerate is decimated because the event handling massively
> > over-synchronises, and the event timestamps which arrive are
> > incorrect. This would be fixed by correctly using the event helpers
> > that we have had in the tree for years (which would also eliminate the
> > unnecessary framebuffer reference handling). It also does not work
> > with the GPU drivers in the tree because it lacks the one-liner to
> > correctly handle dma_resv synchronisation, which makes it both too
> > fast as it displays content which is not ready, and too slow because
> > it can't do it at full frame rate.
>
> We have different team run Android , X11, Weston on rk356x, especially
> for android, we can run at 60 fps.
>
> Our vop2 driver is developed on Linux 4.19, am not sure which version of
> kernel you put our drivers on.

We forward-ported it to a current mainline kernel and started to work
on fixing some of the issues. When we did this, we went back to the
BSP tree posted on GitHub to test using a pure-BSP environment, and
observed the same breakage there.

> > Similarly, on the RK3566 EVB, the DSI does not work unless HDMI is
> > also active, but when HDMI is active at the same time as DSI, it just
>
> I am very sure rk3566 evb DSI can work without HDMI.

I'd love to know how. :) Using the meta-rockchip layer as published on
GitHub, we cannot get working DSI without HDMI, using upstream Weston.
When the HDMI connector is disabled, DSI comes up blank. When the HDMI
connector is enabled, DSI works fine but HDMI is blank.

> But take care that the vop on rk3566 has a special limitation: there are
> three windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> can't be programed framebuffer address independently , they can only
> share framebuffer address with Cluster0/Esmart0/Smart0. We use these feature
> on Android.
>
> I have comment these limitation in our driver.

Yeah, we noticed this.

> Compared to old vop, vop is strong but a bit complicated, we try very had to
> make it work on as much display framework as possible.
>
> We have upstream plane, but I am really in a rush this year. So sorry
> for the late of upstream, but we glad to work with community.
>
> So Sascha, please feel free to go on with your work.

Great, thanks. If you agree with the plan I posted, then we can all go
forward with that upstream, doing the development work with ourselves
and Sascha. Hopefully Rockchip will be able to support this effort.

Cheers,
Daniel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-17 14:33 ` Sascha Hauer
  (?)
  (?)
@ 2021-11-21 23:18   ` Alex Bee
  -1 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-21 23:18 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.
>
> The HDMI changes are based on patches from Benjamin Gaignard, but
> modified a bit as I found out that the HDMI port on the RK3568 only
> needs one additional clock, not two. Also I added regulator support
> which is needed to get the HDMI up on the rk3568-EVB board.
>
> All review and testing feedback welcome


thanks for working on that - it's very (very,very) much appreciated.

It took me some time to figure it out: It seems rk3568-iommu driver s
broken - I did only get "white noise" when using it alongside vop
(similar like it was reported here before). However: removing the
iommu-property from vop makes it working for me with HDMI output on
quartz64 as well. Could you check if you have the iommu driver in kernel
enabled if it works for you, if the property is present in DT? (I used
5.16-rc1 + this series + [0]). Also vop mmu seems to have the
power-domain missing in your series (same as downstream) - however
adding that doesn't help much currently.
As a sidenote: I verfied this with using Ezequiel's vpu addtion for
RK356x: It did only work when removing the iommu there as well (getting
tons of page faults otherwise) - so iommu driver really seems to broken,
at least for RK3566. (Or I'm a missing a option in kernel config, which
wasn't required for the older iommu version?)
 
But as reported before: For HDMI this does currently only work for pixel
clock rates, which are integer-divisable with hpll clock rate (which is
the hardcoded parent of vop0's dclk)
As discussed in Benjamin's initial submission of the addition of
RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
needs a reference clock (it's called vpll there) which needs to get
switched before the vop switches the mode (since phy rate switching is
done before) - it's HPLL in case of RK356x. For whatever reason it's
called "ref" for RK356x only downstream [2] - so you should add another
clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
What brings us to the "real" clock problem and the reason, why
non-integer divisable pixel clock rates are not possible ATM: This is a
long standing issue for RK3288 and RK3399 as well (and one of the main
reasons why 4k modes are not possible for those older SoCs currently):
Upstream all PLL rates are controlled with those PLL rate tables in the
clock driver and they have to be _exactly_ defined as they are used
(HDMI sinks are very picky).
You will not see any additional rates downstream for RK3568: they have a
mechanism there to automatically calculate the PLL settings if the rate
doesn't exist in these tables (IIRC this was submitted upstream also:
but it was rejected/ignored by maintainers). As a quick hackarround (for
testing): You could use this table [3] we are using in LibreElec for
RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
driver (I tested it and it works great). It might be possible to just
add those rates (some also without frac dividers) to the common PLL
table for RK3568.
 
I'm sorry I didn't reply inline as I'm supposed to do: It's late and I
wanted to offload my findings now :)
 
(You probably should also remove the printks in V2)
 
Best,

Alex


[0]
https://patchwork.kernel.org/project/linux-rockchip/patch/20211117154429.2274443-1-michael.riesch@wolfvision.net/

[1] https://patchwork.kernel.org/comment/24295683/
[2]
https://github.com/rockchip-linux/kernel/blob/develop-4.19/arch/arm64/boot/dts/rockchip/rk3568.dtsi#L1715-L1720

[3]
https://github.com/LibreELEC/LibreELEC.tv/blob/master/projects/Rockchip/patches/linux/default/linux-1000-drm-rockchip.patch#L3155-L3182



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-21 23:18   ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-21 23:18 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.
>
> The HDMI changes are based on patches from Benjamin Gaignard, but
> modified a bit as I found out that the HDMI port on the RK3568 only
> needs one additional clock, not two. Also I added regulator support
> which is needed to get the HDMI up on the rk3568-EVB board.
>
> All review and testing feedback welcome


thanks for working on that - it's very (very,very) much appreciated.

It took me some time to figure it out: It seems rk3568-iommu driver s
broken - I did only get "white noise" when using it alongside vop
(similar like it was reported here before). However: removing the
iommu-property from vop makes it working for me with HDMI output on
quartz64 as well. Could you check if you have the iommu driver in kernel
enabled if it works for you, if the property is present in DT? (I used
5.16-rc1 + this series + [0]). Also vop mmu seems to have the
power-domain missing in your series (same as downstream) - however
adding that doesn't help much currently.
As a sidenote: I verfied this with using Ezequiel's vpu addtion for
RK356x: It did only work when removing the iommu there as well (getting
tons of page faults otherwise) - so iommu driver really seems to broken,
at least for RK3566. (Or I'm a missing a option in kernel config, which
wasn't required for the older iommu version?)
 
But as reported before: For HDMI this does currently only work for pixel
clock rates, which are integer-divisable with hpll clock rate (which is
the hardcoded parent of vop0's dclk)
As discussed in Benjamin's initial submission of the addition of
RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
needs a reference clock (it's called vpll there) which needs to get
switched before the vop switches the mode (since phy rate switching is
done before) - it's HPLL in case of RK356x. For whatever reason it's
called "ref" for RK356x only downstream [2] - so you should add another
clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
What brings us to the "real" clock problem and the reason, why
non-integer divisable pixel clock rates are not possible ATM: This is a
long standing issue for RK3288 and RK3399 as well (and one of the main
reasons why 4k modes are not possible for those older SoCs currently):
Upstream all PLL rates are controlled with those PLL rate tables in the
clock driver and they have to be _exactly_ defined as they are used
(HDMI sinks are very picky).
You will not see any additional rates downstream for RK3568: they have a
mechanism there to automatically calculate the PLL settings if the rate
doesn't exist in these tables (IIRC this was submitted upstream also:
but it was rejected/ignored by maintainers). As a quick hackarround (for
testing): You could use this table [3] we are using in LibreElec for
RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
driver (I tested it and it works great). It might be possible to just
add those rates (some also without frac dividers) to the common PLL
table for RK3568.
 
I'm sorry I didn't reply inline as I'm supposed to do: It's late and I
wanted to offload my findings now :)
 
(You probably should also remove the printks in V2)
 
Best,

Alex


[0]
https://patchwork.kernel.org/project/linux-rockchip/patch/20211117154429.2274443-1-michael.riesch@wolfvision.net/

[1] https://patchwork.kernel.org/comment/24295683/
[2]
https://github.com/rockchip-linux/kernel/blob/develop-4.19/arch/arm64/boot/dts/rockchip/rk3568.dtsi#L1715-L1720

[3]
https://github.com/LibreELEC/LibreELEC.tv/blob/master/projects/Rockchip/patches/linux/default/linux-1000-drm-rockchip.patch#L3155-L3182



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-21 23:18   ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-21 23:18 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, Peter Geis, linux-arm-kernel

Hi Sascha,

Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.
>
> The HDMI changes are based on patches from Benjamin Gaignard, but
> modified a bit as I found out that the HDMI port on the RK3568 only
> needs one additional clock, not two. Also I added regulator support
> which is needed to get the HDMI up on the rk3568-EVB board.
>
> All review and testing feedback welcome


thanks for working on that - it's very (very,very) much appreciated.

It took me some time to figure it out: It seems rk3568-iommu driver s
broken - I did only get "white noise" when using it alongside vop
(similar like it was reported here before). However: removing the
iommu-property from vop makes it working for me with HDMI output on
quartz64 as well. Could you check if you have the iommu driver in kernel
enabled if it works for you, if the property is present in DT? (I used
5.16-rc1 + this series + [0]). Also vop mmu seems to have the
power-domain missing in your series (same as downstream) - however
adding that doesn't help much currently.
As a sidenote: I verfied this with using Ezequiel's vpu addtion for
RK356x: It did only work when removing the iommu there as well (getting
tons of page faults otherwise) - so iommu driver really seems to broken,
at least for RK3566. (Or I'm a missing a option in kernel config, which
wasn't required for the older iommu version?)
 
But as reported before: For HDMI this does currently only work for pixel
clock rates, which are integer-divisable with hpll clock rate (which is
the hardcoded parent of vop0's dclk)
As discussed in Benjamin's initial submission of the addition of
RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
needs a reference clock (it's called vpll there) which needs to get
switched before the vop switches the mode (since phy rate switching is
done before) - it's HPLL in case of RK356x. For whatever reason it's
called "ref" for RK356x only downstream [2] - so you should add another
clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
What brings us to the "real" clock problem and the reason, why
non-integer divisable pixel clock rates are not possible ATM: This is a
long standing issue for RK3288 and RK3399 as well (and one of the main
reasons why 4k modes are not possible for those older SoCs currently):
Upstream all PLL rates are controlled with those PLL rate tables in the
clock driver and they have to be _exactly_ defined as they are used
(HDMI sinks are very picky).
You will not see any additional rates downstream for RK3568: they have a
mechanism there to automatically calculate the PLL settings if the rate
doesn't exist in these tables (IIRC this was submitted upstream also:
but it was rejected/ignored by maintainers). As a quick hackarround (for
testing): You could use this table [3] we are using in LibreElec for
RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
driver (I tested it and it works great). It might be possible to just
add those rates (some also without frac dividers) to the common PLL
table for RK3568.
 
I'm sorry I didn't reply inline as I'm supposed to do: It's late and I
wanted to offload my findings now :)
 
(You probably should also remove the printks in V2)
 
Best,

Alex


[0]
https://patchwork.kernel.org/project/linux-rockchip/patch/20211117154429.2274443-1-michael.riesch@wolfvision.net/

[1] https://patchwork.kernel.org/comment/24295683/
[2]
https://github.com/rockchip-linux/kernel/blob/develop-4.19/arch/arm64/boot/dts/rockchip/rk3568.dtsi#L1715-L1720

[3]
https://github.com/LibreELEC/LibreELEC.tv/blob/master/projects/Rockchip/patches/linux/default/linux-1000-drm-rockchip.patch#L3155-L3182



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-21 23:18   ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-21 23:18 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> This series adds initial graphics support for the Rockchip RK356[68]
> SoCs.  Graphics support is based around the VOP2 controller which
> replaces the VOP controller found on earlier Rockchip SoCs. The driver
> has been tested with HDMI support included in this series and MIPI-DSI
> which is not included because it needs some more work. The driver is
> taken from the downstream Rockchip kernel and heavily polished, most non
> standard features have been removed for now. I tested the driver with
> the libdrm modetest utility and also with weston with both pixman and
> panfrost driver support. Michael Riesch reported the driver to work on
> the RK3566 as well, but device tree support for this SoC is not yet
> included in this series.
>
> The HDMI changes are based on patches from Benjamin Gaignard, but
> modified a bit as I found out that the HDMI port on the RK3568 only
> needs one additional clock, not two. Also I added regulator support
> which is needed to get the HDMI up on the rk3568-EVB board.
>
> All review and testing feedback welcome


thanks for working on that - it's very (very,very) much appreciated.

It took me some time to figure it out: It seems rk3568-iommu driver s
broken - I did only get "white noise" when using it alongside vop
(similar like it was reported here before). However: removing the
iommu-property from vop makes it working for me with HDMI output on
quartz64 as well. Could you check if you have the iommu driver in kernel
enabled if it works for you, if the property is present in DT? (I used
5.16-rc1 + this series + [0]). Also vop mmu seems to have the
power-domain missing in your series (same as downstream) - however
adding that doesn't help much currently.
As a sidenote: I verfied this with using Ezequiel's vpu addtion for
RK356x: It did only work when removing the iommu there as well (getting
tons of page faults otherwise) - so iommu driver really seems to broken,
at least for RK3566. (Or I'm a missing a option in kernel config, which
wasn't required for the older iommu version?)
 
But as reported before: For HDMI this does currently only work for pixel
clock rates, which are integer-divisable with hpll clock rate (which is
the hardcoded parent of vop0's dclk)
As discussed in Benjamin's initial submission of the addition of
RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
needs a reference clock (it's called vpll there) which needs to get
switched before the vop switches the mode (since phy rate switching is
done before) - it's HPLL in case of RK356x. For whatever reason it's
called "ref" for RK356x only downstream [2] - so you should add another
clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
What brings us to the "real" clock problem and the reason, why
non-integer divisable pixel clock rates are not possible ATM: This is a
long standing issue for RK3288 and RK3399 as well (and one of the main
reasons why 4k modes are not possible for those older SoCs currently):
Upstream all PLL rates are controlled with those PLL rate tables in the
clock driver and they have to be _exactly_ defined as they are used
(HDMI sinks are very picky).
You will not see any additional rates downstream for RK3568: they have a
mechanism there to automatically calculate the PLL settings if the rate
doesn't exist in these tables (IIRC this was submitted upstream also:
but it was rejected/ignored by maintainers). As a quick hackarround (for
testing): You could use this table [3] we are using in LibreElec for
RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
driver (I tested it and it works great). It might be possible to just
add those rates (some also without frac dividers) to the common PLL
table for RK3568.
 
I'm sorry I didn't reply inline as I'm supposed to do: It's late and I
wanted to offload my findings now :)
 
(You probably should also remove the printks in V2)
 
Best,

Alex


[0]
https://patchwork.kernel.org/project/linux-rockchip/patch/20211117154429.2274443-1-michael.riesch@wolfvision.net/

[1] https://patchwork.kernel.org/comment/24295683/
[2]
https://github.com/rockchip-linux/kernel/blob/develop-4.19/arch/arm64/boot/dts/rockchip/rk3568.dtsi#L1715-L1720

[3]
https://github.com/LibreELEC/LibreELEC.tv/blob/master/projects/Rockchip/patches/linux/default/linux-1000-drm-rockchip.patch#L3155-L3182



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-21 23:18   ` Alex Bee
  (?)
  (?)
@ 2021-11-22  8:10     ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-22  8:10 UTC (permalink / raw)
  To: Alex Bee
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

Hi Alex,

On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
> Hi Sascha,
> 
> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> >
> > The HDMI changes are based on patches from Benjamin Gaignard, but
> > modified a bit as I found out that the HDMI port on the RK3568 only
> > needs one additional clock, not two. Also I added regulator support
> > which is needed to get the HDMI up on the rk3568-EVB board.
> >
> > All review and testing feedback welcome
> 
> 
> thanks for working on that - it's very (very,very) much appreciated.
> 
> It took me some time to figure it out: It seems rk3568-iommu driver s
> broken - I did only get "white noise" when using it alongside vop
> (similar like it was reported here before). However: removing the
> iommu-property from vop makes it working for me with HDMI output on
> quartz64 as well. Could you check if you have the iommu driver in kernel
> enabled if it works for you, if the property is present in DT? (I used
> 5.16-rc1 + this series + [0]).

I have the iommu driver enabled and it works for me. I get this during
boot:

[0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0

So I expect it is indeed used.

> Also vop mmu seems to have the
> power-domain missing in your series (same as downstream) - however
> adding that doesn't help much currently.

Probably the power domain gets enabled anyway when the VOP is activated,
so adding it to the iommu won't help anything. Nevertheless it seems
correct to add the property, I'll do so in the next round.

> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
> RK356x: It did only work when removing the iommu there as well (getting
> tons of page faults otherwise) - so iommu driver really seems to broken,
> at least for RK3566. (Or I'm a missing a option in kernel config, which
> wasn't required for the older iommu version?)

I don't think so. I started from defconfig and disabled other
architectures and unneeded drivers, but I did not enable anything
specific to iommu.

>  
> But as reported before: For HDMI this does currently only work for pixel
> clock rates, which are integer-divisable with hpll clock rate (which is
> the hardcoded parent of vop0's dclk)
> As discussed in Benjamin's initial submission of the addition of
> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
> needs a reference clock (it's called vpll there) which needs to get
> switched before the vop switches the mode (since phy rate switching is
> done before) - it's HPLL in case of RK356x. For whatever reason it's
> called "ref" for RK356x only downstream [2] - so you should add another
> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.

Yeah, a consumer clock should be named after the usage in the consumer,
not after the provider name. I also stumbled over this and naming it
"ref" makes much more sense. We'll likely have to keep supporting "vpll"
as well for compatibility to old device trees.

> What brings us to the "real" clock problem and the reason, why
> non-integer divisable pixel clock rates are not possible ATM: This is a
> long standing issue for RK3288 and RK3399 as well (and one of the main
> reasons why 4k modes are not possible for those older SoCs currently):
> Upstream all PLL rates are controlled with those PLL rate tables in the
> clock driver and they have to be _exactly_ defined as they are used
> (HDMI sinks are very picky).
> You will not see any additional rates downstream for RK3568: they have a
> mechanism there to automatically calculate the PLL settings if the rate
> doesn't exist in these tables (IIRC this was submitted upstream also:
> but it was rejected/ignored by maintainers).

Looks like we have to try harder to get it upstream. Do you have a
pointer to this patch?

> As a quick hackarround (for
> testing): You could use this table [3] we are using in LibreElec for
> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
> driver (I tested it and it works great). It might be possible to just
> add those rates (some also without frac dividers) to the common PLL
> table for RK3568.

Thanks for noting. This could also explain why currently only 1080p is
working.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22  8:10     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-22  8:10 UTC (permalink / raw)
  To: Alex Bee
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Alex,

On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
> Hi Sascha,
> 
> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> >
> > The HDMI changes are based on patches from Benjamin Gaignard, but
> > modified a bit as I found out that the HDMI port on the RK3568 only
> > needs one additional clock, not two. Also I added regulator support
> > which is needed to get the HDMI up on the rk3568-EVB board.
> >
> > All review and testing feedback welcome
> 
> 
> thanks for working on that - it's very (very,very) much appreciated.
> 
> It took me some time to figure it out: It seems rk3568-iommu driver s
> broken - I did only get "white noise" when using it alongside vop
> (similar like it was reported here before). However: removing the
> iommu-property from vop makes it working for me with HDMI output on
> quartz64 as well. Could you check if you have the iommu driver in kernel
> enabled if it works for you, if the property is present in DT? (I used
> 5.16-rc1 + this series + [0]).

I have the iommu driver enabled and it works for me. I get this during
boot:

[0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0

So I expect it is indeed used.

> Also vop mmu seems to have the
> power-domain missing in your series (same as downstream) - however
> adding that doesn't help much currently.

Probably the power domain gets enabled anyway when the VOP is activated,
so adding it to the iommu won't help anything. Nevertheless it seems
correct to add the property, I'll do so in the next round.

> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
> RK356x: It did only work when removing the iommu there as well (getting
> tons of page faults otherwise) - so iommu driver really seems to broken,
> at least for RK3566. (Or I'm a missing a option in kernel config, which
> wasn't required for the older iommu version?)

I don't think so. I started from defconfig and disabled other
architectures and unneeded drivers, but I did not enable anything
specific to iommu.

>  
> But as reported before: For HDMI this does currently only work for pixel
> clock rates, which are integer-divisable with hpll clock rate (which is
> the hardcoded parent of vop0's dclk)
> As discussed in Benjamin's initial submission of the addition of
> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
> needs a reference clock (it's called vpll there) which needs to get
> switched before the vop switches the mode (since phy rate switching is
> done before) - it's HPLL in case of RK356x. For whatever reason it's
> called "ref" for RK356x only downstream [2] - so you should add another
> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.

Yeah, a consumer clock should be named after the usage in the consumer,
not after the provider name. I also stumbled over this and naming it
"ref" makes much more sense. We'll likely have to keep supporting "vpll"
as well for compatibility to old device trees.

> What brings us to the "real" clock problem and the reason, why
> non-integer divisable pixel clock rates are not possible ATM: This is a
> long standing issue for RK3288 and RK3399 as well (and one of the main
> reasons why 4k modes are not possible for those older SoCs currently):
> Upstream all PLL rates are controlled with those PLL rate tables in the
> clock driver and they have to be _exactly_ defined as they are used
> (HDMI sinks are very picky).
> You will not see any additional rates downstream for RK3568: they have a
> mechanism there to automatically calculate the PLL settings if the rate
> doesn't exist in these tables (IIRC this was submitted upstream also:
> but it was rejected/ignored by maintainers).

Looks like we have to try harder to get it upstream. Do you have a
pointer to this patch?

> As a quick hackarround (for
> testing): You could use this table [3] we are using in LibreElec for
> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
> driver (I tested it and it works great). It might be possible to just
> add those rates (some also without frac dividers) to the common PLL
> table for RK3568.

Thanks for noting. This could also explain why currently only 1080p is
working.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22  8:10     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-22  8:10 UTC (permalink / raw)
  To: Alex Bee
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Alex,

On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
> Hi Sascha,
> 
> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> >
> > The HDMI changes are based on patches from Benjamin Gaignard, but
> > modified a bit as I found out that the HDMI port on the RK3568 only
> > needs one additional clock, not two. Also I added regulator support
> > which is needed to get the HDMI up on the rk3568-EVB board.
> >
> > All review and testing feedback welcome
> 
> 
> thanks for working on that - it's very (very,very) much appreciated.
> 
> It took me some time to figure it out: It seems rk3568-iommu driver s
> broken - I did only get "white noise" when using it alongside vop
> (similar like it was reported here before). However: removing the
> iommu-property from vop makes it working for me with HDMI output on
> quartz64 as well. Could you check if you have the iommu driver in kernel
> enabled if it works for you, if the property is present in DT? (I used
> 5.16-rc1 + this series + [0]).

I have the iommu driver enabled and it works for me. I get this during
boot:

[0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0

So I expect it is indeed used.

> Also vop mmu seems to have the
> power-domain missing in your series (same as downstream) - however
> adding that doesn't help much currently.

Probably the power domain gets enabled anyway when the VOP is activated,
so adding it to the iommu won't help anything. Nevertheless it seems
correct to add the property, I'll do so in the next round.

> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
> RK356x: It did only work when removing the iommu there as well (getting
> tons of page faults otherwise) - so iommu driver really seems to broken,
> at least for RK3566. (Or I'm a missing a option in kernel config, which
> wasn't required for the older iommu version?)

I don't think so. I started from defconfig and disabled other
architectures and unneeded drivers, but I did not enable anything
specific to iommu.

>  
> But as reported before: For HDMI this does currently only work for pixel
> clock rates, which are integer-divisable with hpll clock rate (which is
> the hardcoded parent of vop0's dclk)
> As discussed in Benjamin's initial submission of the addition of
> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
> needs a reference clock (it's called vpll there) which needs to get
> switched before the vop switches the mode (since phy rate switching is
> done before) - it's HPLL in case of RK356x. For whatever reason it's
> called "ref" for RK356x only downstream [2] - so you should add another
> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.

Yeah, a consumer clock should be named after the usage in the consumer,
not after the provider name. I also stumbled over this and naming it
"ref" makes much more sense. We'll likely have to keep supporting "vpll"
as well for compatibility to old device trees.

> What brings us to the "real" clock problem and the reason, why
> non-integer divisable pixel clock rates are not possible ATM: This is a
> long standing issue for RK3288 and RK3399 as well (and one of the main
> reasons why 4k modes are not possible for those older SoCs currently):
> Upstream all PLL rates are controlled with those PLL rate tables in the
> clock driver and they have to be _exactly_ defined as they are used
> (HDMI sinks are very picky).
> You will not see any additional rates downstream for RK3568: they have a
> mechanism there to automatically calculate the PLL settings if the rate
> doesn't exist in these tables (IIRC this was submitted upstream also:
> but it was rejected/ignored by maintainers).

Looks like we have to try harder to get it upstream. Do you have a
pointer to this patch?

> As a quick hackarround (for
> testing): You could use this table [3] we are using in LibreElec for
> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
> driver (I tested it and it works great). It might be possible to just
> add those rates (some also without frac dividers) to the common PLL
> table for RK3568.

Thanks for noting. This could also explain why currently only 1080p is
working.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22  8:10     ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-22  8:10 UTC (permalink / raw)
  To: Alex Bee
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Alex,

On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
> Hi Sascha,
> 
> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
> > This series adds initial graphics support for the Rockchip RK356[68]
> > SoCs.  Graphics support is based around the VOP2 controller which
> > replaces the VOP controller found on earlier Rockchip SoCs. The driver
> > has been tested with HDMI support included in this series and MIPI-DSI
> > which is not included because it needs some more work. The driver is
> > taken from the downstream Rockchip kernel and heavily polished, most non
> > standard features have been removed for now. I tested the driver with
> > the libdrm modetest utility and also with weston with both pixman and
> > panfrost driver support. Michael Riesch reported the driver to work on
> > the RK3566 as well, but device tree support for this SoC is not yet
> > included in this series.
> >
> > The HDMI changes are based on patches from Benjamin Gaignard, but
> > modified a bit as I found out that the HDMI port on the RK3568 only
> > needs one additional clock, not two. Also I added regulator support
> > which is needed to get the HDMI up on the rk3568-EVB board.
> >
> > All review and testing feedback welcome
> 
> 
> thanks for working on that - it's very (very,very) much appreciated.
> 
> It took me some time to figure it out: It seems rk3568-iommu driver s
> broken - I did only get "white noise" when using it alongside vop
> (similar like it was reported here before). However: removing the
> iommu-property from vop makes it working for me with HDMI output on
> quartz64 as well. Could you check if you have the iommu driver in kernel
> enabled if it works for you, if the property is present in DT? (I used
> 5.16-rc1 + this series + [0]).

I have the iommu driver enabled and it works for me. I get this during
boot:

[0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0

So I expect it is indeed used.

> Also vop mmu seems to have the
> power-domain missing in your series (same as downstream) - however
> adding that doesn't help much currently.

Probably the power domain gets enabled anyway when the VOP is activated,
so adding it to the iommu won't help anything. Nevertheless it seems
correct to add the property, I'll do so in the next round.

> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
> RK356x: It did only work when removing the iommu there as well (getting
> tons of page faults otherwise) - so iommu driver really seems to broken,
> at least for RK3566. (Or I'm a missing a option in kernel config, which
> wasn't required for the older iommu version?)

I don't think so. I started from defconfig and disabled other
architectures and unneeded drivers, but I did not enable anything
specific to iommu.

>  
> But as reported before: For HDMI this does currently only work for pixel
> clock rates, which are integer-divisable with hpll clock rate (which is
> the hardcoded parent of vop0's dclk)
> As discussed in Benjamin's initial submission of the addition of
> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
> needs a reference clock (it's called vpll there) which needs to get
> switched before the vop switches the mode (since phy rate switching is
> done before) - it's HPLL in case of RK356x. For whatever reason it's
> called "ref" for RK356x only downstream [2] - so you should add another
> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.

Yeah, a consumer clock should be named after the usage in the consumer,
not after the provider name. I also stumbled over this and naming it
"ref" makes much more sense. We'll likely have to keep supporting "vpll"
as well for compatibility to old device trees.

> What brings us to the "real" clock problem and the reason, why
> non-integer divisable pixel clock rates are not possible ATM: This is a
> long standing issue for RK3288 and RK3399 as well (and one of the main
> reasons why 4k modes are not possible for those older SoCs currently):
> Upstream all PLL rates are controlled with those PLL rate tables in the
> clock driver and they have to be _exactly_ defined as they are used
> (HDMI sinks are very picky).
> You will not see any additional rates downstream for RK3568: they have a
> mechanism there to automatically calculate the PLL settings if the rate
> doesn't exist in these tables (IIRC this was submitted upstream also:
> but it was rejected/ignored by maintainers).

Looks like we have to try harder to get it upstream. Do you have a
pointer to this patch?

> As a quick hackarround (for
> testing): You could use this table [3] we are using in LibreElec for
> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
> driver (I tested it and it works great). It might be possible to just
> add those rates (some also without frac dividers) to the common PLL
> table for RK3568.

Thanks for noting. This could also explain why currently only 1080p is
working.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-22  8:10     ` Sascha Hauer
  (?)
  (?)
@ 2021-11-22 17:47       ` Alex Bee
  -1 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-22 17:47 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Am 22.11.21 um 09:10 schrieb Sascha Hauer:
> Hi Alex,
>
> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>> Hi Sascha,
>>
>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>> This series adds initial graphics support for the Rockchip RK356[68]
>>> SoCs.  Graphics support is based around the VOP2 controller which
>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>> has been tested with HDMI support included in this series and MIPI-DSI
>>> which is not included because it needs some more work. The driver is
>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>> standard features have been removed for now. I tested the driver with
>>> the libdrm modetest utility and also with weston with both pixman and
>>> panfrost driver support. Michael Riesch reported the driver to work on
>>> the RK3566 as well, but device tree support for this SoC is not yet
>>> included in this series.
>>>
>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>> needs one additional clock, not two. Also I added regulator support
>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>
>>> All review and testing feedback welcome
>>
>> thanks for working on that - it's very (very,very) much appreciated.
>>
>> It took me some time to figure it out: It seems rk3568-iommu driver s
>> broken - I did only get "white noise" when using it alongside vop
>> (similar like it was reported here before). However: removing the
>> iommu-property from vop makes it working for me with HDMI output on
>> quartz64 as well. Could you check if you have the iommu driver in kernel
>> enabled if it works for you, if the property is present in DT? (I used
>> 5.16-rc1 + this series + [0]).
> I have the iommu driver enabled and it works for me. I get this during
> boot:
>
> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>
> So I expect it is indeed used.
>
>> Also vop mmu seems to have the
>> power-domain missing in your series (same as downstream) - however
>> adding that doesn't help much currently.
> Probably the power domain gets enabled anyway when the VOP is activated,
> so adding it to the iommu won't help anything. Nevertheless it seems
> correct to add the property, I'll do so in the next round.
>
>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>> RK356x: It did only work when removing the iommu there as well (getting
>> tons of page faults otherwise) - so iommu driver really seems to broken,
>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>> wasn't required for the older iommu version?)
> I don't think so. I started from defconfig and disabled other
> architectures and unneeded drivers, but I did not enable anything
> specific to iommu.

I've found out now that I can make it work with iommu, by limiting the
available memory to something below 4G (I have a 8G board). So there is
something wrong in the driver or somewhere in memory mapping, iommu api
(since it works when using CMA), ... however: it does clearly not relate
to your patch.

>>  
>> But as reported before: For HDMI this does currently only work for pixel
>> clock rates, which are integer-divisable with hpll clock rate (which is
>> the hardcoded parent of vop0's dclk)
>> As discussed in Benjamin's initial submission of the addition of
>> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
>> needs a reference clock (it's called vpll there) which needs to get
>> switched before the vop switches the mode (since phy rate switching is
>> done before) - it's HPLL in case of RK356x. For whatever reason it's
>> called "ref" for RK356x only downstream [2] - so you should add another
>> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
>> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
> Yeah, a consumer clock should be named after the usage in the consumer,
> not after the provider name. I also stumbled over this and naming it
> "ref" makes much more sense. We'll likely have to keep supporting "vpll"
> as well for compatibility to old device trees.
>
>> What brings us to the "real" clock problem and the reason, why
>> non-integer divisable pixel clock rates are not possible ATM: This is a
>> long standing issue for RK3288 and RK3399 as well (and one of the main
>> reasons why 4k modes are not possible for those older SoCs currently):
>> Upstream all PLL rates are controlled with those PLL rate tables in the
>> clock driver and they have to be _exactly_ defined as they are used
>> (HDMI sinks are very picky).
>> You will not see any additional rates downstream for RK3568: they have a
>> mechanism there to automatically calculate the PLL settings if the rate
>> doesn't exist in these tables (IIRC this was submitted upstream also:
>> but it was rejected/ignored by maintainers).
> Looks like we have to try harder to get it upstream. Do you have a
> pointer to this patch?

Sure:

https://patchwork.kernel.org/project/linux-clk/patch/20191204082527.19957-1-zhangqing@rock-chips.com/

I don't know if that is the was last submitted version.

Best regards,

Alex

>> As a quick hackarround (for
>> testing): You could use this table [3] we are using in LibreElec for
>> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
>> driver (I tested it and it works great). It might be possible to just
>> add those rates (some also without frac dividers) to the common PLL
>> table for RK3568.
> Thanks for noting. This could also explain why currently only 1080p is
> working.
>
> Sascha
>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 17:47       ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-22 17:47 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Am 22.11.21 um 09:10 schrieb Sascha Hauer:
> Hi Alex,
>
> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>> Hi Sascha,
>>
>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>> This series adds initial graphics support for the Rockchip RK356[68]
>>> SoCs.  Graphics support is based around the VOP2 controller which
>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>> has been tested with HDMI support included in this series and MIPI-DSI
>>> which is not included because it needs some more work. The driver is
>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>> standard features have been removed for now. I tested the driver with
>>> the libdrm modetest utility and also with weston with both pixman and
>>> panfrost driver support. Michael Riesch reported the driver to work on
>>> the RK3566 as well, but device tree support for this SoC is not yet
>>> included in this series.
>>>
>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>> needs one additional clock, not two. Also I added regulator support
>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>
>>> All review and testing feedback welcome
>>
>> thanks for working on that - it's very (very,very) much appreciated.
>>
>> It took me some time to figure it out: It seems rk3568-iommu driver s
>> broken - I did only get "white noise" when using it alongside vop
>> (similar like it was reported here before). However: removing the
>> iommu-property from vop makes it working for me with HDMI output on
>> quartz64 as well. Could you check if you have the iommu driver in kernel
>> enabled if it works for you, if the property is present in DT? (I used
>> 5.16-rc1 + this series + [0]).
> I have the iommu driver enabled and it works for me. I get this during
> boot:
>
> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>
> So I expect it is indeed used.
>
>> Also vop mmu seems to have the
>> power-domain missing in your series (same as downstream) - however
>> adding that doesn't help much currently.
> Probably the power domain gets enabled anyway when the VOP is activated,
> so adding it to the iommu won't help anything. Nevertheless it seems
> correct to add the property, I'll do so in the next round.
>
>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>> RK356x: It did only work when removing the iommu there as well (getting
>> tons of page faults otherwise) - so iommu driver really seems to broken,
>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>> wasn't required for the older iommu version?)
> I don't think so. I started from defconfig and disabled other
> architectures and unneeded drivers, but I did not enable anything
> specific to iommu.

I've found out now that I can make it work with iommu, by limiting the
available memory to something below 4G (I have a 8G board). So there is
something wrong in the driver or somewhere in memory mapping, iommu api
(since it works when using CMA), ... however: it does clearly not relate
to your patch.

>>  
>> But as reported before: For HDMI this does currently only work for pixel
>> clock rates, which are integer-divisable with hpll clock rate (which is
>> the hardcoded parent of vop0's dclk)
>> As discussed in Benjamin's initial submission of the addition of
>> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
>> needs a reference clock (it's called vpll there) which needs to get
>> switched before the vop switches the mode (since phy rate switching is
>> done before) - it's HPLL in case of RK356x. For whatever reason it's
>> called "ref" for RK356x only downstream [2] - so you should add another
>> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
>> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
> Yeah, a consumer clock should be named after the usage in the consumer,
> not after the provider name. I also stumbled over this and naming it
> "ref" makes much more sense. We'll likely have to keep supporting "vpll"
> as well for compatibility to old device trees.
>
>> What brings us to the "real" clock problem and the reason, why
>> non-integer divisable pixel clock rates are not possible ATM: This is a
>> long standing issue for RK3288 and RK3399 as well (and one of the main
>> reasons why 4k modes are not possible for those older SoCs currently):
>> Upstream all PLL rates are controlled with those PLL rate tables in the
>> clock driver and they have to be _exactly_ defined as they are used
>> (HDMI sinks are very picky).
>> You will not see any additional rates downstream for RK3568: they have a
>> mechanism there to automatically calculate the PLL settings if the rate
>> doesn't exist in these tables (IIRC this was submitted upstream also:
>> but it was rejected/ignored by maintainers).
> Looks like we have to try harder to get it upstream. Do you have a
> pointer to this patch?

Sure:

https://patchwork.kernel.org/project/linux-clk/patch/20191204082527.19957-1-zhangqing@rock-chips.com/

I don't know if that is the was last submitted version.

Best regards,

Alex

>> As a quick hackarround (for
>> testing): You could use this table [3] we are using in LibreElec for
>> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
>> driver (I tested it and it works great). It might be possible to just
>> add those rates (some also without frac dividers) to the common PLL
>> table for RK3568.
> Thanks for noting. This could also explain why currently only 1080p is
> working.
>
> Sascha
>

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 17:47       ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-22 17:47 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

Am 22.11.21 um 09:10 schrieb Sascha Hauer:
> Hi Alex,
>
> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>> Hi Sascha,
>>
>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>> This series adds initial graphics support for the Rockchip RK356[68]
>>> SoCs.  Graphics support is based around the VOP2 controller which
>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>> has been tested with HDMI support included in this series and MIPI-DSI
>>> which is not included because it needs some more work. The driver is
>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>> standard features have been removed for now. I tested the driver with
>>> the libdrm modetest utility and also with weston with both pixman and
>>> panfrost driver support. Michael Riesch reported the driver to work on
>>> the RK3566 as well, but device tree support for this SoC is not yet
>>> included in this series.
>>>
>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>> needs one additional clock, not two. Also I added regulator support
>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>
>>> All review and testing feedback welcome
>>
>> thanks for working on that - it's very (very,very) much appreciated.
>>
>> It took me some time to figure it out: It seems rk3568-iommu driver s
>> broken - I did only get "white noise" when using it alongside vop
>> (similar like it was reported here before). However: removing the
>> iommu-property from vop makes it working for me with HDMI output on
>> quartz64 as well. Could you check if you have the iommu driver in kernel
>> enabled if it works for you, if the property is present in DT? (I used
>> 5.16-rc1 + this series + [0]).
> I have the iommu driver enabled and it works for me. I get this during
> boot:
>
> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>
> So I expect it is indeed used.
>
>> Also vop mmu seems to have the
>> power-domain missing in your series (same as downstream) - however
>> adding that doesn't help much currently.
> Probably the power domain gets enabled anyway when the VOP is activated,
> so adding it to the iommu won't help anything. Nevertheless it seems
> correct to add the property, I'll do so in the next round.
>
>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>> RK356x: It did only work when removing the iommu there as well (getting
>> tons of page faults otherwise) - so iommu driver really seems to broken,
>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>> wasn't required for the older iommu version?)
> I don't think so. I started from defconfig and disabled other
> architectures and unneeded drivers, but I did not enable anything
> specific to iommu.

I've found out now that I can make it work with iommu, by limiting the
available memory to something below 4G (I have a 8G board). So there is
something wrong in the driver or somewhere in memory mapping, iommu api
(since it works when using CMA), ... however: it does clearly not relate
to your patch.

>>  
>> But as reported before: For HDMI this does currently only work for pixel
>> clock rates, which are integer-divisable with hpll clock rate (which is
>> the hardcoded parent of vop0's dclk)
>> As discussed in Benjamin's initial submission of the addition of
>> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
>> needs a reference clock (it's called vpll there) which needs to get
>> switched before the vop switches the mode (since phy rate switching is
>> done before) - it's HPLL in case of RK356x. For whatever reason it's
>> called "ref" for RK356x only downstream [2] - so you should add another
>> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
>> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
> Yeah, a consumer clock should be named after the usage in the consumer,
> not after the provider name. I also stumbled over this and naming it
> "ref" makes much more sense. We'll likely have to keep supporting "vpll"
> as well for compatibility to old device trees.
>
>> What brings us to the "real" clock problem and the reason, why
>> non-integer divisable pixel clock rates are not possible ATM: This is a
>> long standing issue for RK3288 and RK3399 as well (and one of the main
>> reasons why 4k modes are not possible for those older SoCs currently):
>> Upstream all PLL rates are controlled with those PLL rate tables in the
>> clock driver and they have to be _exactly_ defined as they are used
>> (HDMI sinks are very picky).
>> You will not see any additional rates downstream for RK3568: they have a
>> mechanism there to automatically calculate the PLL settings if the rate
>> doesn't exist in these tables (IIRC this was submitted upstream also:
>> but it was rejected/ignored by maintainers).
> Looks like we have to try harder to get it upstream. Do you have a
> pointer to this patch?

Sure:

https://patchwork.kernel.org/project/linux-clk/patch/20191204082527.19957-1-zhangqing@rock-chips.com/

I don't know if that is the was last submitted version.

Best regards,

Alex

>> As a quick hackarround (for
>> testing): You could use this table [3] we are using in LibreElec for
>> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
>> driver (I tested it and it works great). It might be possible to just
>> add those rates (some also without frac dividers) to the common PLL
>> table for RK3568.
> Thanks for noting. This could also explain why currently only 1080p is
> working.
>
> Sascha
>

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 17:47       ` Alex Bee
  0 siblings, 0 replies; 201+ messages in thread
From: Alex Bee @ 2021-11-22 17:47 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Am 22.11.21 um 09:10 schrieb Sascha Hauer:
> Hi Alex,
>
> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>> Hi Sascha,
>>
>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>> This series adds initial graphics support for the Rockchip RK356[68]
>>> SoCs.  Graphics support is based around the VOP2 controller which
>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>> has been tested with HDMI support included in this series and MIPI-DSI
>>> which is not included because it needs some more work. The driver is
>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>> standard features have been removed for now. I tested the driver with
>>> the libdrm modetest utility and also with weston with both pixman and
>>> panfrost driver support. Michael Riesch reported the driver to work on
>>> the RK3566 as well, but device tree support for this SoC is not yet
>>> included in this series.
>>>
>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>> needs one additional clock, not two. Also I added regulator support
>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>
>>> All review and testing feedback welcome
>>
>> thanks for working on that - it's very (very,very) much appreciated.
>>
>> It took me some time to figure it out: It seems rk3568-iommu driver s
>> broken - I did only get "white noise" when using it alongside vop
>> (similar like it was reported here before). However: removing the
>> iommu-property from vop makes it working for me with HDMI output on
>> quartz64 as well. Could you check if you have the iommu driver in kernel
>> enabled if it works for you, if the property is present in DT? (I used
>> 5.16-rc1 + this series + [0]).
> I have the iommu driver enabled and it works for me. I get this during
> boot:
>
> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>
> So I expect it is indeed used.
>
>> Also vop mmu seems to have the
>> power-domain missing in your series (same as downstream) - however
>> adding that doesn't help much currently.
> Probably the power domain gets enabled anyway when the VOP is activated,
> so adding it to the iommu won't help anything. Nevertheless it seems
> correct to add the property, I'll do so in the next round.
>
>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>> RK356x: It did only work when removing the iommu there as well (getting
>> tons of page faults otherwise) - so iommu driver really seems to broken,
>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>> wasn't required for the older iommu version?)
> I don't think so. I started from defconfig and disabled other
> architectures and unneeded drivers, but I did not enable anything
> specific to iommu.

I've found out now that I can make it work with iommu, by limiting the
available memory to something below 4G (I have a 8G board). So there is
something wrong in the driver or somewhere in memory mapping, iommu api
(since it works when using CMA), ... however: it does clearly not relate
to your patch.

>>  
>> But as reported before: For HDMI this does currently only work for pixel
>> clock rates, which are integer-divisable with hpll clock rate (which is
>> the hardcoded parent of vop0's dclk)
>> As discussed in Benjamin's initial submission of the addition of
>> RK3568's hdmi controller [1] same as with RK3288's and RK3399's hdmi phy
>> needs a reference clock (it's called vpll there) which needs to get
>> switched before the vop switches the mode (since phy rate switching is
>> done before) - it's HPLL in case of RK356x. For whatever reason it's
>> called "ref" for RK356x only downstream [2] - so you should add another
>> clock "vpll" (renaming it to "ref" for _ALL_ SoCs which have it would be
>> a _GREAT_ idea) which is <&pmucru PLL_HPLL>.
> Yeah, a consumer clock should be named after the usage in the consumer,
> not after the provider name. I also stumbled over this and naming it
> "ref" makes much more sense. We'll likely have to keep supporting "vpll"
> as well for compatibility to old device trees.
>
>> What brings us to the "real" clock problem and the reason, why
>> non-integer divisable pixel clock rates are not possible ATM: This is a
>> long standing issue for RK3288 and RK3399 as well (and one of the main
>> reasons why 4k modes are not possible for those older SoCs currently):
>> Upstream all PLL rates are controlled with those PLL rate tables in the
>> clock driver and they have to be _exactly_ defined as they are used
>> (HDMI sinks are very picky).
>> You will not see any additional rates downstream for RK3568: they have a
>> mechanism there to automatically calculate the PLL settings if the rate
>> doesn't exist in these tables (IIRC this was submitted upstream also:
>> but it was rejected/ignored by maintainers).
> Looks like we have to try harder to get it upstream. Do you have a
> pointer to this patch?

Sure:

https://patchwork.kernel.org/project/linux-clk/patch/20191204082527.19957-1-zhangqing@rock-chips.com/

I don't know if that is the was last submitted version.

Best regards,

Alex

>> As a quick hackarround (for
>> testing): You could use this table [3] we are using in LibreElec for
>> RK3399 to get 4k modes working and assign it to HPLL in RK3568's clock
>> driver (I tested it and it works great). It might be possible to just
>> add those rates (some also without frac dividers) to the common PLL
>> table for RK3568.
> Thanks for noting. This could also explain why currently only 1080p is
> working.
>
> Sascha
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
  2021-11-22 17:47       ` Alex Bee
  (?)
  (?)
@ 2021-11-22 19:21         ` Robin Murphy
  -1 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-11-22 19:21 UTC (permalink / raw)
  To: Alex Bee, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-22 17:47, Alex Bee wrote:
> Am 22.11.21 um 09:10 schrieb Sascha Hauer:
>> Hi Alex,
>>
>> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>>> Hi Sascha,
>>>
>>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>>> This series adds initial graphics support for the Rockchip RK356[68]
>>>> SoCs.  Graphics support is based around the VOP2 controller which
>>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>>> has been tested with HDMI support included in this series and MIPI-DSI
>>>> which is not included because it needs some more work. The driver is
>>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>>> standard features have been removed for now. I tested the driver with
>>>> the libdrm modetest utility and also with weston with both pixman and
>>>> panfrost driver support. Michael Riesch reported the driver to work on
>>>> the RK3566 as well, but device tree support for this SoC is not yet
>>>> included in this series.
>>>>
>>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>>> needs one additional clock, not two. Also I added regulator support
>>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>>
>>>> All review and testing feedback welcome
>>>
>>> thanks for working on that - it's very (very,very) much appreciated.
>>>
>>> It took me some time to figure it out: It seems rk3568-iommu driver s
>>> broken - I did only get "white noise" when using it alongside vop
>>> (similar like it was reported here before). However: removing the
>>> iommu-property from vop makes it working for me with HDMI output on
>>> quartz64 as well. Could you check if you have the iommu driver in kernel
>>> enabled if it works for you, if the property is present in DT? (I used
>>> 5.16-rc1 + this series + [0]).
>> I have the iommu driver enabled and it works for me. I get this during
>> boot:
>>
>> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>>
>> So I expect it is indeed used.
>>
>>> Also vop mmu seems to have the
>>> power-domain missing in your series (same as downstream) - however
>>> adding that doesn't help much currently.
>> Probably the power domain gets enabled anyway when the VOP is activated,
>> so adding it to the iommu won't help anything. Nevertheless it seems
>> correct to add the property, I'll do so in the next round.
>>
>>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>>> RK356x: It did only work when removing the iommu there as well (getting
>>> tons of page faults otherwise) - so iommu driver really seems to broken,
>>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>>> wasn't required for the older iommu version?)
>> I don't think so. I started from defconfig and disabled other
>> architectures and unneeded drivers, but I did not enable anything
>> specific to iommu.
> 
> I've found out now that I can make it work with iommu, by limiting the
> available memory to something below 4G (I have a 8G board). So there is
> something wrong in the driver or somewhere in memory mapping, iommu api
> (since it works when using CMA), ... however: it does clearly not relate
> to your patch.

FWIW it doesn't surprise me that there might still be bugs lurking in 
the IOMMU driver's relatively recent changes for packing 40-bit physical 
addresses into 32-bit pagetable entries and registers - that sort of 
thing is always tricky to get right. You're correct that that's 
something that wants debugging in its own right, though.

Robin.

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 19:21         ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-11-22 19:21 UTC (permalink / raw)
  To: Alex Bee, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-22 17:47, Alex Bee wrote:
> Am 22.11.21 um 09:10 schrieb Sascha Hauer:
>> Hi Alex,
>>
>> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>>> Hi Sascha,
>>>
>>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>>> This series adds initial graphics support for the Rockchip RK356[68]
>>>> SoCs.  Graphics support is based around the VOP2 controller which
>>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>>> has been tested with HDMI support included in this series and MIPI-DSI
>>>> which is not included because it needs some more work. The driver is
>>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>>> standard features have been removed for now. I tested the driver with
>>>> the libdrm modetest utility and also with weston with both pixman and
>>>> panfrost driver support. Michael Riesch reported the driver to work on
>>>> the RK3566 as well, but device tree support for this SoC is not yet
>>>> included in this series.
>>>>
>>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>>> needs one additional clock, not two. Also I added regulator support
>>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>>
>>>> All review and testing feedback welcome
>>>
>>> thanks for working on that - it's very (very,very) much appreciated.
>>>
>>> It took me some time to figure it out: It seems rk3568-iommu driver s
>>> broken - I did only get "white noise" when using it alongside vop
>>> (similar like it was reported here before). However: removing the
>>> iommu-property from vop makes it working for me with HDMI output on
>>> quartz64 as well. Could you check if you have the iommu driver in kernel
>>> enabled if it works for you, if the property is present in DT? (I used
>>> 5.16-rc1 + this series + [0]).
>> I have the iommu driver enabled and it works for me. I get this during
>> boot:
>>
>> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>>
>> So I expect it is indeed used.
>>
>>> Also vop mmu seems to have the
>>> power-domain missing in your series (same as downstream) - however
>>> adding that doesn't help much currently.
>> Probably the power domain gets enabled anyway when the VOP is activated,
>> so adding it to the iommu won't help anything. Nevertheless it seems
>> correct to add the property, I'll do so in the next round.
>>
>>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>>> RK356x: It did only work when removing the iommu there as well (getting
>>> tons of page faults otherwise) - so iommu driver really seems to broken,
>>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>>> wasn't required for the older iommu version?)
>> I don't think so. I started from defconfig and disabled other
>> architectures and unneeded drivers, but I did not enable anything
>> specific to iommu.
> 
> I've found out now that I can make it work with iommu, by limiting the
> available memory to something below 4G (I have a 8G board). So there is
> something wrong in the driver or somewhere in memory mapping, iommu api
> (since it works when using CMA), ... however: it does clearly not relate
> to your patch.

FWIW it doesn't surprise me that there might still be bugs lurking in 
the IOMMU driver's relatively recent changes for packing 40-bit physical 
addresses into 32-bit pagetable entries and registers - that sort of 
thing is always tricky to get right. You're correct that that's 
something that wants debugging in its own right, though.

Robin.

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 19:21         ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-11-22 19:21 UTC (permalink / raw)
  To: Alex Bee, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

On 2021-11-22 17:47, Alex Bee wrote:
> Am 22.11.21 um 09:10 schrieb Sascha Hauer:
>> Hi Alex,
>>
>> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>>> Hi Sascha,
>>>
>>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>>> This series adds initial graphics support for the Rockchip RK356[68]
>>>> SoCs.  Graphics support is based around the VOP2 controller which
>>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>>> has been tested with HDMI support included in this series and MIPI-DSI
>>>> which is not included because it needs some more work. The driver is
>>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>>> standard features have been removed for now. I tested the driver with
>>>> the libdrm modetest utility and also with weston with both pixman and
>>>> panfrost driver support. Michael Riesch reported the driver to work on
>>>> the RK3566 as well, but device tree support for this SoC is not yet
>>>> included in this series.
>>>>
>>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>>> needs one additional clock, not two. Also I added regulator support
>>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>>
>>>> All review and testing feedback welcome
>>>
>>> thanks for working on that - it's very (very,very) much appreciated.
>>>
>>> It took me some time to figure it out: It seems rk3568-iommu driver s
>>> broken - I did only get "white noise" when using it alongside vop
>>> (similar like it was reported here before). However: removing the
>>> iommu-property from vop makes it working for me with HDMI output on
>>> quartz64 as well. Could you check if you have the iommu driver in kernel
>>> enabled if it works for you, if the property is present in DT? (I used
>>> 5.16-rc1 + this series + [0]).
>> I have the iommu driver enabled and it works for me. I get this during
>> boot:
>>
>> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>>
>> So I expect it is indeed used.
>>
>>> Also vop mmu seems to have the
>>> power-domain missing in your series (same as downstream) - however
>>> adding that doesn't help much currently.
>> Probably the power domain gets enabled anyway when the VOP is activated,
>> so adding it to the iommu won't help anything. Nevertheless it seems
>> correct to add the property, I'll do so in the next round.
>>
>>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>>> RK356x: It did only work when removing the iommu there as well (getting
>>> tons of page faults otherwise) - so iommu driver really seems to broken,
>>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>>> wasn't required for the older iommu version?)
>> I don't think so. I started from defconfig and disabled other
>> architectures and unneeded drivers, but I did not enable anything
>> specific to iommu.
> 
> I've found out now that I can make it work with iommu, by limiting the
> available memory to something below 4G (I have a 8G board). So there is
> something wrong in the driver or somewhere in memory mapping, iommu api
> (since it works when using CMA), ... however: it does clearly not relate
> to your patch.

FWIW it doesn't surprise me that there might still be bugs lurking in 
the IOMMU driver's relatively recent changes for packing 40-bit physical 
addresses into 32-bit pagetable entries and registers - that sort of 
thing is always tricky to get right. You're correct that that's 
something that wants debugging in its own right, though.

Robin.

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support
@ 2021-11-22 19:21         ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-11-22 19:21 UTC (permalink / raw)
  To: Alex Bee, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-22 17:47, Alex Bee wrote:
> Am 22.11.21 um 09:10 schrieb Sascha Hauer:
>> Hi Alex,
>>
>> On Mon, Nov 22, 2021 at 12:18:47AM +0100, Alex Bee wrote:
>>> Hi Sascha,
>>>
>>> Am 17.11.21 um 15:33 schrieb Sascha Hauer:
>>>> This series adds initial graphics support for the Rockchip RK356[68]
>>>> SoCs.  Graphics support is based around the VOP2 controller which
>>>> replaces the VOP controller found on earlier Rockchip SoCs. The driver
>>>> has been tested with HDMI support included in this series and MIPI-DSI
>>>> which is not included because it needs some more work. The driver is
>>>> taken from the downstream Rockchip kernel and heavily polished, most non
>>>> standard features have been removed for now. I tested the driver with
>>>> the libdrm modetest utility and also with weston with both pixman and
>>>> panfrost driver support. Michael Riesch reported the driver to work on
>>>> the RK3566 as well, but device tree support for this SoC is not yet
>>>> included in this series.
>>>>
>>>> The HDMI changes are based on patches from Benjamin Gaignard, but
>>>> modified a bit as I found out that the HDMI port on the RK3568 only
>>>> needs one additional clock, not two. Also I added regulator support
>>>> which is needed to get the HDMI up on the rk3568-EVB board.
>>>>
>>>> All review and testing feedback welcome
>>>
>>> thanks for working on that - it's very (very,very) much appreciated.
>>>
>>> It took me some time to figure it out: It seems rk3568-iommu driver s
>>> broken - I did only get "white noise" when using it alongside vop
>>> (similar like it was reported here before). However: removing the
>>> iommu-property from vop makes it working for me with HDMI output on
>>> quartz64 as well. Could you check if you have the iommu driver in kernel
>>> enabled if it works for you, if the property is present in DT? (I used
>>> 5.16-rc1 + this series + [0]).
>> I have the iommu driver enabled and it works for me. I get this during
>> boot:
>>
>> [0.263287] rockchip-vop2 fe040000.vop: Adding to iommu group 0
>>
>> So I expect it is indeed used.
>>
>>> Also vop mmu seems to have the
>>> power-domain missing in your series (same as downstream) - however
>>> adding that doesn't help much currently.
>> Probably the power domain gets enabled anyway when the VOP is activated,
>> so adding it to the iommu won't help anything. Nevertheless it seems
>> correct to add the property, I'll do so in the next round.
>>
>>> As a sidenote: I verfied this with using Ezequiel's vpu addtion for
>>> RK356x: It did only work when removing the iommu there as well (getting
>>> tons of page faults otherwise) - so iommu driver really seems to broken,
>>> at least for RK3566. (Or I'm a missing a option in kernel config, which
>>> wasn't required for the older iommu version?)
>> I don't think so. I started from defconfig and disabled other
>> architectures and unneeded drivers, but I did not enable anything
>> specific to iommu.
> 
> I've found out now that I can make it work with iommu, by limiting the
> available memory to something below 4G (I have a 8G board). So there is
> something wrong in the driver or somewhere in memory mapping, iommu api
> (since it works when using CMA), ... however: it does clearly not relate
> to your patch.

FWIW it doesn't surprise me that there might still be bugs lurking in 
the IOMMU driver's relatively recent changes for packing 40-bit physical 
addresses into 32-bit pagetable entries and registers - that sort of 
thing is always tricky to get right. You're correct that that's 
something that wants debugging in its own right, though.

Robin.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
  2021-11-17 15:44     ` Michael Riesch
  (?)
  (?)
@ 2021-11-25 19:44       ` Johan Jonker
  -1 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 19:44 UTC (permalink / raw)
  To: Michael Riesch, dri-devel, devicetree, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout



On 11/17/21 4:44 PM, Michael Riesch wrote:
> Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
> Quartz64 Model A.
> 
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> ---
>  .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> index 4d4b2a301b1a..9fba790c6af4 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> @@ -205,6 +205,16 @@ &gmac1m0_clkinout
>  	status = "okay";
>  };
>  
> +&hdmi {

> +	status = "okay";
> +	avdd-0v9-supply = <&vdda_0v9>;
> +	avdd-1v8-supply = <&vcc_1v8>;

Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};
> +
>  &i2c0 {
>  	status = "okay";
>  
> @@ -546,3 +556,17 @@ bluetooth {
>  &uart2 {
>  	status = "okay";
>  };
> +
> +&vop {

> +	status = "okay";

status below

> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-25 19:44       ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 19:44 UTC (permalink / raw)
  To: Michael Riesch, dri-devel, devicetree, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, pgwipeout



On 11/17/21 4:44 PM, Michael Riesch wrote:
> Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
> Quartz64 Model A.
> 
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> ---
>  .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> index 4d4b2a301b1a..9fba790c6af4 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> @@ -205,6 +205,16 @@ &gmac1m0_clkinout
>  	status = "okay";
>  };
>  
> +&hdmi {

> +	status = "okay";
> +	avdd-0v9-supply = <&vdda_0v9>;
> +	avdd-1v8-supply = <&vcc_1v8>;

Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};
> +
>  &i2c0 {
>  	status = "okay";
>  
> @@ -546,3 +556,17 @@ bluetooth {
>  &uart2 {
>  	status = "okay";
>  };
> +
> +&vop {

> +	status = "okay";

status below

> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-25 19:44       ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 19:44 UTC (permalink / raw)
  To: Michael Riesch, dri-devel, devicetree, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout



On 11/17/21 4:44 PM, Michael Riesch wrote:
> Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
> Quartz64 Model A.
> 
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> ---
>  .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> index 4d4b2a301b1a..9fba790c6af4 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> @@ -205,6 +205,16 @@ &gmac1m0_clkinout
>  	status = "okay";
>  };
>  
> +&hdmi {

> +	status = "okay";
> +	avdd-0v9-supply = <&vdda_0v9>;
> +	avdd-1v8-supply = <&vcc_1v8>;

Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};
> +
>  &i2c0 {
>  	status = "okay";
>  
> @@ -546,3 +556,17 @@ bluetooth {
>  &uart2 {
>  	status = "okay";
>  };
> +
> +&vop {

> +	status = "okay";

status below

> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a
@ 2021-11-25 19:44       ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 19:44 UTC (permalink / raw)
  To: Michael Riesch, dri-devel, devicetree, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: s.hauer, benjamin.gaignard, hjc, heiko, pgwipeout



On 11/17/21 4:44 PM, Michael Riesch wrote:
> Enable the RK356x Video Output Processor (VOP) 2 on the Pine64
> Quartz64 Model A.
> 
> Signed-off-by: Michael Riesch <michael.riesch@wolfvision.net>
> ---
>  .../boot/dts/rockchip/rk3566-quartz64-a.dts   | 24 +++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> index 4d4b2a301b1a..9fba790c6af4 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts
> @@ -205,6 +205,16 @@ &gmac1m0_clkinout
>  	status = "okay";
>  };
>  
> +&hdmi {

> +	status = "okay";
> +	avdd-0v9-supply = <&vdda_0v9>;
> +	avdd-1v8-supply = <&vcc_1v8>;

Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +};
> +
> +&hdmi_in_vp0 {
> +	status = "okay";
> +};
> +
>  &i2c0 {
>  	status = "okay";
>  
> @@ -546,3 +556,17 @@ bluetooth {
>  &uart2 {
>  	status = "okay";
>  };
> +
> +&vop {

> +	status = "okay";

status below

> +	assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> +	assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> +};
> +
> +&vop_mmu {
> +	status = "okay";
> +};
> +
> +&vp0_out_hdmi {
> +	status = "okay";
> +};
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-25 20:25     ` Johan Jonker
  -1 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 20:25 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,


On 11/17/21 3:33 PM, Sascha Hauer wrote:
> The VOP2 is the display output controller on the RK3568. Add the node
> for it to the dtsi file along with the required display-subsystem node
> and the iommu node.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 46d9552f60284..6ebf7c14e096a 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
>  		};
>  	};
>  

> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vop_out>;
> +	};

Some DT sort rules:

For nodes:
Sort things without reg alphabetical first,
then sort the rest by reg address.

> +
> +	vop: vop@fe040000 {

> +		compatible = "rockchip,rk3568-vop";

From rockchip-vop2.yaml:
+properties:
+  compatible:
+    enum:

+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop

Maybe sort yaml compatibles in alphabetical order.

rockchip,rk3566-vop is not used in the dtsi I think.

Comment by Andy Yan:
> 
> But take care that the vop on rk3566 has a special limitation: there are 
> three
> 
> windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> 
> can't be programed framebuffer address independently , they can only
> 
> share framebuffer address with Cluster0/Esmart0/Smart0.

Question:
Given Andy's comment could someone explain weather the vop and hdmi
nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
rockchip,rk3566-dw-hdmi compatible?

> +		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
> +		reg-names = "regs", "gamma_lut";

> +		rockchip,grf = <&grf>;
Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
> +		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
> +		iommus = <&vop_mmu>;
> +		power-domains = <&power RK3568_PD_VO>;
> +		status = "disabled";
> +
> +		vop_out: ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			vp0: port@0 {

> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0>;

My incomplete list:

Inside nodes:
If exists on top: compatible, reg and interrupts.
In alphabetical order the required properties.
Then in alphabetical order the other properties.
And as last things that start with '#' in alphabetical order.
Add status below all other properties for soc internal components with
any board-specifics.

> +			};
> +
> +			vp1: port@1 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <1>;
> +			};
> +
> +			vp2: port@2 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <2>;
> +			};
> +		};
> +	};
> +
> +	vop_mmu: iommu@fe043e00 {
> +		compatible = "rockchip,rk3568-iommu";
> +		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;

> +		interrupt-names = "vop_mmu";

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make dtbs_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dt.yaml: iommu@fe043e00:
'interrupt-names' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
> +		clock-names = "aclk", "iface";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	qos_gpu: qos@fe128000 {
>  		compatible = "rockchip,rk3568-qos", "syscon";
>  		reg = <0x0 0xfe128000 0x0 0x20>;
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-25 20:25     ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 20:25 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, Peter Geis, linux-arm-kernel

Hi Sascha,


On 11/17/21 3:33 PM, Sascha Hauer wrote:
> The VOP2 is the display output controller on the RK3568. Add the node
> for it to the dtsi file along with the required display-subsystem node
> and the iommu node.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 46d9552f60284..6ebf7c14e096a 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
>  		};
>  	};
>  

> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vop_out>;
> +	};

Some DT sort rules:

For nodes:
Sort things without reg alphabetical first,
then sort the rest by reg address.

> +
> +	vop: vop@fe040000 {

> +		compatible = "rockchip,rk3568-vop";

From rockchip-vop2.yaml:
+properties:
+  compatible:
+    enum:

+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop

Maybe sort yaml compatibles in alphabetical order.

rockchip,rk3566-vop is not used in the dtsi I think.

Comment by Andy Yan:
> 
> But take care that the vop on rk3566 has a special limitation: there are 
> three
> 
> windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> 
> can't be programed framebuffer address independently , they can only
> 
> share framebuffer address with Cluster0/Esmart0/Smart0.

Question:
Given Andy's comment could someone explain weather the vop and hdmi
nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
rockchip,rk3566-dw-hdmi compatible?

> +		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
> +		reg-names = "regs", "gamma_lut";

> +		rockchip,grf = <&grf>;
Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
> +		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
> +		iommus = <&vop_mmu>;
> +		power-domains = <&power RK3568_PD_VO>;
> +		status = "disabled";
> +
> +		vop_out: ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			vp0: port@0 {

> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0>;

My incomplete list:

Inside nodes:
If exists on top: compatible, reg and interrupts.
In alphabetical order the required properties.
Then in alphabetical order the other properties.
And as last things that start with '#' in alphabetical order.
Add status below all other properties for soc internal components with
any board-specifics.

> +			};
> +
> +			vp1: port@1 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <1>;
> +			};
> +
> +			vp2: port@2 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <2>;
> +			};
> +		};
> +	};
> +
> +	vop_mmu: iommu@fe043e00 {
> +		compatible = "rockchip,rk3568-iommu";
> +		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;

> +		interrupt-names = "vop_mmu";

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make dtbs_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dt.yaml: iommu@fe043e00:
'interrupt-names' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
> +		clock-names = "aclk", "iface";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	qos_gpu: qos@fe128000 {
>  		compatible = "rockchip,rk3568-qos", "syscon";
>  		reg = <0x0 0xfe128000 0x0 0x20>;
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-25 20:25     ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 20:25 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,


On 11/17/21 3:33 PM, Sascha Hauer wrote:
> The VOP2 is the display output controller on the RK3568. Add the node
> for it to the dtsi file along with the required display-subsystem node
> and the iommu node.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 46d9552f60284..6ebf7c14e096a 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
>  		};
>  	};
>  

> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vop_out>;
> +	};

Some DT sort rules:

For nodes:
Sort things without reg alphabetical first,
then sort the rest by reg address.

> +
> +	vop: vop@fe040000 {

> +		compatible = "rockchip,rk3568-vop";

From rockchip-vop2.yaml:
+properties:
+  compatible:
+    enum:

+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop

Maybe sort yaml compatibles in alphabetical order.

rockchip,rk3566-vop is not used in the dtsi I think.

Comment by Andy Yan:
> 
> But take care that the vop on rk3566 has a special limitation: there are 
> three
> 
> windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> 
> can't be programed framebuffer address independently , they can only
> 
> share framebuffer address with Cluster0/Esmart0/Smart0.

Question:
Given Andy's comment could someone explain weather the vop and hdmi
nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
rockchip,rk3566-dw-hdmi compatible?

> +		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
> +		reg-names = "regs", "gamma_lut";

> +		rockchip,grf = <&grf>;
Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
> +		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
> +		iommus = <&vop_mmu>;
> +		power-domains = <&power RK3568_PD_VO>;
> +		status = "disabled";
> +
> +		vop_out: ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			vp0: port@0 {

> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0>;

My incomplete list:

Inside nodes:
If exists on top: compatible, reg and interrupts.
In alphabetical order the required properties.
Then in alphabetical order the other properties.
And as last things that start with '#' in alphabetical order.
Add status below all other properties for soc internal components with
any board-specifics.

> +			};
> +
> +			vp1: port@1 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <1>;
> +			};
> +
> +			vp2: port@2 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <2>;
> +			};
> +		};
> +	};
> +
> +	vop_mmu: iommu@fe043e00 {
> +		compatible = "rockchip,rk3568-iommu";
> +		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;

> +		interrupt-names = "vop_mmu";

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make dtbs_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dt.yaml: iommu@fe043e00:
'interrupt-names' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
> +		clock-names = "aclk", "iface";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	qos_gpu: qos@fe128000 {
>  		compatible = "rockchip,rk3568-qos", "syscon";
>  		reg = <0x0 0xfe128000 0x0 0x20>;
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-25 20:25     ` Johan Jonker
  0 siblings, 0 replies; 201+ messages in thread
From: Johan Jonker @ 2021-11-25 20:25 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,


On 11/17/21 3:33 PM, Sascha Hauer wrote:
> The VOP2 is the display output controller on the RK3568. Add the node
> for it to the dtsi file along with the required display-subsystem node
> and the iommu node.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> index 46d9552f60284..6ebf7c14e096a 100644
> --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
>  		};
>  	};
>  

> +	display_subsystem: display-subsystem {
> +		compatible = "rockchip,display-subsystem";
> +		ports = <&vop_out>;
> +	};

Some DT sort rules:

For nodes:
Sort things without reg alphabetical first,
then sort the rest by reg address.

> +
> +	vop: vop@fe040000 {

> +		compatible = "rockchip,rk3568-vop";

From rockchip-vop2.yaml:
+properties:
+  compatible:
+    enum:

+      - rockchip,rk3568-vop
+      - rockchip,rk3566-vop

Maybe sort yaml compatibles in alphabetical order.

rockchip,rk3566-vop is not used in the dtsi I think.

Comment by Andy Yan:
> 
> But take care that the vop on rk3566 has a special limitation: there are 
> three
> 
> windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> 
> can't be programed framebuffer address independently , they can only
> 
> share framebuffer address with Cluster0/Esmart0/Smart0.

Question:
Given Andy's comment could someone explain weather the vop and hdmi
nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
rockchip,rk3566-dw-hdmi compatible?

> +		reg = <0x0 0xfe040000 0x0 0x3000>, <0x0 0xfe044000 0x0 0x1000>;
> +		reg-names = "regs", "gamma_lut";

> +		rockchip,grf = <&grf>;
Heiko's sort rules:

compatible
reg
interrupts
[alphabetical]
status [if needed]

> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>, <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
> +		clock-names = "aclk_vop", "hclk_vop", "dclk_vp0", "dclk_vp1", "dclk_vp2";
> +		iommus = <&vop_mmu>;
> +		power-domains = <&power RK3568_PD_VO>;
> +		status = "disabled";
> +
> +		vop_out: ports {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +
> +			vp0: port@0 {

> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0>;

My incomplete list:

Inside nodes:
If exists on top: compatible, reg and interrupts.
In alphabetical order the required properties.
Then in alphabetical order the other properties.
And as last things that start with '#' in alphabetical order.
Add status below all other properties for soc internal components with
any board-specifics.

> +			};
> +
> +			vp1: port@1 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <1>;
> +			};
> +
> +			vp2: port@2 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <2>;
> +			};
> +		};
> +	};
> +
> +	vop_mmu: iommu@fe043e00 {
> +		compatible = "rockchip,rk3568-iommu";
> +		reg = <0x0 0xfe043e00 0x0 0x100>, <0x0 0xfe043f00 0x0 0x100>;
> +		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;

> +		interrupt-names = "vop_mmu";

ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make dtbs_check
DT_SCHEMA_FILES=Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dt.yaml: iommu@fe043e00:
'interrupt-names' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /Documentation/devicetree/bindings/iommu/rockchip,iommu.yaml

> +		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
> +		clock-names = "aclk", "iface";
> +		#iommu-cells = <0>;
> +		status = "disabled";
> +	};
> +
>  	qos_gpu: qos@fe128000 {
>  		compatible = "rockchip,rk3568-qos", "syscon";
>  		reg = <0x0 0xfe128000 0x0 0x20>;
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
  2021-11-17 14:33   ` Sascha Hauer
                       ` (2 preceding siblings ...)
  (?)
@ 2021-11-26  6:44     ` kernel test robot
  -1 siblings, 0 replies; 201+ messages in thread
From: kernel test robot @ 2021-11-26  6:44 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	linux-rockchip, Michael Riesch, kernel, kbuild-all,
	linux-arm-kernel

Hi Sascha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on drm/drm-next v5.16-rc2 next-20211125]
[cannot apply to arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20211126/202111261442.VG18rKq6-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
        git checkout f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/rockchip/rockchip_drm_vop2.c: In function 'vop2_setup_dly_for_window':
>> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c:2943:27: warning: variable 'plane' set but not used [-Wunused-but-set-variable]
    2943 |         struct drm_plane *plane;
         |                           ^~~~~


vim +/plane +2943 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

  2937	
  2938	static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
  2939					      int nr_layers)
  2940	{
  2941		struct vop2 *vop2 = vp->vop2;
  2942		const struct vop2_zpos *zpos;
> 2943		struct drm_plane *plane;
  2944		struct vop2_win *win;
  2945		uint32_t dly;
  2946		int i = 0;
  2947	
  2948		for (i = 0; i < nr_layers; i++) {
  2949			zpos = &vop2_zpos[i];
  2950			win = zpos->win;
  2951			plane = &win->base;
  2952			dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
  2953	
  2954			if (vop2_cluster_window(win))
  2955				dly |= dly << 8;
  2956	
  2957			vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
  2958		}
  2959	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-26  6:44     ` kernel test robot
  0 siblings, 0 replies; 201+ messages in thread
From: kernel test robot @ 2021-11-26  6:44 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: kbuild-all, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on drm/drm-next v5.16-rc2 next-20211125]
[cannot apply to arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20211126/202111261442.VG18rKq6-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
        git checkout f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/rockchip/rockchip_drm_vop2.c: In function 'vop2_setup_dly_for_window':
>> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c:2943:27: warning: variable 'plane' set but not used [-Wunused-but-set-variable]
    2943 |         struct drm_plane *plane;
         |                           ^~~~~


vim +/plane +2943 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

  2937	
  2938	static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
  2939					      int nr_layers)
  2940	{
  2941		struct vop2 *vop2 = vp->vop2;
  2942		const struct vop2_zpos *zpos;
> 2943		struct drm_plane *plane;
  2944		struct vop2_win *win;
  2945		uint32_t dly;
  2946		int i = 0;
  2947	
  2948		for (i = 0; i < nr_layers; i++) {
  2949			zpos = &vop2_zpos[i];
  2950			win = zpos->win;
  2951			plane = &win->base;
  2952			dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
  2953	
  2954			if (vop2_cluster_window(win))
  2955				dly |= dly << 8;
  2956	
  2957			vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
  2958		}
  2959	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-26  6:44     ` kernel test robot
  0 siblings, 0 replies; 201+ messages in thread
From: kernel test robot @ 2021-11-26  6:44 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: kbuild-all, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on drm/drm-next v5.16-rc2 next-20211125]
[cannot apply to arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20211126/202111261442.VG18rKq6-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
        git checkout f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/rockchip/rockchip_drm_vop2.c: In function 'vop2_setup_dly_for_window':
>> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c:2943:27: warning: variable 'plane' set but not used [-Wunused-but-set-variable]
    2943 |         struct drm_plane *plane;
         |                           ^~~~~


vim +/plane +2943 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

  2937	
  2938	static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
  2939					      int nr_layers)
  2940	{
  2941		struct vop2 *vop2 = vp->vop2;
  2942		const struct vop2_zpos *zpos;
> 2943		struct drm_plane *plane;
  2944		struct vop2_win *win;
  2945		uint32_t dly;
  2946		int i = 0;
  2947	
  2948		for (i = 0; i < nr_layers; i++) {
  2949			zpos = &vop2_zpos[i];
  2950			win = zpos->win;
  2951			plane = &win->base;
  2952			dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
  2953	
  2954			if (vop2_cluster_window(win))
  2955				dly |= dly << 8;
  2956	
  2957			vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
  2958		}
  2959	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-26  6:44     ` kernel test robot
  0 siblings, 0 replies; 201+ messages in thread
From: kernel test robot @ 2021-11-26  6:44 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: kbuild-all, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

Hi Sascha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on drm/drm-next v5.16-rc2 next-20211125]
[cannot apply to arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20211126/202111261442.VG18rKq6-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
        git checkout f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/rockchip/rockchip_drm_vop2.c: In function 'vop2_setup_dly_for_window':
>> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c:2943:27: warning: variable 'plane' set but not used [-Wunused-but-set-variable]
    2943 |         struct drm_plane *plane;
         |                           ^~~~~


vim +/plane +2943 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

  2937	
  2938	static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
  2939					      int nr_layers)
  2940	{
  2941		struct vop2 *vop2 = vp->vop2;
  2942		const struct vop2_zpos *zpos;
> 2943		struct drm_plane *plane;
  2944		struct vop2_win *win;
  2945		uint32_t dly;
  2946		int i = 0;
  2947	
  2948		for (i = 0; i < nr_layers; i++) {
  2949			zpos = &vop2_zpos[i];
  2950			win = zpos->win;
  2951			plane = &win->base;
  2952			dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
  2953	
  2954			if (vop2_cluster_window(win))
  2955				dly |= dly << 8;
  2956	
  2957			vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
  2958		}
  2959	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 12/12] drm: rockchip: Add VOP2 driver
@ 2021-11-26  6:44     ` kernel test robot
  0 siblings, 0 replies; 201+ messages in thread
From: kernel test robot @ 2021-11-26  6:44 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2802 bytes --]

Hi Sascha,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rockchip/for-next]
[also build test WARNING on drm/drm-next v5.16-rc2 next-20211125]
[cannot apply to arm64/for-next/core]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20211126/202111261442.VG18rKq6-lkp(a)intel.com/config)
compiler: mips-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Sascha-Hauer/drm-rockchip-RK356x-VOP2-support/20211117-223601
        git checkout f8c11ce8b4d254bb4824a87adbf9ed187a3c1178
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/rockchip/rockchip_drm_vop2.c: In function 'vop2_setup_dly_for_window':
>> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c:2943:27: warning: variable 'plane' set but not used [-Wunused-but-set-variable]
    2943 |         struct drm_plane *plane;
         |                           ^~~~~


vim +/plane +2943 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c

  2937	
  2938	static void vop2_setup_dly_for_window(struct vop2_video_port *vp, const struct vop2_zpos *vop2_zpos,
  2939					      int nr_layers)
  2940	{
  2941		struct vop2 *vop2 = vp->vop2;
  2942		const struct vop2_zpos *zpos;
> 2943		struct drm_plane *plane;
  2944		struct vop2_win *win;
  2945		uint32_t dly;
  2946		int i = 0;
  2947	
  2948		for (i = 0; i < nr_layers; i++) {
  2949			zpos = &vop2_zpos[i];
  2950			win = zpos->win;
  2951			plane = &win->base;
  2952			dly = win->data->dly[VOP2_DLY_MODE_DEFAULT];
  2953	
  2954			if (vop2_cluster_window(win))
  2955				dly |= dly << 8;
  2956	
  2957			vop2_write(vop2, &vop2->data->ctrl->win_dly[win->data->phys_id], dly);
  2958		}
  2959	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
  2021-11-25 20:25     ` Johan Jonker
  (?)
  (?)
@ 2021-11-26  7:40       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-26  7:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> Hi Sascha,
> 
> 
> On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > The VOP2 is the display output controller on the RK3568. Add the node
> > for it to the dtsi file along with the required display-subsystem node
> > and the iommu node.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 46d9552f60284..6ebf7c14e096a 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> >  		};
> >  	};
> >  
> 
> > +	display_subsystem: display-subsystem {
> > +		compatible = "rockchip,display-subsystem";
> > +		ports = <&vop_out>;
> > +	};
> 
> Some DT sort rules:
> 
> For nodes:
> Sort things without reg alphabetical first,
> then sort the rest by reg address.
> 
> > +
> > +	vop: vop@fe040000 {
> 
> > +		compatible = "rockchip,rk3568-vop";
> 
> From rockchip-vop2.yaml:
> +properties:
> +  compatible:
> +    enum:
> 
> +      - rockchip,rk3568-vop
> +      - rockchip,rk3566-vop
> 
> Maybe sort yaml compatibles in alphabetical order.
> 
> rockchip,rk3566-vop is not used in the dtsi I think.
> 
> Comment by Andy Yan:
> > 
> > But take care that the vop on rk3566 has a special limitation: there are 
> > three
> > 
> > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > 
> > can't be programed framebuffer address independently , they can only
> > 
> > share framebuffer address with Cluster0/Esmart0/Smart0.
> 
> Question:
> Given Andy's comment could someone explain weather the vop and hdmi
> nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> rockchip,rk3566-dw-hdmi compatible?

We could put the vop/hdmi nodes into rk356x.dtsi and just add the
compatible properties to rk3566.dtsi and rk3568.dtsi.
We'll need the exact SoC type, besides the mirror lock thingy there are a
few other minor differences between the SoCs.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  7:40       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-26  7:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> Hi Sascha,
> 
> 
> On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > The VOP2 is the display output controller on the RK3568. Add the node
> > for it to the dtsi file along with the required display-subsystem node
> > and the iommu node.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 46d9552f60284..6ebf7c14e096a 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> >  		};
> >  	};
> >  
> 
> > +	display_subsystem: display-subsystem {
> > +		compatible = "rockchip,display-subsystem";
> > +		ports = <&vop_out>;
> > +	};
> 
> Some DT sort rules:
> 
> For nodes:
> Sort things without reg alphabetical first,
> then sort the rest by reg address.
> 
> > +
> > +	vop: vop@fe040000 {
> 
> > +		compatible = "rockchip,rk3568-vop";
> 
> From rockchip-vop2.yaml:
> +properties:
> +  compatible:
> +    enum:
> 
> +      - rockchip,rk3568-vop
> +      - rockchip,rk3566-vop
> 
> Maybe sort yaml compatibles in alphabetical order.
> 
> rockchip,rk3566-vop is not used in the dtsi I think.
> 
> Comment by Andy Yan:
> > 
> > But take care that the vop on rk3566 has a special limitation: there are 
> > three
> > 
> > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > 
> > can't be programed framebuffer address independently , they can only
> > 
> > share framebuffer address with Cluster0/Esmart0/Smart0.
> 
> Question:
> Given Andy's comment could someone explain weather the vop and hdmi
> nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> rockchip,rk3566-dw-hdmi compatible?

We could put the vop/hdmi nodes into rk356x.dtsi and just add the
compatible properties to rk3566.dtsi and rk3568.dtsi.
We'll need the exact SoC type, besides the mirror lock thingy there are a
few other minor differences between the SoCs.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  7:40       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-26  7:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> Hi Sascha,
> 
> 
> On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > The VOP2 is the display output controller on the RK3568. Add the node
> > for it to the dtsi file along with the required display-subsystem node
> > and the iommu node.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 46d9552f60284..6ebf7c14e096a 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> >  		};
> >  	};
> >  
> 
> > +	display_subsystem: display-subsystem {
> > +		compatible = "rockchip,display-subsystem";
> > +		ports = <&vop_out>;
> > +	};
> 
> Some DT sort rules:
> 
> For nodes:
> Sort things without reg alphabetical first,
> then sort the rest by reg address.
> 
> > +
> > +	vop: vop@fe040000 {
> 
> > +		compatible = "rockchip,rk3568-vop";
> 
> From rockchip-vop2.yaml:
> +properties:
> +  compatible:
> +    enum:
> 
> +      - rockchip,rk3568-vop
> +      - rockchip,rk3566-vop
> 
> Maybe sort yaml compatibles in alphabetical order.
> 
> rockchip,rk3566-vop is not used in the dtsi I think.
> 
> Comment by Andy Yan:
> > 
> > But take care that the vop on rk3566 has a special limitation: there are 
> > three
> > 
> > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > 
> > can't be programed framebuffer address independently , they can only
> > 
> > share framebuffer address with Cluster0/Esmart0/Smart0.
> 
> Question:
> Given Andy's comment could someone explain weather the vop and hdmi
> nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> rockchip,rk3566-dw-hdmi compatible?

We could put the vop/hdmi nodes into rk356x.dtsi and just add the
compatible properties to rk3566.dtsi and rk3568.dtsi.
We'll need the exact SoC type, besides the mirror lock thingy there are a
few other minor differences between the SoCs.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  7:40       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-11-26  7:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> Hi Sascha,
> 
> 
> On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > The VOP2 is the display output controller on the RK3568. Add the node
> > for it to the dtsi file along with the required display-subsystem node
> > and the iommu node.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> > 
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 46d9552f60284..6ebf7c14e096a 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> >  		};
> >  	};
> >  
> 
> > +	display_subsystem: display-subsystem {
> > +		compatible = "rockchip,display-subsystem";
> > +		ports = <&vop_out>;
> > +	};
> 
> Some DT sort rules:
> 
> For nodes:
> Sort things without reg alphabetical first,
> then sort the rest by reg address.
> 
> > +
> > +	vop: vop@fe040000 {
> 
> > +		compatible = "rockchip,rk3568-vop";
> 
> From rockchip-vop2.yaml:
> +properties:
> +  compatible:
> +    enum:
> 
> +      - rockchip,rk3568-vop
> +      - rockchip,rk3566-vop
> 
> Maybe sort yaml compatibles in alphabetical order.
> 
> rockchip,rk3566-vop is not used in the dtsi I think.
> 
> Comment by Andy Yan:
> > 
> > But take care that the vop on rk3566 has a special limitation: there are 
> > three
> > 
> > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > 
> > can't be programed framebuffer address independently , they can only
> > 
> > share framebuffer address with Cluster0/Esmart0/Smart0.
> 
> Question:
> Given Andy's comment could someone explain weather the vop and hdmi
> nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> rockchip,rk3566-dw-hdmi compatible?

We could put the vop/hdmi nodes into rk356x.dtsi and just add the
compatible properties to rk3566.dtsi and rk3568.dtsi.
We'll need the exact SoC type, besides the mirror lock thingy there are a
few other minor differences between the SoCs.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
  2021-11-26  7:40       ` Sascha Hauer
  (?)
  (?)
@ 2021-11-26  8:15         ` Heiko Stübner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-26  8:15 UTC (permalink / raw)
  To: Johan Jonker, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Freitag, 26. November 2021, 08:40:21 CET schrieb Sascha Hauer:
> On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> > Hi Sascha,
> > 
> > 
> > On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > > The VOP2 is the display output controller on the RK3568. Add the node
> > > for it to the dtsi file along with the required display-subsystem node
> > > and the iommu node.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> > >  1 file changed, 52 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > index 46d9552f60284..6ebf7c14e096a 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> > >  		};
> > >  	};
> > >  
> > 
> > > +	display_subsystem: display-subsystem {
> > > +		compatible = "rockchip,display-subsystem";
> > > +		ports = <&vop_out>;
> > > +	};
> > 
> > Some DT sort rules:
> > 
> > For nodes:
> > Sort things without reg alphabetical first,
> > then sort the rest by reg address.
> > 
> > > +
> > > +	vop: vop@fe040000 {
> > 
> > > +		compatible = "rockchip,rk3568-vop";
> > 
> > From rockchip-vop2.yaml:
> > +properties:
> > +  compatible:
> > +    enum:
> > 
> > +      - rockchip,rk3568-vop
> > +      - rockchip,rk3566-vop
> > 
> > Maybe sort yaml compatibles in alphabetical order.
> > 
> > rockchip,rk3566-vop is not used in the dtsi I think.
> > 
> > Comment by Andy Yan:
> > > 
> > > But take care that the vop on rk3566 has a special limitation: there are 
> > > three
> > > 
> > > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > > 
> > > can't be programed framebuffer address independently , they can only
> > > 
> > > share framebuffer address with Cluster0/Esmart0/Smart0.
> > 
> > Question:
> > Given Andy's comment could someone explain weather the vop and hdmi
> > nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> > rockchip,rk3566-dw-hdmi compatible?
> 
> We could put the vop/hdmi nodes into rk356x.dtsi and just add the
> compatible properties to rk3566.dtsi and rk3568.dtsi.

sounds about right. We have similar solutions in place in other socs.

Heiko




_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  8:15         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-26  8:15 UTC (permalink / raw)
  To: Johan Jonker, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	dri-devel, linux-rockchip, Michael Riesch, kernel,
	linux-arm-kernel

Am Freitag, 26. November 2021, 08:40:21 CET schrieb Sascha Hauer:
> On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> > Hi Sascha,
> > 
> > 
> > On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > > The VOP2 is the display output controller on the RK3568. Add the node
> > > for it to the dtsi file along with the required display-subsystem node
> > > and the iommu node.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> > >  1 file changed, 52 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > index 46d9552f60284..6ebf7c14e096a 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> > >  		};
> > >  	};
> > >  
> > 
> > > +	display_subsystem: display-subsystem {
> > > +		compatible = "rockchip,display-subsystem";
> > > +		ports = <&vop_out>;
> > > +	};
> > 
> > Some DT sort rules:
> > 
> > For nodes:
> > Sort things without reg alphabetical first,
> > then sort the rest by reg address.
> > 
> > > +
> > > +	vop: vop@fe040000 {
> > 
> > > +		compatible = "rockchip,rk3568-vop";
> > 
> > From rockchip-vop2.yaml:
> > +properties:
> > +  compatible:
> > +    enum:
> > 
> > +      - rockchip,rk3568-vop
> > +      - rockchip,rk3566-vop
> > 
> > Maybe sort yaml compatibles in alphabetical order.
> > 
> > rockchip,rk3566-vop is not used in the dtsi I think.
> > 
> > Comment by Andy Yan:
> > > 
> > > But take care that the vop on rk3566 has a special limitation: there are 
> > > three
> > > 
> > > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > > 
> > > can't be programed framebuffer address independently , they can only
> > > 
> > > share framebuffer address with Cluster0/Esmart0/Smart0.
> > 
> > Question:
> > Given Andy's comment could someone explain weather the vop and hdmi
> > nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> > rockchip,rk3566-dw-hdmi compatible?
> 
> We could put the vop/hdmi nodes into rk356x.dtsi and just add the
> compatible properties to rk3566.dtsi and rk3568.dtsi.

sounds about right. We have similar solutions in place in other socs.

Heiko




^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  8:15         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-26  8:15 UTC (permalink / raw)
  To: Johan Jonker, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Freitag, 26. November 2021, 08:40:21 CET schrieb Sascha Hauer:
> On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> > Hi Sascha,
> > 
> > 
> > On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > > The VOP2 is the display output controller on the RK3568. Add the node
> > > for it to the dtsi file along with the required display-subsystem node
> > > and the iommu node.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> > >  1 file changed, 52 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > index 46d9552f60284..6ebf7c14e096a 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> > >  		};
> > >  	};
> > >  
> > 
> > > +	display_subsystem: display-subsystem {
> > > +		compatible = "rockchip,display-subsystem";
> > > +		ports = <&vop_out>;
> > > +	};
> > 
> > Some DT sort rules:
> > 
> > For nodes:
> > Sort things without reg alphabetical first,
> > then sort the rest by reg address.
> > 
> > > +
> > > +	vop: vop@fe040000 {
> > 
> > > +		compatible = "rockchip,rk3568-vop";
> > 
> > From rockchip-vop2.yaml:
> > +properties:
> > +  compatible:
> > +    enum:
> > 
> > +      - rockchip,rk3568-vop
> > +      - rockchip,rk3566-vop
> > 
> > Maybe sort yaml compatibles in alphabetical order.
> > 
> > rockchip,rk3566-vop is not used in the dtsi I think.
> > 
> > Comment by Andy Yan:
> > > 
> > > But take care that the vop on rk3566 has a special limitation: there are 
> > > three
> > > 
> > > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > > 
> > > can't be programed framebuffer address independently , they can only
> > > 
> > > share framebuffer address with Cluster0/Esmart0/Smart0.
> > 
> > Question:
> > Given Andy's comment could someone explain weather the vop and hdmi
> > nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> > rockchip,rk3566-dw-hdmi compatible?
> 
> We could put the vop/hdmi nodes into rk356x.dtsi and just add the
> compatible properties to rk3566.dtsi and rk3568.dtsi.

sounds about right. We have similar solutions in place in other socs.

Heiko




_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes
@ 2021-11-26  8:15         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-11-26  8:15 UTC (permalink / raw)
  To: Johan Jonker, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis

Am Freitag, 26. November 2021, 08:40:21 CET schrieb Sascha Hauer:
> On Thu, Nov 25, 2021 at 09:25:28PM +0100, Johan Jonker wrote:
> > Hi Sascha,
> > 
> > 
> > On 11/17/21 3:33 PM, Sascha Hauer wrote:
> > > The VOP2 is the display output controller on the RK3568. Add the node
> > > for it to the dtsi file along with the required display-subsystem node
> > > and the iommu node.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 52 ++++++++++++++++++++++++
> > >  1 file changed, 52 insertions(+)
> > > 
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > index 46d9552f60284..6ebf7c14e096a 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > > @@ -447,6 +447,58 @@ gmac1_mtl_tx_setup: tx-queues-config {
> > >  		};
> > >  	};
> > >  
> > 
> > > +	display_subsystem: display-subsystem {
> > > +		compatible = "rockchip,display-subsystem";
> > > +		ports = <&vop_out>;
> > > +	};
> > 
> > Some DT sort rules:
> > 
> > For nodes:
> > Sort things without reg alphabetical first,
> > then sort the rest by reg address.
> > 
> > > +
> > > +	vop: vop@fe040000 {
> > 
> > > +		compatible = "rockchip,rk3568-vop";
> > 
> > From rockchip-vop2.yaml:
> > +properties:
> > +  compatible:
> > +    enum:
> > 
> > +      - rockchip,rk3568-vop
> > +      - rockchip,rk3566-vop
> > 
> > Maybe sort yaml compatibles in alphabetical order.
> > 
> > rockchip,rk3566-vop is not used in the dtsi I think.
> > 
> > Comment by Andy Yan:
> > > 
> > > But take care that the vop on rk3566 has a special limitation: there are 
> > > three
> > > 
> > > windows(Cluster1/Esmart1/Smart1) that have a mirror lock, that means they
> > > 
> > > can't be programed framebuffer address independently , they can only
> > > 
> > > share framebuffer address with Cluster0/Esmart0/Smart0.
> > 
> > Question:
> > Given Andy's comment could someone explain weather the vop and hdmi
> > nodes should be in rk3566.dtsi and rk3568.dtsi with an extra
> > rockchip,rk3566-dw-hdmi compatible?
> 
> We could put the vop/hdmi nodes into rk356x.dtsi and just add the
> compatible properties to rk3566.dtsi and rk3568.dtsi.

sounds about right. We have similar solutions in place in other socs.

Heiko




^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-27 15:07     ` Heiko Stuebner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stuebner @ 2021-11-27 15:07 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sascha Hauer,
	Sandy Huang, linux-rockchip, Michael Riesch, kernel,
	linux-arm-kernel

Hi,

Am Mittwoch, 17. November 2021, 15:33:36 CET schrieb Sascha Hauer:
> From: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> 
> Define a new compatible for rk3568 HDMI.
> This version of HDMI hardware block needs two new clocks hclk_vio and hclk
> to provide phy reference clocks.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index da3b889ad8fcd..53fa42479d5b7 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -23,6 +23,7 @@ properties:
>        - rockchip,rk3288-dw-hdmi
>        - rockchip,rk3328-dw-hdmi
>        - rockchip,rk3399-dw-hdmi
> +      - rockchip,rk3568-dw-hdmi
>  
>    reg-io-width:
>      const: 4
> @@ -49,8 +50,11 @@ properties:
>            - vpll
>        - enum:
>            - grf
> +          - hclk_vio

I don't believe this clock should be here:
(1) the rk3568 dts node later in the series doesn't use it at all
(2) generally vio-clocks are part of the interconnect where the ip block
    connects to, so right now we just enable it as critical on all socs and
    if someone actually models the interconnect (where also the qos
    [quality of service configs] nodes would play into), it would need to
    be included there.


Heiko

> +          - vpll
> +      - enum:
> +          - hclk
>            - vpll
> -      - const: vpll
>  
>    ddc-i2c-bus:
>      $ref: /schemas/types.yaml#/definitions/phandle
> 





^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-27 15:07     ` Heiko Stuebner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stuebner @ 2021-11-27 15:07 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Rob Herring, Sascha Hauer

Hi,

Am Mittwoch, 17. November 2021, 15:33:36 CET schrieb Sascha Hauer:
> From: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> 
> Define a new compatible for rk3568 HDMI.
> This version of HDMI hardware block needs two new clocks hclk_vio and hclk
> to provide phy reference clocks.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index da3b889ad8fcd..53fa42479d5b7 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -23,6 +23,7 @@ properties:
>        - rockchip,rk3288-dw-hdmi
>        - rockchip,rk3328-dw-hdmi
>        - rockchip,rk3399-dw-hdmi
> +      - rockchip,rk3568-dw-hdmi
>  
>    reg-io-width:
>      const: 4
> @@ -49,8 +50,11 @@ properties:
>            - vpll
>        - enum:
>            - grf
> +          - hclk_vio

I don't believe this clock should be here:
(1) the rk3568 dts node later in the series doesn't use it at all
(2) generally vio-clocks are part of the interconnect where the ip block
    connects to, so right now we just enable it as critical on all socs and
    if someone actually models the interconnect (where also the qos
    [quality of service configs] nodes would play into), it would need to
    be included there.


Heiko

> +          - vpll
> +      - enum:
> +          - hclk
>            - vpll
> -      - const: vpll
>  
>    ddc-i2c-bus:
>      $ref: /schemas/types.yaml#/definitions/phandle
> 





_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-27 15:07     ` Heiko Stuebner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stuebner @ 2021-11-27 15:07 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Rob Herring, Sascha Hauer

Hi,

Am Mittwoch, 17. November 2021, 15:33:36 CET schrieb Sascha Hauer:
> From: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> 
> Define a new compatible for rk3568 HDMI.
> This version of HDMI hardware block needs two new clocks hclk_vio and hclk
> to provide phy reference clocks.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index da3b889ad8fcd..53fa42479d5b7 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -23,6 +23,7 @@ properties:
>        - rockchip,rk3288-dw-hdmi
>        - rockchip,rk3328-dw-hdmi
>        - rockchip,rk3399-dw-hdmi
> +      - rockchip,rk3568-dw-hdmi
>  
>    reg-io-width:
>      const: 4
> @@ -49,8 +50,11 @@ properties:
>            - vpll
>        - enum:
>            - grf
> +          - hclk_vio

I don't believe this clock should be here:
(1) the rk3568 dts node later in the series doesn't use it at all
(2) generally vio-clocks are part of the interconnect where the ip block
    connects to, so right now we just enable it as critical on all socs and
    if someone actually models the interconnect (where also the qos
    [quality of service configs] nodes would play into), it would need to
    be included there.


Heiko

> +          - vpll
> +      - enum:
> +          - hclk
>            - vpll
> -      - const: vpll
>  
>    ddc-i2c-bus:
>      $ref: /schemas/types.yaml#/definitions/phandle
> 





^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI
@ 2021-11-27 15:07     ` Heiko Stuebner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stuebner @ 2021-11-27 15:07 UTC (permalink / raw)
  To: dri-devel, Sascha Hauer
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang, Peter Geis,
	Rob Herring, Sascha Hauer

Hi,

Am Mittwoch, 17. November 2021, 15:33:36 CET schrieb Sascha Hauer:
> From: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> 
> Define a new compatible for rk3568 HDMI.
> This version of HDMI hardware block needs two new clocks hclk_vio and hclk
> to provide phy reference clocks.
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Link: https://lore.kernel.org/r/20210707120323.401785-2-benjamin.gaignard@collabora.com
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../bindings/display/rockchip/rockchip,dw-hdmi.yaml         | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index da3b889ad8fcd..53fa42479d5b7 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -23,6 +23,7 @@ properties:
>        - rockchip,rk3288-dw-hdmi
>        - rockchip,rk3328-dw-hdmi
>        - rockchip,rk3399-dw-hdmi
> +      - rockchip,rk3568-dw-hdmi
>  
>    reg-io-width:
>      const: 4
> @@ -49,8 +50,11 @@ properties:
>            - vpll
>        - enum:
>            - grf
> +          - hclk_vio

I don't believe this clock should be here:
(1) the rk3568 dts node later in the series doesn't use it at all
(2) generally vio-clocks are part of the interconnect where the ip block
    connects to, so right now we just enable it as critical on all socs and
    if someone actually models the interconnect (where also the qos
    [quality of service configs] nodes would play into), it would need to
    be included there.


Heiko

> +          - vpll
> +      - enum:
> +          - hclk
>            - vpll
> -      - const: vpll
>  
>    ddc-i2c-bus:
>      $ref: /schemas/types.yaml#/definitions/phandle
> 





_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-11-29 22:46     ` Rob Herring
  -1 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-29 22:46 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 03:33:39PM +0100, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++

Bindings should be a separate patch. Include this as part of adding 
RK3568 support to the binding.

>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>  2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>    reg-io-width:
>      const: 4
>  
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.

0.9V ???

> +
>    clocks:
>      minItems: 2
>      items:

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-29 22:46     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-29 22:46 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	linux-rockchip, Michael Riesch, kernel, Peter Geis,
	linux-arm-kernel

On Wed, Nov 17, 2021 at 03:33:39PM +0100, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++

Bindings should be a separate patch. Include this as part of adding 
RK3568 support to the binding.

>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>  2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>    reg-io-width:
>      const: 4
>  
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.

0.9V ???

> +
>    clocks:
>      minItems: 2
>      items:

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-29 22:46     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-29 22:46 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 03:33:39PM +0100, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++

Bindings should be a separate patch. Include this as part of adding 
RK3568 support to the binding.

>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>  2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>    reg-io-width:
>      const: 4
>  
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.

0.9V ???

> +
>    clocks:
>      minItems: 2
>      items:

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-11-29 22:46     ` Rob Herring
  0 siblings, 0 replies; 201+ messages in thread
From: Rob Herring @ 2021-11-29 22:46 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 03:33:39PM +0100, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++

Bindings should be a separate patch. Include this as part of adding 
RK3568 support to the binding.

>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>  2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>    reg-io-width:
>      const: 4
>  
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.

0.9V ???

> +
>    clocks:
>      minItems: 2
>      items:

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
  2021-11-17 15:13     ` Rob Herring
  (?)
  (?)
@ 2021-12-01 16:04       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-01 16:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 09:13:33AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > Add support for the HDMI port found on RK3568.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 6ebf7c14e096a..53be61a7ce595 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -472,18 +472,36 @@ vp0: port@0 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <0>;
> > +
> > +                               vp0_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp0>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp1: port@1 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <1>;
> > +
> > +                               vp1_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp1>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp2: port@2 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <2>;
> > +
> > +                               vp2_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp2>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >                 };
> >         };
> > @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
> >                 status = "disabled";
> >         };
> >
> > +       hdmi: hdmi@fe0a0000 {
> > +               compatible = "rockchip,rk3568-dw-hdmi";
> > +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> > +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> > +               clocks = <&cru PCLK_HDMI_HOST>,
> > +                        <&cru CLK_HDMI_SFR>,
> > +                        <&cru CLK_HDMI_CEC>,
> > +                        <&cru HCLK_VOP>;
> > +               clock-names = "iahb", "isfr", "cec", "hclk";
> > +               power-domains = <&power RK3568_PD_VO>;
> > +               reg-io-width = <4>;
> > +               rockchip,grf = <&grf>;
> > +               #sound-dai-cells = <0>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> > +               status = "disabled";
> > +
> > +               ports {
> > +                       #address-cells = <1>;
> > +                       #size-cells = <0>;
> > +
> > +                       hdmi_in: port@0 {
> 
> 
> The schema says there is only 1 'port' node. Please run schema
> validation when making DT changes.
> 
> However, an HDMI bridge should also define an output port to a
> connector node (or another bridge). So the fix is to allow 'port@0'
> and add an output port.

The rockchip bindings traditionally don't have a connector explicitly
specified in their device trees. I'll stick to that for the next round.
If necessary I'll look later what it takes to add a connector node.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-12-01 16:04       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-01 16:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:13:33AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > Add support for the HDMI port found on RK3568.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 6ebf7c14e096a..53be61a7ce595 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -472,18 +472,36 @@ vp0: port@0 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <0>;
> > +
> > +                               vp0_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp0>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp1: port@1 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <1>;
> > +
> > +                               vp1_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp1>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp2: port@2 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <2>;
> > +
> > +                               vp2_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp2>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >                 };
> >         };
> > @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
> >                 status = "disabled";
> >         };
> >
> > +       hdmi: hdmi@fe0a0000 {
> > +               compatible = "rockchip,rk3568-dw-hdmi";
> > +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> > +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> > +               clocks = <&cru PCLK_HDMI_HOST>,
> > +                        <&cru CLK_HDMI_SFR>,
> > +                        <&cru CLK_HDMI_CEC>,
> > +                        <&cru HCLK_VOP>;
> > +               clock-names = "iahb", "isfr", "cec", "hclk";
> > +               power-domains = <&power RK3568_PD_VO>;
> > +               reg-io-width = <4>;
> > +               rockchip,grf = <&grf>;
> > +               #sound-dai-cells = <0>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> > +               status = "disabled";
> > +
> > +               ports {
> > +                       #address-cells = <1>;
> > +                       #size-cells = <0>;
> > +
> > +                       hdmi_in: port@0 {
> 
> 
> The schema says there is only 1 'port' node. Please run schema
> validation when making DT changes.
> 
> However, an HDMI bridge should also define an output port to a
> connector node (or another bridge). So the fix is to allow 'port@0'
> and add an output port.

The rockchip bindings traditionally don't have a connector explicitly
specified in their device trees. I'll stick to that for the next round.
If necessary I'll look later what it takes to add a connector node.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-12-01 16:04       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-01 16:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:13:33AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > Add support for the HDMI port found on RK3568.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 6ebf7c14e096a..53be61a7ce595 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -472,18 +472,36 @@ vp0: port@0 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <0>;
> > +
> > +                               vp0_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp0>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp1: port@1 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <1>;
> > +
> > +                               vp1_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp1>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp2: port@2 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <2>;
> > +
> > +                               vp2_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp2>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >                 };
> >         };
> > @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
> >                 status = "disabled";
> >         };
> >
> > +       hdmi: hdmi@fe0a0000 {
> > +               compatible = "rockchip,rk3568-dw-hdmi";
> > +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> > +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> > +               clocks = <&cru PCLK_HDMI_HOST>,
> > +                        <&cru CLK_HDMI_SFR>,
> > +                        <&cru CLK_HDMI_CEC>,
> > +                        <&cru HCLK_VOP>;
> > +               clock-names = "iahb", "isfr", "cec", "hclk";
> > +               power-domains = <&power RK3568_PD_VO>;
> > +               reg-io-width = <4>;
> > +               rockchip,grf = <&grf>;
> > +               #sound-dai-cells = <0>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> > +               status = "disabled";
> > +
> > +               ports {
> > +                       #address-cells = <1>;
> > +                       #size-cells = <0>;
> > +
> > +                       hdmi_in: port@0 {
> 
> 
> The schema says there is only 1 'port' node. Please run schema
> validation when making DT changes.
> 
> However, an HDMI bridge should also define an output port to a
> connector node (or another bridge). So the fix is to allow 'port@0'
> and add an output port.

The rockchip bindings traditionally don't have a connector explicitly
specified in their device trees. I'll stick to that for the next round.
If necessary I'll look later what it takes to add a connector node.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes
@ 2021-12-01 16:04       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-01 16:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:13:33AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > Add support for the HDMI port found on RK3568.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  arch/arm64/boot/dts/rockchip/rk356x.dtsi | 65 ++++++++++++++++++++++++
> >  1 file changed, 65 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > index 6ebf7c14e096a..53be61a7ce595 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > +++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
> > @@ -472,18 +472,36 @@ vp0: port@0 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <0>;
> > +
> > +                               vp0_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp0>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp1: port@1 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <1>;
> > +
> > +                               vp1_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp1>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >
> >                         vp2: port@2 {
> >                                 #address-cells = <1>;
> >                                 #size-cells = <0>;
> >                                 reg = <2>;
> > +
> > +                               vp2_out_hdmi: endpoint@0 {
> > +                                       reg = <0>;
> > +                                       remote-endpoint = <&hdmi_in_vp2>;
> > +                                       status = "disabled";
> > +                               };
> >                         };
> >                 };
> >         };
> > @@ -499,6 +517,53 @@ vop_mmu: iommu@fe043e00 {
> >                 status = "disabled";
> >         };
> >
> > +       hdmi: hdmi@fe0a0000 {
> > +               compatible = "rockchip,rk3568-dw-hdmi";
> > +               reg = <0x0 0xfe0a0000 0x0 0x20000>;
> > +               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> > +               clocks = <&cru PCLK_HDMI_HOST>,
> > +                        <&cru CLK_HDMI_SFR>,
> > +                        <&cru CLK_HDMI_CEC>,
> > +                        <&cru HCLK_VOP>;
> > +               clock-names = "iahb", "isfr", "cec", "hclk";
> > +               power-domains = <&power RK3568_PD_VO>;
> > +               reg-io-width = <4>;
> > +               rockchip,grf = <&grf>;
> > +               #sound-dai-cells = <0>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&hdmitx_scl &hdmitx_sda &hdmitxm0_cec>;
> > +               status = "disabled";
> > +
> > +               ports {
> > +                       #address-cells = <1>;
> > +                       #size-cells = <0>;
> > +
> > +                       hdmi_in: port@0 {
> 
> 
> The schema says there is only 1 'port' node. Please run schema
> validation when making DT changes.
> 
> However, an HDMI bridge should also define an output port to a
> connector node (or another bridge). So the fix is to allow 'port@0'
> and add an output port.

The rockchip bindings traditionally don't have a connector explicitly
specified in their device trees. I'll stick to that for the next round.
If necessary I'll look later what it takes to add a connector node.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-11-17 15:19     ` Rob Herring
  (?)
  (?)
@ 2021-12-02 15:34       ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 15:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This enabled the VOP2 display controller along with hdmi and the
> > required port routes which is enough to get a picture out of the
> > hdmi port of the board.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > index 184e2aa2416af..156e001492173 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> >         status = "okay";
> >  };
> >
> > +&hdmi {
> > +       status = "okay";
> > +       avdd-0v9-supply = <&vdda0v9_image>;
> > +       avdd-1v8-supply = <&vcca1v8_image>;
> > +};
> > +
> >  &i2c0 {
> >         status = "okay";
> >
> > @@ -390,3 +396,21 @@ &sdmmc0 {
> >  &uart2 {
> >         status = "okay";
> >  };
> > +
> > +&vop {
> > +       status = "okay";
> > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > +};
> > +
> > +&vop_mmu {
> > +       status = "okay";
> > +};
> > +
> > +&hdmi_in_vp0 {
> > +       status = "okay";
> > +};
> > +
> > +&vp0_out_hdmi {
> > +       status = "okay";
> > +};
> 
> You can accomplish the same thing already with:
> 
> &vp0_out_hdmi {
>   remote-endpoint = <&hdmi_in_vp0>;
> };

My idea was to describe all possible connections in the dtsi file and
let the board dts writer only en/disable the needed connections. When
the connections are specified in the dts file then writing it is more
difficult and error prone.

> 
> or:
> 
> &vp0_out_hdmi {
>   /delete-property/ remote-endpoint;
> };

With this I have to change all connections that I don't need. With
status = "okay" I have to change all connections that I actually do
need, which will be much easier to read and write.

I'll stick to the status = "okay" method for the next round, maybe I can
still convince you ;)

If it's the 'status' property you don't like being used when it's not a
device that is enabled/disabled, then every other name would be fine
with me as well.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:34       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 15:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, dri-devel,
	open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, Peter Geis, linux-arm-kernel

On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This enabled the VOP2 display controller along with hdmi and the
> > required port routes which is enough to get a picture out of the
> > hdmi port of the board.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > index 184e2aa2416af..156e001492173 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> >         status = "okay";
> >  };
> >
> > +&hdmi {
> > +       status = "okay";
> > +       avdd-0v9-supply = <&vdda0v9_image>;
> > +       avdd-1v8-supply = <&vcca1v8_image>;
> > +};
> > +
> >  &i2c0 {
> >         status = "okay";
> >
> > @@ -390,3 +396,21 @@ &sdmmc0 {
> >  &uart2 {
> >         status = "okay";
> >  };
> > +
> > +&vop {
> > +       status = "okay";
> > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > +};
> > +
> > +&vop_mmu {
> > +       status = "okay";
> > +};
> > +
> > +&hdmi_in_vp0 {
> > +       status = "okay";
> > +};
> > +
> > +&vp0_out_hdmi {
> > +       status = "okay";
> > +};
> 
> You can accomplish the same thing already with:
> 
> &vp0_out_hdmi {
>   remote-endpoint = <&hdmi_in_vp0>;
> };

My idea was to describe all possible connections in the dtsi file and
let the board dts writer only en/disable the needed connections. When
the connections are specified in the dts file then writing it is more
difficult and error prone.

> 
> or:
> 
> &vp0_out_hdmi {
>   /delete-property/ remote-endpoint;
> };

With this I have to change all connections that I don't need. With
status = "okay" I have to change all connections that I actually do
need, which will be much easier to read and write.

I'll stick to the status = "okay" method for the next round, maybe I can
still convince you ;)

If it's the 'status' property you don't like being used when it's not a
device that is enabled/disabled, then every other name would be fine
with me as well.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:34       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 15:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This enabled the VOP2 display controller along with hdmi and the
> > required port routes which is enough to get a picture out of the
> > hdmi port of the board.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > index 184e2aa2416af..156e001492173 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> >         status = "okay";
> >  };
> >
> > +&hdmi {
> > +       status = "okay";
> > +       avdd-0v9-supply = <&vdda0v9_image>;
> > +       avdd-1v8-supply = <&vcca1v8_image>;
> > +};
> > +
> >  &i2c0 {
> >         status = "okay";
> >
> > @@ -390,3 +396,21 @@ &sdmmc0 {
> >  &uart2 {
> >         status = "okay";
> >  };
> > +
> > +&vop {
> > +       status = "okay";
> > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > +};
> > +
> > +&vop_mmu {
> > +       status = "okay";
> > +};
> > +
> > +&hdmi_in_vp0 {
> > +       status = "okay";
> > +};
> > +
> > +&vp0_out_hdmi {
> > +       status = "okay";
> > +};
> 
> You can accomplish the same thing already with:
> 
> &vp0_out_hdmi {
>   remote-endpoint = <&hdmi_in_vp0>;
> };

My idea was to describe all possible connections in the dtsi file and
let the board dts writer only en/disable the needed connections. When
the connections are specified in the dts file then writing it is more
difficult and error prone.

> 
> or:
> 
> &vp0_out_hdmi {
>   /delete-property/ remote-endpoint;
> };

With this I have to change all connections that I don't need. With
status = "okay" I have to change all connections that I actually do
need, which will be much easier to read and write.

I'll stick to the status = "okay" method for the next round, maybe I can
still convince you ;)

If it's the 'status' property you don't like being used when it's not a
device that is enabled/disabled, then every other name would be fine
with me as well.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:34       ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 15:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Heiko Stübner, Peter Geis

On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >
> > This enabled the VOP2 display controller along with hdmi and the
> > required port routes which is enough to get a picture out of the
> > hdmi port of the board.
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > ---
> >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > index 184e2aa2416af..156e001492173 100644
> > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> >         status = "okay";
> >  };
> >
> > +&hdmi {
> > +       status = "okay";
> > +       avdd-0v9-supply = <&vdda0v9_image>;
> > +       avdd-1v8-supply = <&vcca1v8_image>;
> > +};
> > +
> >  &i2c0 {
> >         status = "okay";
> >
> > @@ -390,3 +396,21 @@ &sdmmc0 {
> >  &uart2 {
> >         status = "okay";
> >  };
> > +
> > +&vop {
> > +       status = "okay";
> > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > +};
> > +
> > +&vop_mmu {
> > +       status = "okay";
> > +};
> > +
> > +&hdmi_in_vp0 {
> > +       status = "okay";
> > +};
> > +
> > +&vp0_out_hdmi {
> > +       status = "okay";
> > +};
> 
> You can accomplish the same thing already with:
> 
> &vp0_out_hdmi {
>   remote-endpoint = <&hdmi_in_vp0>;
> };

My idea was to describe all possible connections in the dtsi file and
let the board dts writer only en/disable the needed connections. When
the connections are specified in the dts file then writing it is more
difficult and error prone.

> 
> or:
> 
> &vp0_out_hdmi {
>   /delete-property/ remote-endpoint;
> };

With this I have to change all connections that I don't need. With
status = "okay" I have to change all connections that I actually do
need, which will be much easier to read and write.

I'll stick to the status = "okay" method for the next round, maybe I can
still convince you ;)

If it's the 'status' property you don't like being used when it's not a
device that is enabled/disabled, then every other name would be fine
with me as well.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-12-02 15:34       ` Sascha Hauer
  (?)
  (?)
@ 2021-12-02 15:41         ` Heiko Stübner
  -1 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-12-02 15:41 UTC (permalink / raw)
  To: Rob Herring, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Sascha,

Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > This enabled the VOP2 display controller along with hdmi and the
> > > required port routes which is enough to get a picture out of the
> > > hdmi port of the board.
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > index 184e2aa2416af..156e001492173 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > >         status = "okay";
> > >  };
> > >
> > > +&hdmi {
> > > +       status = "okay";
> > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > +};
> > > +
> > >  &i2c0 {
> > >         status = "okay";
> > >
> > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > >  &uart2 {
> > >         status = "okay";
> > >  };
> > > +
> > > +&vop {
> > > +       status = "okay";
> > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > +};
> > > +
> > > +&vop_mmu {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&hdmi_in_vp0 {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&vp0_out_hdmi {
> > > +       status = "okay";
> > > +};
> > 
> > You can accomplish the same thing already with:
> > 
> > &vp0_out_hdmi {
> >   remote-endpoint = <&hdmi_in_vp0>;
> > };
> 
> My idea was to describe all possible connections in the dtsi file and
> let the board dts writer only en/disable the needed connections. When
> the connections are specified in the dts file then writing it is more
> difficult and error prone.
> 
> > 
> > or:
> > 
> > &vp0_out_hdmi {
> >   /delete-property/ remote-endpoint;
> > };
> 
> With this I have to change all connections that I don't need. With
> status = "okay" I have to change all connections that I actually do
> need, which will be much easier to read and write.
> 
> I'll stick to the status = "okay" method for the next round, maybe I can
> still convince you ;)
> 
> If it's the 'status' property you don't like being used when it's not a
> device that is enabled/disabled, then every other name would be fine
> with me as well.

hmm, we do have code in the rockchip drm-driver to find out
if the device at the end of a graph-connection is disabled or not [0] ,
So on previous Rockchip socs, there are already all connections
established, and the driver weeds out the disabled ones.

So I'm wondering what is missing to use that in a vop2 context?


Heiko

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_drv.c#n274



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:41         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-12-02 15:41 UTC (permalink / raw)
  To: Rob Herring, Sascha Hauer
  Cc: devicetree, Benjamin Gaignard, Peter Geis, Sandy Huang,
	dri-devel, open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, linux-arm-kernel

Hi Sascha,

Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > This enabled the VOP2 display controller along with hdmi and the
> > > required port routes which is enough to get a picture out of the
> > > hdmi port of the board.
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > index 184e2aa2416af..156e001492173 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > >         status = "okay";
> > >  };
> > >
> > > +&hdmi {
> > > +       status = "okay";
> > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > +};
> > > +
> > >  &i2c0 {
> > >         status = "okay";
> > >
> > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > >  &uart2 {
> > >         status = "okay";
> > >  };
> > > +
> > > +&vop {
> > > +       status = "okay";
> > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > +};
> > > +
> > > +&vop_mmu {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&hdmi_in_vp0 {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&vp0_out_hdmi {
> > > +       status = "okay";
> > > +};
> > 
> > You can accomplish the same thing already with:
> > 
> > &vp0_out_hdmi {
> >   remote-endpoint = <&hdmi_in_vp0>;
> > };
> 
> My idea was to describe all possible connections in the dtsi file and
> let the board dts writer only en/disable the needed connections. When
> the connections are specified in the dts file then writing it is more
> difficult and error prone.
> 
> > 
> > or:
> > 
> > &vp0_out_hdmi {
> >   /delete-property/ remote-endpoint;
> > };
> 
> With this I have to change all connections that I don't need. With
> status = "okay" I have to change all connections that I actually do
> need, which will be much easier to read and write.
> 
> I'll stick to the status = "okay" method for the next round, maybe I can
> still convince you ;)
> 
> If it's the 'status' property you don't like being used when it's not a
> device that is enabled/disabled, then every other name would be fine
> with me as well.

hmm, we do have code in the rockchip drm-driver to find out
if the device at the end of a graph-connection is disabled or not [0] ,
So on previous Rockchip socs, there are already all connections
established, and the driver weeds out the disabled ones.

So I'm wondering what is missing to use that in a vop2 context?


Heiko

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_drv.c#n274



^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:41         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-12-02 15:41 UTC (permalink / raw)
  To: Rob Herring, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Sascha,

Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > This enabled the VOP2 display controller along with hdmi and the
> > > required port routes which is enough to get a picture out of the
> > > hdmi port of the board.
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > index 184e2aa2416af..156e001492173 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > >         status = "okay";
> > >  };
> > >
> > > +&hdmi {
> > > +       status = "okay";
> > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > +};
> > > +
> > >  &i2c0 {
> > >         status = "okay";
> > >
> > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > >  &uart2 {
> > >         status = "okay";
> > >  };
> > > +
> > > +&vop {
> > > +       status = "okay";
> > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > +};
> > > +
> > > +&vop_mmu {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&hdmi_in_vp0 {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&vp0_out_hdmi {
> > > +       status = "okay";
> > > +};
> > 
> > You can accomplish the same thing already with:
> > 
> > &vp0_out_hdmi {
> >   remote-endpoint = <&hdmi_in_vp0>;
> > };
> 
> My idea was to describe all possible connections in the dtsi file and
> let the board dts writer only en/disable the needed connections. When
> the connections are specified in the dts file then writing it is more
> difficult and error prone.
> 
> > 
> > or:
> > 
> > &vp0_out_hdmi {
> >   /delete-property/ remote-endpoint;
> > };
> 
> With this I have to change all connections that I don't need. With
> status = "okay" I have to change all connections that I actually do
> need, which will be much easier to read and write.
> 
> I'll stick to the status = "okay" method for the next round, maybe I can
> still convince you ;)
> 
> If it's the 'status' property you don't like being used when it's not a
> device that is enabled/disabled, then every other name would be fine
> with me as well.

hmm, we do have code in the rockchip drm-driver to find out
if the device at the end of a graph-connection is disabled or not [0] ,
So on previous Rockchip socs, there are already all connections
established, and the driver weeds out the disabled ones.

So I'm wondering what is missing to use that in a vop2 context?


Heiko

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_drv.c#n274



_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 15:41         ` Heiko Stübner
  0 siblings, 0 replies; 201+ messages in thread
From: Heiko Stübner @ 2021-12-02 15:41 UTC (permalink / raw)
  To: Rob Herring, Sascha Hauer
  Cc: dri-devel, linux-arm-kernel, open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Sascha,

Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > >
> > > This enabled the VOP2 display controller along with hdmi and the
> > > required port routes which is enough to get a picture out of the
> > > hdmi port of the board.
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > index 184e2aa2416af..156e001492173 100644
> > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > >         status = "okay";
> > >  };
> > >
> > > +&hdmi {
> > > +       status = "okay";
> > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > +};
> > > +
> > >  &i2c0 {
> > >         status = "okay";
> > >
> > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > >  &uart2 {
> > >         status = "okay";
> > >  };
> > > +
> > > +&vop {
> > > +       status = "okay";
> > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > +};
> > > +
> > > +&vop_mmu {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&hdmi_in_vp0 {
> > > +       status = "okay";
> > > +};
> > > +
> > > +&vp0_out_hdmi {
> > > +       status = "okay";
> > > +};
> > 
> > You can accomplish the same thing already with:
> > 
> > &vp0_out_hdmi {
> >   remote-endpoint = <&hdmi_in_vp0>;
> > };
> 
> My idea was to describe all possible connections in the dtsi file and
> let the board dts writer only en/disable the needed connections. When
> the connections are specified in the dts file then writing it is more
> difficult and error prone.
> 
> > 
> > or:
> > 
> > &vp0_out_hdmi {
> >   /delete-property/ remote-endpoint;
> > };
> 
> With this I have to change all connections that I don't need. With
> status = "okay" I have to change all connections that I actually do
> need, which will be much easier to read and write.
> 
> I'll stick to the status = "okay" method for the next round, maybe I can
> still convince you ;)
> 
> If it's the 'status' property you don't like being used when it's not a
> device that is enabled/disabled, then every other name would be fine
> with me as well.

hmm, we do have code in the rockchip drm-driver to find out
if the device at the end of a graph-connection is disabled or not [0] ,
So on previous Rockchip socs, there are already all connections
established, and the driver weeds out the disabled ones.

So I'm wondering what is missing to use that in a vop2 context?


Heiko

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/rockchip/rockchip_drm_drv.c#n274



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
  2021-12-02 15:41         ` Heiko Stübner
  (?)
  (?)
@ 2021-12-02 16:09           ` Sascha Hauer
  -1 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 16:09 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Rob Herring, dri-devel, linux-arm-kernel,
	open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Heiko,

On Thu, Dec 02, 2021 at 04:41:17PM +0100, Heiko Stübner wrote:
> Hi Sascha,
> 
> Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> > On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > >
> > > > This enabled the VOP2 display controller along with hdmi and the
> > > > required port routes which is enough to get a picture out of the
> > > > hdmi port of the board.
> > > >
> > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > > ---
> > > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > > >  1 file changed, 24 insertions(+)
> > > >
> > > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > index 184e2aa2416af..156e001492173 100644
> > > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > > >         status = "okay";
> > > >  };
> > > >
> > > > +&hdmi {
> > > > +       status = "okay";
> > > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > > +};
> > > > +
> > > >  &i2c0 {
> > > >         status = "okay";
> > > >
> > > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > > >  &uart2 {
> > > >         status = "okay";
> > > >  };
> > > > +
> > > > +&vop {
> > > > +       status = "okay";
> > > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > > +};
> > > > +
> > > > +&vop_mmu {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&hdmi_in_vp0 {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&vp0_out_hdmi {
> > > > +       status = "okay";
> > > > +};
> > > 
> > > You can accomplish the same thing already with:
> > > 
> > > &vp0_out_hdmi {
> > >   remote-endpoint = <&hdmi_in_vp0>;
> > > };
> > 
> > My idea was to describe all possible connections in the dtsi file and
> > let the board dts writer only en/disable the needed connections. When
> > the connections are specified in the dts file then writing it is more
> > difficult and error prone.
> > 
> > > 
> > > or:
> > > 
> > > &vp0_out_hdmi {
> > >   /delete-property/ remote-endpoint;
> > > };
> > 
> > With this I have to change all connections that I don't need. With
> > status = "okay" I have to change all connections that I actually do
> > need, which will be much easier to read and write.
> > 
> > I'll stick to the status = "okay" method for the next round, maybe I can
> > still convince you ;)
> > 
> > If it's the 'status' property you don't like being used when it's not a
> > device that is enabled/disabled, then every other name would be fine
> > with me as well.
> 
> hmm, we do have code in the rockchip drm-driver to find out
> if the device at the end of a graph-connection is disabled or not [0] ,
> So on previous Rockchip socs, there are already all connections
> established, and the driver weeds out the disabled ones.
> 
> So I'm wondering what is missing to use that in a vop2 context?

The vop2 has three video ports (crtcs) instead of only one. All three are
described in the device tree and each of them has a of_graph connection
to the different encoders, so something like:

vp0 <-> hdmi
vp0 <-> mipi
vp1 <-> hdmi
vp1 <-> mipi
vp2 <-> hdmi
vp2 <-> mipi

Enabling just vp0 <-> hdmi means only the first video port is can do
hdmi. Different constraints in the clock tree (hdmi reference clock is
hardwired to hpll, not enough PLLs to put all video ports on independent
ones) prevent us from just allowing all connections.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 16:09           ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 16:09 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Rob Herring, dri-devel, linux-arm-kernel,
	open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Heiko,

On Thu, Dec 02, 2021 at 04:41:17PM +0100, Heiko Stübner wrote:
> Hi Sascha,
> 
> Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> > On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > >
> > > > This enabled the VOP2 display controller along with hdmi and the
> > > > required port routes which is enough to get a picture out of the
> > > > hdmi port of the board.
> > > >
> > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > > ---
> > > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > > >  1 file changed, 24 insertions(+)
> > > >
> > > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > index 184e2aa2416af..156e001492173 100644
> > > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > > >         status = "okay";
> > > >  };
> > > >
> > > > +&hdmi {
> > > > +       status = "okay";
> > > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > > +};
> > > > +
> > > >  &i2c0 {
> > > >         status = "okay";
> > > >
> > > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > > >  &uart2 {
> > > >         status = "okay";
> > > >  };
> > > > +
> > > > +&vop {
> > > > +       status = "okay";
> > > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > > +};
> > > > +
> > > > +&vop_mmu {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&hdmi_in_vp0 {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&vp0_out_hdmi {
> > > > +       status = "okay";
> > > > +};
> > > 
> > > You can accomplish the same thing already with:
> > > 
> > > &vp0_out_hdmi {
> > >   remote-endpoint = <&hdmi_in_vp0>;
> > > };
> > 
> > My idea was to describe all possible connections in the dtsi file and
> > let the board dts writer only en/disable the needed connections. When
> > the connections are specified in the dts file then writing it is more
> > difficult and error prone.
> > 
> > > 
> > > or:
> > > 
> > > &vp0_out_hdmi {
> > >   /delete-property/ remote-endpoint;
> > > };
> > 
> > With this I have to change all connections that I don't need. With
> > status = "okay" I have to change all connections that I actually do
> > need, which will be much easier to read and write.
> > 
> > I'll stick to the status = "okay" method for the next round, maybe I can
> > still convince you ;)
> > 
> > If it's the 'status' property you don't like being used when it's not a
> > device that is enabled/disabled, then every other name would be fine
> > with me as well.
> 
> hmm, we do have code in the rockchip drm-driver to find out
> if the device at the end of a graph-connection is disabled or not [0] ,
> So on previous Rockchip socs, there are already all connections
> established, and the driver weeds out the disabled ones.
> 
> So I'm wondering what is missing to use that in a vop2 context?

The vop2 has three video ports (crtcs) instead of only one. All three are
described in the device tree and each of them has a of_graph connection
to the different encoders, so something like:

vp0 <-> hdmi
vp0 <-> mipi
vp1 <-> hdmi
vp1 <-> mipi
vp2 <-> hdmi
vp2 <-> mipi

Enabling just vp0 <-> hdmi means only the first video port is can do
hdmi. Different constraints in the clock tree (hdmi reference clock is
hardwired to hpll, not enough PLLs to put all video ports on independent
ones) prevent us from just allowing all connections.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 16:09           ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 16:09 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Benjamin Gaignard, Peter Geis, devicetree, Sandy Huang,
	dri-devel, open list:ARM/Rockchip SoC...,
	Michael Riesch, Sascha Hauer, linux-arm-kernel

Hi Heiko,

On Thu, Dec 02, 2021 at 04:41:17PM +0100, Heiko Stübner wrote:
> Hi Sascha,
> 
> Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> > On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > >
> > > > This enabled the VOP2 display controller along with hdmi and the
> > > > required port routes which is enough to get a picture out of the
> > > > hdmi port of the board.
> > > >
> > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > > ---
> > > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > > >  1 file changed, 24 insertions(+)
> > > >
> > > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > index 184e2aa2416af..156e001492173 100644
> > > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > > >         status = "okay";
> > > >  };
> > > >
> > > > +&hdmi {
> > > > +       status = "okay";
> > > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > > +};
> > > > +
> > > >  &i2c0 {
> > > >         status = "okay";
> > > >
> > > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > > >  &uart2 {
> > > >         status = "okay";
> > > >  };
> > > > +
> > > > +&vop {
> > > > +       status = "okay";
> > > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > > +};
> > > > +
> > > > +&vop_mmu {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&hdmi_in_vp0 {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&vp0_out_hdmi {
> > > > +       status = "okay";
> > > > +};
> > > 
> > > You can accomplish the same thing already with:
> > > 
> > > &vp0_out_hdmi {
> > >   remote-endpoint = <&hdmi_in_vp0>;
> > > };
> > 
> > My idea was to describe all possible connections in the dtsi file and
> > let the board dts writer only en/disable the needed connections. When
> > the connections are specified in the dts file then writing it is more
> > difficult and error prone.
> > 
> > > 
> > > or:
> > > 
> > > &vp0_out_hdmi {
> > >   /delete-property/ remote-endpoint;
> > > };
> > 
> > With this I have to change all connections that I don't need. With
> > status = "okay" I have to change all connections that I actually do
> > need, which will be much easier to read and write.
> > 
> > I'll stick to the status = "okay" method for the next round, maybe I can
> > still convince you ;)
> > 
> > If it's the 'status' property you don't like being used when it's not a
> > device that is enabled/disabled, then every other name would be fine
> > with me as well.
> 
> hmm, we do have code in the rockchip drm-driver to find out
> if the device at the end of a graph-connection is disabled or not [0] ,
> So on previous Rockchip socs, there are already all connections
> established, and the driver weeds out the disabled ones.
> 
> So I'm wondering what is missing to use that in a vop2 context?

The vop2 has three video ports (crtcs) instead of only one. All three are
described in the device tree and each of them has a of_graph connection
to the different encoders, so something like:

vp0 <-> hdmi
vp0 <-> mipi
vp1 <-> hdmi
vp1 <-> mipi
vp2 <-> hdmi
vp2 <-> mipi

Enabling just vp0 <-> hdmi means only the first video port is can do
hdmi. Different constraints in the clock tree (hdmi reference clock is
hardwired to hpll, not enough PLLs to put all video ports on independent
ones) prevent us from just allowing all connections.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi
@ 2021-12-02 16:09           ` Sascha Hauer
  0 siblings, 0 replies; 201+ messages in thread
From: Sascha Hauer @ 2021-12-02 16:09 UTC (permalink / raw)
  To: Heiko Stübner
  Cc: Rob Herring, dri-devel, linux-arm-kernel,
	open list:ARM/Rockchip SoC...,
	devicetree, Sascha Hauer, Benjamin Gaignard, Michael Riesch,
	Sandy Huang, Peter Geis

Hi Heiko,

On Thu, Dec 02, 2021 at 04:41:17PM +0100, Heiko Stübner wrote:
> Hi Sascha,
> 
> Am Donnerstag, 2. Dezember 2021, 16:34:49 CET schrieb Sascha Hauer:
> > On Wed, Nov 17, 2021 at 09:19:38AM -0600, Rob Herring wrote:
> > > On Wed, Nov 17, 2021 at 8:34 AM Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > > >
> > > > This enabled the VOP2 display controller along with hdmi and the
> > > > required port routes which is enough to get a picture out of the
> > > > hdmi port of the board.
> > > >
> > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > > ---
> > > >  .../boot/dts/rockchip/rk3568-evb1-v10.dts     | 24 +++++++++++++++++++
> > > >  1 file changed, 24 insertions(+)
> > > >
> > > > diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > index 184e2aa2416af..156e001492173 100644
> > > > --- a/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dts
> > > > @@ -106,6 +106,12 @@ &gmac1m1_rgmii_clk
> > > >         status = "okay";
> > > >  };
> > > >
> > > > +&hdmi {
> > > > +       status = "okay";
> > > > +       avdd-0v9-supply = <&vdda0v9_image>;
> > > > +       avdd-1v8-supply = <&vcca1v8_image>;
> > > > +};
> > > > +
> > > >  &i2c0 {
> > > >         status = "okay";
> > > >
> > > > @@ -390,3 +396,21 @@ &sdmmc0 {
> > > >  &uart2 {
> > > >         status = "okay";
> > > >  };
> > > > +
> > > > +&vop {
> > > > +       status = "okay";
> > > > +       assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
> > > > +       assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
> > > > +};
> > > > +
> > > > +&vop_mmu {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&hdmi_in_vp0 {
> > > > +       status = "okay";
> > > > +};
> > > > +
> > > > +&vp0_out_hdmi {
> > > > +       status = "okay";
> > > > +};
> > > 
> > > You can accomplish the same thing already with:
> > > 
> > > &vp0_out_hdmi {
> > >   remote-endpoint = <&hdmi_in_vp0>;
> > > };
> > 
> > My idea was to describe all possible connections in the dtsi file and
> > let the board dts writer only en/disable the needed connections. When
> > the connections are specified in the dts file then writing it is more
> > difficult and error prone.
> > 
> > > 
> > > or:
> > > 
> > > &vp0_out_hdmi {
> > >   /delete-property/ remote-endpoint;
> > > };
> > 
> > With this I have to change all connections that I don't need. With
> > status = "okay" I have to change all connections that I actually do
> > need, which will be much easier to read and write.
> > 
> > I'll stick to the status = "okay" method for the next round, maybe I can
> > still convince you ;)
> > 
> > If it's the 'status' property you don't like being used when it's not a
> > device that is enabled/disabled, then every other name would be fine
> > with me as well.
> 
> hmm, we do have code in the rockchip drm-driver to find out
> if the device at the end of a graph-connection is disabled or not [0] ,
> So on previous Rockchip socs, there are already all connections
> established, and the driver weeds out the disabled ones.
> 
> So I'm wondering what is missing to use that in a vop2 context?

The vop2 has three video ports (crtcs) instead of only one. All three are
described in the device tree and each of them has a of_graph connection
to the different encoders, so something like:

vp0 <-> hdmi
vp0 <-> mipi
vp1 <-> hdmi
vp1 <-> mipi
vp2 <-> hdmi
vp2 <-> mipi

Enabling just vp0 <-> hdmi means only the first video port is can do
hdmi. Different constraints in the clock tree (hdmi reference clock is
hardwired to hpll, not enough PLLs to put all video ports on independent
ones) prevent us from just allowing all connections.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
  2021-11-17 14:33   ` Sascha Hauer
  (?)
  (?)
@ 2021-12-07 17:01     ` Robin Murphy
  -1 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-12-07 17:01 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-17 14:33, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>   2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>     reg-io-width:
>       const: 4
>   
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
>     clocks:
>       minItems: 2
>       items:
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> index 29608c25e2d0e..b8fe56c89cdc9 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> @@ -9,6 +9,7 @@
>   #include <linux/platform_device.h>
>   #include <linux/phy/phy.h>
>   #include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
>   
>   #include <drm/bridge/dw_hdmi.h>
>   #include <drm/drm_edid.h>
> @@ -83,6 +84,8 @@ struct rockchip_hdmi {
>   	struct clk *vpll_clk;
>   	struct clk *grf_clk;
>   	struct dw_hdmi *hdmi;
> +	struct regulator *avdd_0v9;
> +	struct regulator *avdd_1v8;
>   	struct phy *phy;
>   };
>   
> @@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
>   	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
>   	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
>   
> +	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");

These are clearly *not* optional, unless the HDMI block is magic and can 
still work without physical power. Use devm_regulator_get(), and if the 
real supply is missing from the DT for whatever reason you should get a 
dummy regulator back, which you can then successfully disable and enable 
without all the conditional mess.

Robin.

> +	if (IS_ERR(hdmi->avdd_0v9)) {
> +		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_0v9);
> +
> +		hdmi->avdd_0v9 = NULL;
> +	}
> +
> +	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
> +	if (IS_ERR(hdmi->avdd_1v8)) {
> +		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_1v8);
> +
> +		hdmi->avdd_1v8 = NULL;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   		return ret;
>   	}
>   
> +	if (hdmi->avdd_0v9) {
> +		ret = regulator_enable(hdmi->avdd_0v9);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
> +			goto err_avdd_0v9;
> +		}
> +	}
> +
> +	if (hdmi->avdd_1v8) {
> +		ret = regulator_enable(hdmi->avdd_1v8);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
> +			goto err_avdd_1v8;
> +		}
> +	}
> +
>   	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
>   	if (ret) {
>   		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
>   			      ret);
> -		return ret;
> +		goto err_clk;
>   	}
>   
>   	if (hdmi->chip_data == &rk3568_chip_data) {
> @@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   	 */
>   	if (IS_ERR(hdmi->hdmi)) {
>   		ret = PTR_ERR(hdmi->hdmi);
> -		drm_encoder_cleanup(encoder);
> -		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +		goto err_bind;
>   	}
>   
> +	return 0;
> +
> +err_bind:
> +	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +	drm_encoder_cleanup(encoder);
> +err_clk:
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +err_avdd_1v8:
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
> +err_avdd_0v9:
>   	return ret;
>   }
>   
> @@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
>   
>   	dw_hdmi_unbind(hdmi->hdmi);
>   	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
>   }
>   
>   static const struct component_ops dw_hdmi_rockchip_ops = {
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-12-07 17:01     ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-12-07 17:01 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: devicetree, Benjamin Gaignard, Sandy Huang, linux-rockchip,
	Michael Riesch, kernel, Peter Geis, linux-arm-kernel

On 2021-11-17 14:33, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>   2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>     reg-io-width:
>       const: 4
>   
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
>     clocks:
>       minItems: 2
>       items:
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> index 29608c25e2d0e..b8fe56c89cdc9 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> @@ -9,6 +9,7 @@
>   #include <linux/platform_device.h>
>   #include <linux/phy/phy.h>
>   #include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
>   
>   #include <drm/bridge/dw_hdmi.h>
>   #include <drm/drm_edid.h>
> @@ -83,6 +84,8 @@ struct rockchip_hdmi {
>   	struct clk *vpll_clk;
>   	struct clk *grf_clk;
>   	struct dw_hdmi *hdmi;
> +	struct regulator *avdd_0v9;
> +	struct regulator *avdd_1v8;
>   	struct phy *phy;
>   };
>   
> @@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
>   	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
>   	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
>   
> +	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");

These are clearly *not* optional, unless the HDMI block is magic and can 
still work without physical power. Use devm_regulator_get(), and if the 
real supply is missing from the DT for whatever reason you should get a 
dummy regulator back, which you can then successfully disable and enable 
without all the conditional mess.

Robin.

> +	if (IS_ERR(hdmi->avdd_0v9)) {
> +		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_0v9);
> +
> +		hdmi->avdd_0v9 = NULL;
> +	}
> +
> +	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
> +	if (IS_ERR(hdmi->avdd_1v8)) {
> +		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_1v8);
> +
> +		hdmi->avdd_1v8 = NULL;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   		return ret;
>   	}
>   
> +	if (hdmi->avdd_0v9) {
> +		ret = regulator_enable(hdmi->avdd_0v9);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
> +			goto err_avdd_0v9;
> +		}
> +	}
> +
> +	if (hdmi->avdd_1v8) {
> +		ret = regulator_enable(hdmi->avdd_1v8);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
> +			goto err_avdd_1v8;
> +		}
> +	}
> +
>   	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
>   	if (ret) {
>   		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
>   			      ret);
> -		return ret;
> +		goto err_clk;
>   	}
>   
>   	if (hdmi->chip_data == &rk3568_chip_data) {
> @@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   	 */
>   	if (IS_ERR(hdmi->hdmi)) {
>   		ret = PTR_ERR(hdmi->hdmi);
> -		drm_encoder_cleanup(encoder);
> -		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +		goto err_bind;
>   	}
>   
> +	return 0;
> +
> +err_bind:
> +	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +	drm_encoder_cleanup(encoder);
> +err_clk:
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +err_avdd_1v8:
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
> +err_avdd_0v9:
>   	return ret;
>   }
>   
> @@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
>   
>   	dw_hdmi_unbind(hdmi->hdmi);
>   	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
>   }
>   
>   static const struct component_ops dw_hdmi_rockchip_ops = {
> 

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-12-07 17:01     ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-12-07 17:01 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-17 14:33, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>   2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>     reg-io-width:
>       const: 4
>   
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
>     clocks:
>       minItems: 2
>       items:
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> index 29608c25e2d0e..b8fe56c89cdc9 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> @@ -9,6 +9,7 @@
>   #include <linux/platform_device.h>
>   #include <linux/phy/phy.h>
>   #include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
>   
>   #include <drm/bridge/dw_hdmi.h>
>   #include <drm/drm_edid.h>
> @@ -83,6 +84,8 @@ struct rockchip_hdmi {
>   	struct clk *vpll_clk;
>   	struct clk *grf_clk;
>   	struct dw_hdmi *hdmi;
> +	struct regulator *avdd_0v9;
> +	struct regulator *avdd_1v8;
>   	struct phy *phy;
>   };
>   
> @@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
>   	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
>   	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
>   
> +	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");

These are clearly *not* optional, unless the HDMI block is magic and can 
still work without physical power. Use devm_regulator_get(), and if the 
real supply is missing from the DT for whatever reason you should get a 
dummy regulator back, which you can then successfully disable and enable 
without all the conditional mess.

Robin.

> +	if (IS_ERR(hdmi->avdd_0v9)) {
> +		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_0v9);
> +
> +		hdmi->avdd_0v9 = NULL;
> +	}
> +
> +	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
> +	if (IS_ERR(hdmi->avdd_1v8)) {
> +		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_1v8);
> +
> +		hdmi->avdd_1v8 = NULL;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   		return ret;
>   	}
>   
> +	if (hdmi->avdd_0v9) {
> +		ret = regulator_enable(hdmi->avdd_0v9);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
> +			goto err_avdd_0v9;
> +		}
> +	}
> +
> +	if (hdmi->avdd_1v8) {
> +		ret = regulator_enable(hdmi->avdd_1v8);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
> +			goto err_avdd_1v8;
> +		}
> +	}
> +
>   	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
>   	if (ret) {
>   		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
>   			      ret);
> -		return ret;
> +		goto err_clk;
>   	}
>   
>   	if (hdmi->chip_data == &rk3568_chip_data) {
> @@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   	 */
>   	if (IS_ERR(hdmi->hdmi)) {
>   		ret = PTR_ERR(hdmi->hdmi);
> -		drm_encoder_cleanup(encoder);
> -		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +		goto err_bind;
>   	}
>   
> +	return 0;
> +
> +err_bind:
> +	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +	drm_encoder_cleanup(encoder);
> +err_clk:
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +err_avdd_1v8:
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
> +err_avdd_0v9:
>   	return ret;
>   }
>   
> @@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
>   
>   	dw_hdmi_unbind(hdmi->hdmi);
>   	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
>   }
>   
>   static const struct component_ops dw_hdmi_rockchip_ops = {
> 

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 201+ messages in thread

* Re: [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support
@ 2021-12-07 17:01     ` Robin Murphy
  0 siblings, 0 replies; 201+ messages in thread
From: Robin Murphy @ 2021-12-07 17:01 UTC (permalink / raw)
  To: Sascha Hauer, dri-devel
  Cc: linux-arm-kernel, linux-rockchip, devicetree, kernel,
	Benjamin Gaignard, Michael Riesch, Sandy Huang,
	Heiko Stübner, Peter Geis

On 2021-11-17 14:33, Sascha Hauer wrote:
> The RK3568 has HDMI_TX_AVDD0V9 and HDMI_TX_AVDD_1V8 supply inputs needed
> for the HDMI port. add support for these to the driver for boards which
> have them supplied by switchable regulators.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>   .../display/rockchip/rockchip,dw-hdmi.yaml    |  6 ++
>   drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c   | 58 ++++++++++++++++++-
>   2 files changed, 61 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> index 53fa42479d5b7..293b2cfbf739f 100644
> --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml
> @@ -28,6 +28,12 @@ properties:
>     reg-io-width:
>       const: 4
>   
> +  avdd-0v9-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
> +  avdd-1v8-supply:
> +    description: A 0.9V supply that powers up the SoC internal circuitry.
> +
>     clocks:
>       minItems: 2
>       items:
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> index 29608c25e2d0e..b8fe56c89cdc9 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> @@ -9,6 +9,7 @@
>   #include <linux/platform_device.h>
>   #include <linux/phy/phy.h>
>   #include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
>   
>   #include <drm/bridge/dw_hdmi.h>
>   #include <drm/drm_edid.h>
> @@ -83,6 +84,8 @@ struct rockchip_hdmi {
>   	struct clk *vpll_clk;
>   	struct clk *grf_clk;
>   	struct dw_hdmi *hdmi;
> +	struct regulator *avdd_0v9;
> +	struct regulator *avdd_1v8;
>   	struct phy *phy;
>   };
>   
> @@ -222,6 +225,22 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
>   	hdmi->vpll_clk = hdmi->clks[RK_HDMI_CLK_VPLL].clk;
>   	hdmi->grf_clk = hdmi->clks[RK_HDMI_CLK_GRF].clk;
>   
> +	hdmi->avdd_0v9 = devm_regulator_get_optional(hdmi->dev, "avdd-0v9");

These are clearly *not* optional, unless the HDMI block is magic and can 
still work without physical power. Use devm_regulator_get(), and if the 
real supply is missing from the DT for whatever reason you should get a 
dummy regulator back, which you can then successfully disable and enable 
without all the conditional mess.

Robin.

> +	if (IS_ERR(hdmi->avdd_0v9)) {
> +		if (PTR_ERR(hdmi->avdd_0v9) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_0v9);
> +
> +		hdmi->avdd_0v9 = NULL;
> +	}
> +
> +	hdmi->avdd_1v8 = devm_regulator_get_optional(hdmi->dev, "avdd-1v8");
> +	if (IS_ERR(hdmi->avdd_1v8)) {
> +		if (PTR_ERR(hdmi->avdd_1v8) != -ENODEV)
> +			return PTR_ERR(hdmi->avdd_1v8);
> +
> +		hdmi->avdd_1v8 = NULL;
> +	}
> +
>   	return 0;
>   }
>   
> @@ -559,11 +578,27 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   		return ret;
>   	}
>   
> +	if (hdmi->avdd_0v9) {
> +		ret = regulator_enable(hdmi->avdd_0v9);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret);
> +			goto err_avdd_0v9;
> +		}
> +	}
> +
> +	if (hdmi->avdd_1v8) {
> +		ret = regulator_enable(hdmi->avdd_1v8);
> +		if (ret) {
> +			DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret);
> +			goto err_avdd_1v8;
> +		}
> +	}
> +
>   	ret = clk_bulk_prepare_enable(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
>   	if (ret) {
>   		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
>   			      ret);
> -		return ret;
> +		goto err_clk;
>   	}
>   
>   	if (hdmi->chip_data == &rk3568_chip_data) {
> @@ -587,10 +622,21 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>   	 */
>   	if (IS_ERR(hdmi->hdmi)) {
>   		ret = PTR_ERR(hdmi->hdmi);
> -		drm_encoder_cleanup(encoder);
> -		clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +		goto err_bind;
>   	}
>   
> +	return 0;
> +
> +err_bind:
> +	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +	drm_encoder_cleanup(encoder);
> +err_clk:
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +err_avdd_1v8:
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
> +err_avdd_0v9:
>   	return ret;
>   }
>   
> @@ -601,6 +647,12 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
>   
>   	dw_hdmi_unbind(hdmi->hdmi);
>   	clk_bulk_disable_unprepare(RK_HDMI_NCLOCKS_HDMI, hdmi->clks);
> +
> +	if (hdmi->avdd_1v8)
> +		regulator_disable(hdmi->avdd_1v8);
> +
> +	if (hdmi->avdd_0v9)
> +		regulator_disable(hdmi->avdd_0v9);
>   }
>   
>   static const struct component_ops dw_hdmi_rockchip_ops = {
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 201+ messages in thread

end of thread, other threads:[~2021-12-07 17:03 UTC | newest]

Thread overview: 201+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-17 14:33 [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support Sascha Hauer
2021-11-17 14:33 ` Sascha Hauer
2021-11-17 14:33 ` Sascha Hauer
2021-11-17 14:33 ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 01/12] dt-bindings: display: rockchip: Add compatible for rk3568 HDMI Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-27 15:07   ` Heiko Stuebner
2021-11-27 15:07     ` Heiko Stuebner
2021-11-27 15:07     ` Heiko Stuebner
2021-11-27 15:07     ` Heiko Stuebner
2021-11-17 14:33 ` [PATCH 02/12] drm/rockchip: dw_hdmi: Do not leave clock enabled in error case Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 03/12] drm/rockchip: dw_hdmi: add rk3568 support Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 04/12] drm/rockchip: dw_hdmi: add regulator support Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-29 22:46   ` Rob Herring
2021-11-29 22:46     ` Rob Herring
2021-11-29 22:46     ` Rob Herring
2021-11-29 22:46     ` Rob Herring
2021-12-07 17:01   ` Robin Murphy
2021-12-07 17:01     ` Robin Murphy
2021-12-07 17:01     ` Robin Murphy
2021-12-07 17:01     ` Robin Murphy
2021-11-17 14:33 ` [PATCH 05/12] of: graph: Allow disabled endpoints Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 06/12] dt-bindings: " Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 07/12] dt-bindings: display: rockchip: Add binding for VOP2 Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 16:10   ` Rob Herring
2021-11-17 16:10     ` Rob Herring
2021-11-17 16:10     ` Rob Herring
2021-11-17 16:10     ` Rob Herring
2021-11-17 14:33 ` [PATCH 08/12] arm64: dts: rockchip: rk356x: Add VOP2 nodes Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-25 20:25   ` Johan Jonker
2021-11-25 20:25     ` Johan Jonker
2021-11-25 20:25     ` Johan Jonker
2021-11-25 20:25     ` Johan Jonker
2021-11-26  7:40     ` Sascha Hauer
2021-11-26  7:40       ` Sascha Hauer
2021-11-26  7:40       ` Sascha Hauer
2021-11-26  7:40       ` Sascha Hauer
2021-11-26  8:15       ` Heiko Stübner
2021-11-26  8:15         ` Heiko Stübner
2021-11-26  8:15         ` Heiko Stübner
2021-11-26  8:15         ` Heiko Stübner
2021-11-17 14:33 ` [PATCH 09/12] arm64: dts: rockchip: rk356x: Add HDMI nodes Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 15:13   ` Rob Herring
2021-11-17 15:13     ` Rob Herring
2021-11-17 15:13     ` Rob Herring
2021-11-17 15:13     ` Rob Herring
2021-12-01 16:04     ` Sascha Hauer
2021-12-01 16:04       ` Sascha Hauer
2021-12-01 16:04       ` Sascha Hauer
2021-12-01 16:04       ` Sascha Hauer
2021-11-17 14:33 ` [PATCH 10/12] arm64: dts: rockchip: rk3568-evb: Enable VOP2 and hdmi Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 15:19   ` Rob Herring
2021-11-17 15:19     ` Rob Herring
2021-11-17 15:19     ` Rob Herring
2021-11-17 15:19     ` Rob Herring
2021-12-02 15:34     ` Sascha Hauer
2021-12-02 15:34       ` Sascha Hauer
2021-12-02 15:34       ` Sascha Hauer
2021-12-02 15:34       ` Sascha Hauer
2021-12-02 15:41       ` Heiko Stübner
2021-12-02 15:41         ` Heiko Stübner
2021-12-02 15:41         ` Heiko Stübner
2021-12-02 15:41         ` Heiko Stübner
2021-12-02 16:09         ` Sascha Hauer
2021-12-02 16:09           ` Sascha Hauer
2021-12-02 16:09           ` Sascha Hauer
2021-12-02 16:09           ` Sascha Hauer
2021-11-17 15:20   ` Michael Riesch
2021-11-17 15:20     ` Michael Riesch
2021-11-17 15:20     ` Michael Riesch
2021-11-17 15:20     ` Michael Riesch
2021-11-17 15:44   ` [PATCH] arm64: dts: rockchip: enable vop2 and hdmi tx on quartz64a Michael Riesch
2021-11-17 15:44     ` Michael Riesch
2021-11-17 15:44     ` Michael Riesch
2021-11-17 15:44     ` Michael Riesch
2021-11-25 19:44     ` Johan Jonker
2021-11-25 19:44       ` Johan Jonker
2021-11-25 19:44       ` Johan Jonker
2021-11-25 19:44       ` Johan Jonker
2021-11-17 14:33 ` [PATCH 11/12] drm/rockchip: Make VOP driver optional Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:40   ` Heiko Stübner
2021-11-17 14:40     ` Heiko Stübner
2021-11-17 14:40     ` Heiko Stübner
2021-11-17 14:40     ` Heiko Stübner
2021-11-17 14:50     ` Sascha Hauer
2021-11-17 14:50       ` Sascha Hauer
2021-11-17 14:50       ` Sascha Hauer
2021-11-17 14:50       ` Sascha Hauer
2021-11-17 15:16       ` Heiko Stübner
2021-11-17 15:16         ` Heiko Stübner
2021-11-17 15:16         ` Heiko Stübner
2021-11-17 15:16         ` Heiko Stübner
2021-11-17 14:33 ` [PATCH 12/12] drm: rockchip: Add VOP2 driver Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 14:33   ` Sascha Hauer
2021-11-17 18:05   ` Nicolas Frattaroli
2021-11-17 18:05     ` Nicolas Frattaroli
2021-11-17 18:05     ` Nicolas Frattaroli
2021-11-17 18:05     ` Nicolas Frattaroli
2021-11-17 18:38     ` Dan Johansen
2021-11-17 19:45     ` Sascha Hauer
2021-11-17 19:45       ` Sascha Hauer
2021-11-17 19:45       ` Sascha Hauer
2021-11-17 19:45       ` Sascha Hauer
2021-11-26  6:44   ` kernel test robot
2021-11-26  6:44     ` kernel test robot
2021-11-26  6:44     ` kernel test robot
2021-11-26  6:44     ` kernel test robot
2021-11-26  6:44     ` kernel test robot
2021-11-17 14:54 ` [PATCH v1 00/12] drm/rockchip: RK356x VOP2 support Rob Herring
2021-11-17 14:54   ` Rob Herring
2021-11-17 14:54   ` Rob Herring
2021-11-17 14:54   ` Rob Herring
2021-11-17 15:41   ` Sascha Hauer
2021-11-17 15:41     ` Sascha Hauer
2021-11-17 15:41     ` Sascha Hauer
2021-11-17 15:41     ` Sascha Hauer
2021-11-18  1:27 ` Kever Yang
2021-11-18  1:27   ` Kever Yang
2021-11-18  1:27   ` Kever Yang
2021-11-18  1:27   ` Kever Yang
2021-11-18  9:26   ` Heiko Stübner
2021-11-18  9:26     ` Heiko Stübner
2021-11-18  9:26     ` Heiko Stübner
2021-11-18  9:26     ` Heiko Stübner
2021-11-18  9:53     ` Daniel Stone
2021-11-18  9:53       ` Daniel Stone
2021-11-18  9:53       ` Daniel Stone
2021-11-18  9:53       ` Daniel Stone
2021-11-18 10:50       ` Kever Yang
2021-11-18 10:50         ` Kever Yang
2021-11-18 10:50         ` Kever Yang
2021-11-18 10:50         ` Kever Yang
2021-11-18 11:08         ` Michael Riesch
2021-11-18 11:08           ` Michael Riesch
2021-11-18 11:08           ` Michael Riesch
2021-11-18 11:08           ` Michael Riesch
2021-11-18 12:07         ` Daniel Stone
2021-11-18 12:07           ` Daniel Stone
2021-11-18 12:07           ` Daniel Stone
2021-11-18 12:07           ` Daniel Stone
2021-11-18 13:14           ` Andy Yan
2021-11-18 13:14             ` Andy Yan
2021-11-18 13:14             ` Andy Yan
2021-11-18 13:14             ` Andy Yan
2021-11-18 13:24             ` Daniel Stone
2021-11-18 13:24               ` Daniel Stone
2021-11-18 13:24               ` Daniel Stone
2021-11-18 13:24               ` Daniel Stone
2021-11-18 10:03     ` Sascha Hauer
2021-11-18 10:03       ` Sascha Hauer
2021-11-18 10:03       ` Sascha Hauer
2021-11-18 10:03       ` Sascha Hauer
2021-11-21 23:18 ` Alex Bee
2021-11-21 23:18   ` Alex Bee
2021-11-21 23:18   ` Alex Bee
2021-11-21 23:18   ` Alex Bee
2021-11-22  8:10   ` Sascha Hauer
2021-11-22  8:10     ` Sascha Hauer
2021-11-22  8:10     ` Sascha Hauer
2021-11-22  8:10     ` Sascha Hauer
2021-11-22 17:47     ` Alex Bee
2021-11-22 17:47       ` Alex Bee
2021-11-22 17:47       ` Alex Bee
2021-11-22 17:47       ` Alex Bee
2021-11-22 19:21       ` Robin Murphy
2021-11-22 19:21         ` Robin Murphy
2021-11-22 19:21         ` Robin Murphy
2021-11-22 19:21         ` Robin Murphy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.