All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/11] Initial Allwinner Display Engine 2.0 Support
@ 2017-03-29 19:46 ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

This patchset is the initial patchset for Allwinner DE2 support.

It contains the support of clocks in DE2 and the mixers in DE2.

The SoC used to develop this patchset is V3s, as V3s is the simplest
one of the SoCs that have DE2.
(Allwinner V3s features only one mixer, although its clock control
unit contains support for second mixer's clock; and its only video
output is RGB LCD, which is already supported in our TCON driver)

The last patch is only a testing patch, it shouldn't be merged; and
for the patch to be really usable, the RFC fix of the TCON driver [1]
is needed.

No HDMI, TV encoder or other internal bridges' support is included
in this patchset, which makes it currently not usable on H3.

Thanks to Jean-Francois Moine and Jernej Skrabec for their efforts
to discover the internal of DE2!

[1] https://lists.freedesktop.org/archives/dri-devel/2016-December/126264.html

Icenowy Zheng (11):
  dt-bindings: add binding for the Allwinner DE2 CCU
  clk: sunxi-ng: add support for DE2 CCU
  dt-bindings: add bindings for DE2 on V3s SoC
  drm/sun4i: abstruct the layer type
  drm/sun4i: abstract a mixer type
  drm/sun4i: add support for Allwinner DE2 mixers
  drm/sun4i: Add compatible string for V3s display engine
  drm/sun4i: tcon: add support for V3s TCON
  ARM: dts: sun8i: add DE2 nodes for V3s SoC
  ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
  [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero

 .../devicetree/bindings/clock/sun8i-de2.txt        |  31 ++
 .../bindings/display/sunxi/sun4i-drm.txt           |  37 +-
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts      |  36 ++
 arch/arm/boot/dts/sun8i-v3s.dtsi                   |  96 +++++
 drivers/clk/sunxi-ng/Kconfig                       |   5 +
 drivers/clk/sunxi-ng/Makefile                      |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c               | 204 +++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h               |  28 ++
 drivers/gpu/drm/sun4i/Kconfig                      |  20 ++
 drivers/gpu/drm/sun4i/Makefile                     |  10 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |  26 +-
 drivers/gpu/drm/sun4i/sun4i_backend.h              |   5 -
 drivers/gpu/drm/sun4i/sun4i_crtc.c                 |  31 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h                 |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   4 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   3 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c                |  22 +-
 drivers/gpu/drm/sun4i/sun4i_layer.h                |   6 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |   7 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c                   |   8 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c                | 156 +++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h                |  35 ++
 drivers/gpu/drm/sun4i/sun8i_mixer.c                | 386 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h                | 131 +++++++
 drivers/gpu/drm/sun4i/sunxi_layer.h                |  17 +
 drivers/gpu/drm/sun4i/sunxi_mixer.h                |  22 ++
 include/dt-bindings/clock/sun8i-de2.h              |  54 +++
 include/dt-bindings/reset/sun8i-de2.h              |  50 +++
 28 files changed, 1391 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

-- 
2.12.0

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

* [PATCH v3 00/11] Initial Allwinner Display Engine 2.0 Support
@ 2017-03-29 19:46 ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

This patchset is the initial patchset for Allwinner DE2 support.

It contains the support of clocks in DE2 and the mixers in DE2.

The SoC used to develop this patchset is V3s, as V3s is the simplest
one of the SoCs that have DE2.
(Allwinner V3s features only one mixer, although its clock control
unit contains support for second mixer's clock; and its only video
output is RGB LCD, which is already supported in our TCON driver)

The last patch is only a testing patch, it shouldn't be merged; and
for the patch to be really usable, the RFC fix of the TCON driver [1]
is needed.

No HDMI, TV encoder or other internal bridges' support is included
in this patchset, which makes it currently not usable on H3.

Thanks to Jean-Francois Moine and Jernej Skrabec for their efforts
to discover the internal of DE2!

[1] https://lists.freedesktop.org/archives/dri-devel/2016-December/126264.html

Icenowy Zheng (11):
  dt-bindings: add binding for the Allwinner DE2 CCU
  clk: sunxi-ng: add support for DE2 CCU
  dt-bindings: add bindings for DE2 on V3s SoC
  drm/sun4i: abstruct the layer type
  drm/sun4i: abstract a mixer type
  drm/sun4i: add support for Allwinner DE2 mixers
  drm/sun4i: Add compatible string for V3s display engine
  drm/sun4i: tcon: add support for V3s TCON
  ARM: dts: sun8i: add DE2 nodes for V3s SoC
  ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
  [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero

 .../devicetree/bindings/clock/sun8i-de2.txt        |  31 ++
 .../bindings/display/sunxi/sun4i-drm.txt           |  37 +-
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts      |  36 ++
 arch/arm/boot/dts/sun8i-v3s.dtsi                   |  96 +++++
 drivers/clk/sunxi-ng/Kconfig                       |   5 +
 drivers/clk/sunxi-ng/Makefile                      |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c               | 204 +++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h               |  28 ++
 drivers/gpu/drm/sun4i/Kconfig                      |  20 ++
 drivers/gpu/drm/sun4i/Makefile                     |  10 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |  26 +-
 drivers/gpu/drm/sun4i/sun4i_backend.h              |   5 -
 drivers/gpu/drm/sun4i/sun4i_crtc.c                 |  31 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h                 |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   4 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   3 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c                |  22 +-
 drivers/gpu/drm/sun4i/sun4i_layer.h                |   6 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |   7 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c                   |   8 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c                | 156 +++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h                |  35 ++
 drivers/gpu/drm/sun4i/sun8i_mixer.c                | 386 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h                | 131 +++++++
 drivers/gpu/drm/sun4i/sunxi_layer.h                |  17 +
 drivers/gpu/drm/sun4i/sunxi_mixer.h                |  22 ++
 include/dt-bindings/clock/sun8i-de2.h              |  54 +++
 include/dt-bindings/reset/sun8i-de2.h              |  50 +++
 28 files changed, 1391 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

-- 
2.12.0

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

* [PATCH v3 00/11] Initial Allwinner Display Engine 2.0 Support
@ 2017-03-29 19:46 ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset is the initial patchset for Allwinner DE2 support.

It contains the support of clocks in DE2 and the mixers in DE2.

The SoC used to develop this patchset is V3s, as V3s is the simplest
one of the SoCs that have DE2.
(Allwinner V3s features only one mixer, although its clock control
unit contains support for second mixer's clock; and its only video
output is RGB LCD, which is already supported in our TCON driver)

The last patch is only a testing patch, it shouldn't be merged; and
for the patch to be really usable, the RFC fix of the TCON driver [1]
is needed.

No HDMI, TV encoder or other internal bridges' support is included
in this patchset, which makes it currently not usable on H3.

Thanks to Jean-Francois Moine and Jernej Skrabec for their efforts
to discover the internal of DE2!

[1] https://lists.freedesktop.org/archives/dri-devel/2016-December/126264.html

Icenowy Zheng (11):
  dt-bindings: add binding for the Allwinner DE2 CCU
  clk: sunxi-ng: add support for DE2 CCU
  dt-bindings: add bindings for DE2 on V3s SoC
  drm/sun4i: abstruct the layer type
  drm/sun4i: abstract a mixer type
  drm/sun4i: add support for Allwinner DE2 mixers
  drm/sun4i: Add compatible string for V3s display engine
  drm/sun4i: tcon: add support for V3s TCON
  ARM: dts: sun8i: add DE2 nodes for V3s SoC
  ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
  [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero

 .../devicetree/bindings/clock/sun8i-de2.txt        |  31 ++
 .../bindings/display/sunxi/sun4i-drm.txt           |  37 +-
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts      |  36 ++
 arch/arm/boot/dts/sun8i-v3s.dtsi                   |  96 +++++
 drivers/clk/sunxi-ng/Kconfig                       |   5 +
 drivers/clk/sunxi-ng/Makefile                      |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c               | 204 +++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h               |  28 ++
 drivers/gpu/drm/sun4i/Kconfig                      |  20 ++
 drivers/gpu/drm/sun4i/Makefile                     |  10 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |  26 +-
 drivers/gpu/drm/sun4i/sun4i_backend.h              |   5 -
 drivers/gpu/drm/sun4i/sun4i_crtc.c                 |  31 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h                 |  10 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   4 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   3 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c                |  22 +-
 drivers/gpu/drm/sun4i/sun4i_layer.h                |   6 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |   7 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c                   |   8 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c                | 156 +++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h                |  35 ++
 drivers/gpu/drm/sun4i/sun8i_mixer.c                | 386 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h                | 131 +++++++
 drivers/gpu/drm/sun4i/sunxi_layer.h                |  17 +
 drivers/gpu/drm/sun4i/sunxi_mixer.h                |  22 ++
 include/dt-bindings/clock/sun8i-de2.h              |  54 +++
 include/dt-bindings/reset/sun8i-de2.h              |  50 +++
 28 files changed, 1391 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

-- 
2.12.0

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

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner "Display Engine 2.0" contains some clock controls in it.

In order to add them as clock drivers, we need a device tree binding.
Add the binding here.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

 .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt

diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..34cf79c05f13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun50i-a64-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@01000000 {
+	compatible = "allwinner,sun50i-a64-de2-clk";
+	reg = <0x01000000 0x100000>;
+	clocks = <&ccu CLK_DE>,
+		 <&ccu CLK_BUS_DE>;
+	clock-names = "mod",
+		      "bus";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
-- 
2.12.0

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

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Allwinner "Display Engine 2.0" contains some clock controls in it.

In order to add them as clock drivers, we need a device tree binding.
Add the binding here.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

 .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt

diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..34cf79c05f13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun50i-a64-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@01000000 {
+	compatible = "allwinner,sun50i-a64-de2-clk";
+	reg = <0x01000000 0x100000>;
+	clocks = <&ccu CLK_DE>,
+		 <&ccu CLK_BUS_DE>;
+	clock-names = "mod",
+		      "bus";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
-- 
2.12.0

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

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner "Display Engine 2.0" contains some clock controls in it.

In order to add them as clock drivers, we need a device tree binding.
Add the binding here.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

 .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt

diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..34cf79c05f13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun50i-a64-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@01000000 {
+	compatible = "allwinner,sun50i-a64-de2-clk";
+	reg = <0x01000000 0x100000>;
+	clocks = <&ccu CLK_DE>,
+		 <&ccu CLK_BUS_DE>;
+	clock-names = "mod",
+		      "bus";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner "Display Engine 2.0" contains some clock controls in it.

In order to add them as clock drivers, we need a device tree binding.
Add the binding here.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

 .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt

diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..34cf79c05f13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+		- "allwinner,sun8i-a83t-de2-clk"
+		- "allwinner,sun50i-a64-de2-clk"
+		- "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+	  Three are needed:
+  - "mod": the display engine module clock
+  - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock at 01000000 {
+	compatible = "allwinner,sun50i-a64-de2-clk";
+	reg = <0x01000000 0x100000>;
+	clocks = <&ccu CLK_DE>,
+		 <&ccu CLK_BUS_DE>;
+	clock-names = "mod",
+		      "bus";
+	resets = <&ccu RST_BUS_DE>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
-- 
2.12.0

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

* [PATCH v3 02/11] clk: sunxi-ng: add support for DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.

Add a sunxi-ng style driver for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.

 drivers/clk/sunxi-ng/Kconfig          |   5 +
 drivers/clk/sunxi-ng/Makefile         |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  | 204 ++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |  28 +++++
 include/dt-bindings/clock/sun8i-de2.h |  54 +++++++++
 include/dt-bindings/reset/sun8i-de2.h |  50 +++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 8af8f4be8e3b..778c141dd966 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -140,6 +140,11 @@ config SUN8I_V3S_CCU
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_GATE
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
 	select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
+		      0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
+		      0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
+		      0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
+		      0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
+		      0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
+		      0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+	&mixer0_clk.common,
+	&mixer1_clk.common,
+	&wb_clk.common,
+
+	&bus_mixer0_clk.common,
+	&bus_mixer1_clk.common,
+	&bus_wb_clk.common,
+
+	&mixer0_div_clk.common,
+	&mixer1_div_clk.common,
+	&wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+	.hws	= {
+		[CLK_MIXER0]		= &mixer0_clk.common.hw,
+		[CLK_MIXER1]		= &mixer1_clk.common.hw,
+		[CLK_WB]		= &wb_clk.common.hw,
+
+		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
+		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
+		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
+
+		[CLK_MIXER0_DIV]	= &mixer1_div_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer0_div_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	/*
+	 * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+	 * only RST_WB is exported here.
+	 */
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	[RST_MIXER1]	= { 0x08, BIT(1) },
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun8i_a83t_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun50i_a64_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct clk *bus_clk;
+	struct reset_control *rstc;
+	void __iomem *reg;
+	const struct sunxi_ccu_desc *ccu_desc;
+	int ret;
+
+	ccu_desc = of_device_get_match_data(&pdev->dev);
+	if (!ccu_desc)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(bus_clk)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+		return ret;
+	}
+
+	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Couldn't get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* The bus clock needs to be enabled for us to access the registers */
+	ret = clk_prepare_enable(bus_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+		return ret;
+	}
+
+	/* The reset control needs to be asserted for the controls to work */
+	ret = reset_control_deassert(rstc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Couldn't deassert reset control: %d\n", ret);
+		goto err_disable_clk;
+	}
+
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+	if (ret)
+		goto err_assert_reset;
+
+	return 0;
+
+err_assert_reset:
+	reset_control_assert(rstc);
+err_disable_clk:
+	clk_disable_unprepare(bus_clk);
+	return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-a83t-de2-clk",
+		.data = &sun8i_a83t_de2_clk_desc,
+	},
+	{
+		.compatible = "allwinner,sun50i-h5-de2-clk",
+		.data = &sun50i_a64_de2_clk_desc,
+	},
+	/*
+	 * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+	 * DE2 really working.
+	 * So there's currently no A64 compatible here.
+	 * H5 shares the same reset line with A64, so here H5 is using the
+	 * clock description of A64.
+	 */
+	{ }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+	.probe	= sunxi_de2_clk_probe,
+	.driver	= {
+		.name	= "sunxi-de2-clks",
+		.of_match_table	= sunxi_de2_clk_ids,
+	},
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV	3
+#define CLK_MIXER1_DIV	4
+#define CLK_WB_DIV	5
+
+#define CLK_NUMBER	(CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0		0
+#define CLK_BUS_MIXER1		1
+#define CLK_BUS_WB		2
+
+#define CLK_MIXER0		6
+#define CLK_MIXER1		7
+#define CLK_WB			8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0	0
+#define RST_MIXER1	1
+#define RST_WB		2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
-- 
2.12.0

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

* [PATCH v3 02/11] clk: sunxi-ng: add support for DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.

Add a sunxi-ng style driver for it.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.

 drivers/clk/sunxi-ng/Kconfig          |   5 +
 drivers/clk/sunxi-ng/Makefile         |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  | 204 ++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |  28 +++++
 include/dt-bindings/clock/sun8i-de2.h |  54 +++++++++
 include/dt-bindings/reset/sun8i-de2.h |  50 +++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 8af8f4be8e3b..778c141dd966 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -140,6 +140,11 @@ config SUN8I_V3S_CCU
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_GATE
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
 	select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
+		      0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
+		      0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
+		      0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
+		      0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
+		      0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
+		      0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+	&mixer0_clk.common,
+	&mixer1_clk.common,
+	&wb_clk.common,
+
+	&bus_mixer0_clk.common,
+	&bus_mixer1_clk.common,
+	&bus_wb_clk.common,
+
+	&mixer0_div_clk.common,
+	&mixer1_div_clk.common,
+	&wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+	.hws	= {
+		[CLK_MIXER0]		= &mixer0_clk.common.hw,
+		[CLK_MIXER1]		= &mixer1_clk.common.hw,
+		[CLK_WB]		= &wb_clk.common.hw,
+
+		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
+		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
+		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
+
+		[CLK_MIXER0_DIV]	= &mixer1_div_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer0_div_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	/*
+	 * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+	 * only RST_WB is exported here.
+	 */
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	[RST_MIXER1]	= { 0x08, BIT(1) },
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun8i_a83t_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun50i_a64_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct clk *bus_clk;
+	struct reset_control *rstc;
+	void __iomem *reg;
+	const struct sunxi_ccu_desc *ccu_desc;
+	int ret;
+
+	ccu_desc = of_device_get_match_data(&pdev->dev);
+	if (!ccu_desc)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(bus_clk)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+		return ret;
+	}
+
+	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Couldn't get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* The bus clock needs to be enabled for us to access the registers */
+	ret = clk_prepare_enable(bus_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+		return ret;
+	}
+
+	/* The reset control needs to be asserted for the controls to work */
+	ret = reset_control_deassert(rstc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Couldn't deassert reset control: %d\n", ret);
+		goto err_disable_clk;
+	}
+
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+	if (ret)
+		goto err_assert_reset;
+
+	return 0;
+
+err_assert_reset:
+	reset_control_assert(rstc);
+err_disable_clk:
+	clk_disable_unprepare(bus_clk);
+	return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-a83t-de2-clk",
+		.data = &sun8i_a83t_de2_clk_desc,
+	},
+	{
+		.compatible = "allwinner,sun50i-h5-de2-clk",
+		.data = &sun50i_a64_de2_clk_desc,
+	},
+	/*
+	 * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+	 * DE2 really working.
+	 * So there's currently no A64 compatible here.
+	 * H5 shares the same reset line with A64, so here H5 is using the
+	 * clock description of A64.
+	 */
+	{ }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+	.probe	= sunxi_de2_clk_probe,
+	.driver	= {
+		.name	= "sunxi-de2-clks",
+		.of_match_table	= sunxi_de2_clk_ids,
+	},
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV	3
+#define CLK_MIXER1_DIV	4
+#define CLK_WB_DIV	5
+
+#define CLK_NUMBER	(CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0		0
+#define CLK_BUS_MIXER1		1
+#define CLK_BUS_WB		2
+
+#define CLK_MIXER0		6
+#define CLK_MIXER1		7
+#define CLK_WB			8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0	0
+#define RST_MIXER1	1
+#define RST_WB		2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
-- 
2.12.0

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

* [PATCH v3 02/11] clk: sunxi-ng: add support for DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.

Add a sunxi-ng style driver for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.

 drivers/clk/sunxi-ng/Kconfig          |   5 +
 drivers/clk/sunxi-ng/Makefile         |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  | 204 ++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |  28 +++++
 include/dt-bindings/clock/sun8i-de2.h |  54 +++++++++
 include/dt-bindings/reset/sun8i-de2.h |  50 +++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 8af8f4be8e3b..778c141dd966 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -140,6 +140,11 @@ config SUN8I_V3S_CCU
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_GATE
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
 	select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
+		      0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
+		      0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
+		      0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
+		      0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
+		      0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
+		      0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+	&mixer0_clk.common,
+	&mixer1_clk.common,
+	&wb_clk.common,
+
+	&bus_mixer0_clk.common,
+	&bus_mixer1_clk.common,
+	&bus_wb_clk.common,
+
+	&mixer0_div_clk.common,
+	&mixer1_div_clk.common,
+	&wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+	.hws	= {
+		[CLK_MIXER0]		= &mixer0_clk.common.hw,
+		[CLK_MIXER1]		= &mixer1_clk.common.hw,
+		[CLK_WB]		= &wb_clk.common.hw,
+
+		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
+		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
+		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
+
+		[CLK_MIXER0_DIV]	= &mixer1_div_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer0_div_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	/*
+	 * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+	 * only RST_WB is exported here.
+	 */
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	[RST_MIXER1]	= { 0x08, BIT(1) },
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun8i_a83t_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun50i_a64_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct clk *bus_clk;
+	struct reset_control *rstc;
+	void __iomem *reg;
+	const struct sunxi_ccu_desc *ccu_desc;
+	int ret;
+
+	ccu_desc = of_device_get_match_data(&pdev->dev);
+	if (!ccu_desc)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(bus_clk)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+		return ret;
+	}
+
+	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Couldn't get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* The bus clock needs to be enabled for us to access the registers */
+	ret = clk_prepare_enable(bus_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+		return ret;
+	}
+
+	/* The reset control needs to be asserted for the controls to work */
+	ret = reset_control_deassert(rstc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Couldn't deassert reset control: %d\n", ret);
+		goto err_disable_clk;
+	}
+
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+	if (ret)
+		goto err_assert_reset;
+
+	return 0;
+
+err_assert_reset:
+	reset_control_assert(rstc);
+err_disable_clk:
+	clk_disable_unprepare(bus_clk);
+	return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-a83t-de2-clk",
+		.data = &sun8i_a83t_de2_clk_desc,
+	},
+	{
+		.compatible = "allwinner,sun50i-h5-de2-clk",
+		.data = &sun50i_a64_de2_clk_desc,
+	},
+	/*
+	 * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+	 * DE2 really working.
+	 * So there's currently no A64 compatible here.
+	 * H5 shares the same reset line with A64, so here H5 is using the
+	 * clock description of A64.
+	 */
+	{ }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+	.probe	= sunxi_de2_clk_probe,
+	.driver	= {
+		.name	= "sunxi-de2-clks",
+		.of_match_table	= sunxi_de2_clk_ids,
+	},
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV	3
+#define CLK_MIXER1_DIV	4
+#define CLK_WB_DIV	5
+
+#define CLK_NUMBER	(CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0		0
+#define CLK_BUS_MIXER1		1
+#define CLK_BUS_WB		2
+
+#define CLK_MIXER0		6
+#define CLK_MIXER1		7
+#define CLK_WB			8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0	0
+#define RST_MIXER1	1
+#define RST_WB		2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 02/11] clk: sunxi-ng: add support for DE2 CCU
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.

Add a sunxi-ng style driver for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.

 drivers/clk/sunxi-ng/Kconfig          |   5 +
 drivers/clk/sunxi-ng/Makefile         |   1 +
 drivers/clk/sunxi-ng/ccu-sun8i-de2.c  | 204 ++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h  |  28 +++++
 include/dt-bindings/clock/sun8i-de2.h |  54 +++++++++
 include/dt-bindings/reset/sun8i-de2.h |  50 +++++++++
 6 files changed, 342 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 8af8f4be8e3b..778c141dd966 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -140,6 +140,11 @@ config SUN8I_V3S_CCU
 	default MACH_SUN8I
 	depends on MACH_SUN8I || COMPILE_TEST
 
+config SUN8I_DE2_CCU
+	bool "Support for the Allwinner SoCs DE2 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_GATE
+
 config SUN9I_A80_CCU
 	bool "Support for the Allwinner A80 CCU"
 	select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)	+= ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)	+= ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU)	+= ccu-sun8i-de2.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)	+= ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
+		      0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
+		      0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
+		      0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
+		      0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
+		      0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
+		      0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+		   CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+		   CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+	&mixer0_clk.common,
+	&mixer1_clk.common,
+	&wb_clk.common,
+
+	&bus_mixer0_clk.common,
+	&bus_mixer1_clk.common,
+	&bus_wb_clk.common,
+
+	&mixer0_div_clk.common,
+	&mixer1_div_clk.common,
+	&wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+	.hws	= {
+		[CLK_MIXER0]		= &mixer0_clk.common.hw,
+		[CLK_MIXER1]		= &mixer1_clk.common.hw,
+		[CLK_WB]		= &wb_clk.common.hw,
+
+		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
+		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
+		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
+
+		[CLK_MIXER0_DIV]	= &mixer1_div_clk.common.hw,
+		[CLK_MIXER1_DIV]	= &mixer0_div_clk.common.hw,
+		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	/*
+	 * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+	 * only RST_WB is exported here.
+	 */
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+	[RST_MIXER0]	= { 0x08, BIT(0) },
+	[RST_MIXER1]	= { 0x08, BIT(1) },
+	[RST_WB]	= { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun8i_a83t_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+	.ccu_clks	= sunxi_de2_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sunxi_de2_clks),
+
+	.hw_clks	= &sunxi_de2_hw_clks,
+
+	.resets		= sun50i_a64_de2_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct clk *bus_clk;
+	struct reset_control *rstc;
+	void __iomem *reg;
+	const struct sunxi_ccu_desc *ccu_desc;
+	int ret;
+
+	ccu_desc = of_device_get_match_data(&pdev->dev);
+	if (!ccu_desc)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(bus_clk)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+		return ret;
+	}
+
+	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(bus_clk);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Couldn't get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* The bus clock needs to be enabled for us to access the registers */
+	ret = clk_prepare_enable(bus_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+		return ret;
+	}
+
+	/* The reset control needs to be asserted for the controls to work */
+	ret = reset_control_deassert(rstc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Couldn't deassert reset control: %d\n", ret);
+		goto err_disable_clk;
+	}
+
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+	if (ret)
+		goto err_assert_reset;
+
+	return 0;
+
+err_assert_reset:
+	reset_control_assert(rstc);
+err_disable_clk:
+	clk_disable_unprepare(bus_clk);
+	return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-a83t-de2-clk",
+		.data = &sun8i_a83t_de2_clk_desc,
+	},
+	{
+		.compatible = "allwinner,sun50i-h5-de2-clk",
+		.data = &sun50i_a64_de2_clk_desc,
+	},
+	/*
+	 * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+	 * DE2 really working.
+	 * So there's currently no A64 compatible here.
+	 * H5 shares the same reset line with A64, so here H5 is using the
+	 * clock description of A64.
+	 */
+	{ }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+	.probe	= sunxi_de2_clk_probe,
+	.driver	= {
+		.name	= "sunxi-de2-clks",
+		.of_match_table	= sunxi_de2_clk_ids,
+	},
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV	3
+#define CLK_MIXER1_DIV	4
+#define CLK_WB_DIV	5
+
+#define CLK_NUMBER	(CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0		0
+#define CLK_BUS_MIXER1		1
+#define CLK_BUS_WB		2
+
+#define CLK_MIXER0		6
+#define CLK_MIXER1		7
+#define CLK_WB			8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0	0
+#define RST_MIXER1	1
+#define RST_WB		2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
-- 
2.12.0

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

* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.

Add document for it (new compatibles and the new "mixer" part).

The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Remove the description of having a BE directly as allwinner,pipeline.

 .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..38de5e96f359 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
@@ -52,7 +52,12 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -137,6 +142,26 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the outputs
 
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-v3s-de2-mixer
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * bus: the backend interface clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
 
 Display Engine Pipeline
 -----------------------
@@ -151,9 +176,13 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-    frontends available.
+    pipeline entry point. For SoCs with original DE (currently
+    all SoCs supported by display engine except V3s), this
+    phandle should be a display frontend; for SoCs with DE2,
+    this phandle should be a mixer.
 
 Example:
 
-- 
2.12.0

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

* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.

Add document for it (new compatibles and the new "mixer" part).

The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Remove the description of having a BE directly as allwinner,pipeline.

 .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..38de5e96f359 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
@@ -52,7 +52,12 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -137,6 +142,26 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the outputs
 
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-v3s-de2-mixer
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * bus: the backend interface clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
 
 Display Engine Pipeline
 -----------------------
@@ -151,9 +176,13 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-    frontends available.
+    pipeline entry point. For SoCs with original DE (currently
+    all SoCs supported by display engine except V3s), this
+    phandle should be a display frontend; for SoCs with DE2,
+    this phandle should be a mixer.
 
 Example:
 
-- 
2.12.0

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

* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.

Add document for it (new compatibles and the new "mixer" part).

The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Remove the description of having a BE directly as allwinner,pipeline.

 .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..38de5e96f359 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
@@ -52,7 +52,12 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -137,6 +142,26 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the outputs
 
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-v3s-de2-mixer
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * bus: the backend interface clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
 
 Display Engine Pipeline
 -----------------------
@@ -151,9 +176,13 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-    frontends available.
+    pipeline entry point. For SoCs with original DE (currently
+    all SoCs supported by display engine except V3s), this
+    phandle should be a display frontend; for SoCs with DE2,
+    this phandle should be a mixer.
 
 Example:
 
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.

Add document for it (new compatibles and the new "mixer" part).

The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Remove the description of having a BE directly as allwinner,pipeline.

 .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
 1 file changed, 33 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..38de5e96f359 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
    * allwinner,sun6i-a31-tcon
    * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
+   * allwinner,sun8i-v3s-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
    - 'ahb': the interface clocks
-   - 'tcon-ch0': The clock driving the TCON channel 0
  - resets: phandles to the reset controllers driving the encoder
    - "lcd": the reset line for the TCON channel 0
 
@@ -52,7 +52,12 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+   - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -137,6 +142,26 @@ Required properties:
   Documentation/devicetree/bindings/media/video-interfaces.txt. The
   first port should be the input endpoints, the second one the outputs
 
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-v3s-de2-mixer
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * bus: the backend interface clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
 
 Display Engine Pipeline
 -----------------------
@@ -151,9 +176,13 @@ Required properties:
     * allwinner,sun6i-a31-display-engine
     * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
+    * allwinner,sun8i-v3s-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
-    frontends available.
+    pipeline entry point. For SoCs with original DE (currently
+    all SoCs supported by display engine except V3s), this
+    phandle should be a display frontend; for SoCs with DE2,
+    this phandle should be a mixer.
 
 Example:
 
-- 
2.12.0

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layer.

Abstract the layer type to void * and a ops struct, which contains the
only function used by crtc -- get the drm_plane struct of the layer.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
 drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
 5 files changed, 49 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..33854ee7f636 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -29,6 +29,7 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
@@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 
 	/* find primary and cursor planes for drm_crtc_init_with_planes */
 	for (i = 0; scrtc->layers[i]; i++) {
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		switch (layer->plane.type) {
+		switch (plane->type) {
 		case DRM_PLANE_TYPE_PRIMARY:
-			primary = &layer->plane;
+			primary = plane;
 			break;
 		case DRM_PLANE_TYPE_CURSOR:
-			cursor = &layer->plane;
+			cursor = plane;
 			break;
 		default:
 			break;
@@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	/* Set possible_crtcs to this crtc for overlay planes */
 	for (i = 0; scrtc->layers[i]; i++) {
 		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
-			layer->plane.possible_crtcs = possible_crtcs;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			plane->possible_crtcs = possible_crtcs;
 	}
 
 	return scrtc;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..a4036ee44cf8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,8 @@ struct sun4i_crtc {
 
 	struct sun4i_backend		*backend;
 	struct sun4i_tcon		*tcon;
-	struct sun4i_layer		**layers;
+	void				**layers;
+	const struct sunxi_layer_ops	*layer_ops;
 };
 
 static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..bc4a70d6968b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,7 +16,9 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
@@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	},
 };
 
+static struct drm_plane *sun4i_layer_get_plane(void *layer)
+{
+	struct sun4i_layer *sun4i_layer = layer;
+
+	return &sun4i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun4i_layer_get_plane,
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 						struct sun4i_backend *backend,
 						const struct sun4i_plane_desc *plane)
@@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend)
+				       struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
+	struct sun4i_backend *backend = crtc->backend;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 		layers[i] = layer;
 	};
 
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
 	return layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..425eea7b9e3b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend);
+				       struct sun4i_crtc *crtc);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
new file mode 100644
index 000000000000..d8838ec39299
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_LAYER_H_
+#define _SUNXI_LAYER_H_
+
+struct sunxi_layer_ops {
+	struct drm_plane *(*get_plane)(void *layer);
+};
+
+#endif /* _SUNXI_LAYER_H_ */
-- 
2.12.0

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layer.

Abstract the layer type to void * and a ops struct, which contains the
only function used by crtc -- get the drm_plane struct of the layer.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
 drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
 5 files changed, 49 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..33854ee7f636 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -29,6 +29,7 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
@@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 
 	/* find primary and cursor planes for drm_crtc_init_with_planes */
 	for (i = 0; scrtc->layers[i]; i++) {
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		switch (layer->plane.type) {
+		switch (plane->type) {
 		case DRM_PLANE_TYPE_PRIMARY:
-			primary = &layer->plane;
+			primary = plane;
 			break;
 		case DRM_PLANE_TYPE_CURSOR:
-			cursor = &layer->plane;
+			cursor = plane;
 			break;
 		default:
 			break;
@@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	/* Set possible_crtcs to this crtc for overlay planes */
 	for (i = 0; scrtc->layers[i]; i++) {
 		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
-			layer->plane.possible_crtcs = possible_crtcs;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			plane->possible_crtcs = possible_crtcs;
 	}
 
 	return scrtc;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..a4036ee44cf8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,8 @@ struct sun4i_crtc {
 
 	struct sun4i_backend		*backend;
 	struct sun4i_tcon		*tcon;
-	struct sun4i_layer		**layers;
+	void				**layers;
+	const struct sunxi_layer_ops	*layer_ops;
 };
 
 static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..bc4a70d6968b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,7 +16,9 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
@@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	},
 };
 
+static struct drm_plane *sun4i_layer_get_plane(void *layer)
+{
+	struct sun4i_layer *sun4i_layer = layer;
+
+	return &sun4i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun4i_layer_get_plane,
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 						struct sun4i_backend *backend,
 						const struct sun4i_plane_desc *plane)
@@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend)
+				       struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
+	struct sun4i_backend *backend = crtc->backend;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 		layers[i] = layer;
 	};
 
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
 	return layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..425eea7b9e3b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend);
+				       struct sun4i_crtc *crtc);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
new file mode 100644
index 000000000000..d8838ec39299
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_LAYER_H_
+#define _SUNXI_LAYER_H_
+
+struct sunxi_layer_ops {
+	struct drm_plane *(*get_plane)(void *layer);
+};
+
+#endif /* _SUNXI_LAYER_H_ */
-- 
2.12.0

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, linux-clk,
	linux-arm-kernel, Icenowy Zheng

As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layer.

Abstract the layer type to void * and a ops struct, which contains the
only function used by crtc -- get the drm_plane struct of the layer.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
 drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
 5 files changed, 49 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..33854ee7f636 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -29,6 +29,7 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
@@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 
 	/* find primary and cursor planes for drm_crtc_init_with_planes */
 	for (i = 0; scrtc->layers[i]; i++) {
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		switch (layer->plane.type) {
+		switch (plane->type) {
 		case DRM_PLANE_TYPE_PRIMARY:
-			primary = &layer->plane;
+			primary = plane;
 			break;
 		case DRM_PLANE_TYPE_CURSOR:
-			cursor = &layer->plane;
+			cursor = plane;
 			break;
 		default:
 			break;
@@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	/* Set possible_crtcs to this crtc for overlay planes */
 	for (i = 0; scrtc->layers[i]; i++) {
 		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
-			layer->plane.possible_crtcs = possible_crtcs;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			plane->possible_crtcs = possible_crtcs;
 	}
 
 	return scrtc;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..a4036ee44cf8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,8 @@ struct sun4i_crtc {
 
 	struct sun4i_backend		*backend;
 	struct sun4i_tcon		*tcon;
-	struct sun4i_layer		**layers;
+	void				**layers;
+	const struct sunxi_layer_ops	*layer_ops;
 };
 
 static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..bc4a70d6968b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,7 +16,9 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
@@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	},
 };
 
+static struct drm_plane *sun4i_layer_get_plane(void *layer)
+{
+	struct sun4i_layer *sun4i_layer = layer;
+
+	return &sun4i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun4i_layer_get_plane,
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 						struct sun4i_backend *backend,
 						const struct sun4i_plane_desc *plane)
@@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend)
+				       struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
+	struct sun4i_backend *backend = crtc->backend;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 		layers[i] = layer;
 	};
 
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
 	return layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..425eea7b9e3b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend);
+				       struct sun4i_crtc *crtc);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
new file mode 100644
index 000000000000..d8838ec39299
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_LAYER_H_
+#define _SUNXI_LAYER_H_
+
+struct sunxi_layer_ops {
+	struct drm_plane *(*get_plane)(void *layer);
+};
+
+#endif /* _SUNXI_LAYER_H_ */
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layer.

Abstract the layer type to void * and a ops struct, which contains the
only function used by crtc -- get the drm_plane struct of the layer.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
 drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
 5 files changed, 49 insertions(+), 11 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..33854ee7f636 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -29,6 +29,7 @@
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
@@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 
 	/* find primary and cursor planes for drm_crtc_init_with_planes */
 	for (i = 0; scrtc->layers[i]; i++) {
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		switch (layer->plane.type) {
+		switch (plane->type) {
 		case DRM_PLANE_TYPE_PRIMARY:
-			primary = &layer->plane;
+			primary = plane;
 			break;
 		case DRM_PLANE_TYPE_CURSOR:
-			cursor = &layer->plane;
+			cursor = plane;
 			break;
 		default:
 			break;
@@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	/* Set possible_crtcs to this crtc for overlay planes */
 	for (i = 0; scrtc->layers[i]; i++) {
 		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
-		struct sun4i_layer *layer = scrtc->layers[i];
+		void *layer = scrtc->layers[i];
+		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
 
-		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
-			layer->plane.possible_crtcs = possible_crtcs;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			plane->possible_crtcs = possible_crtcs;
 	}
 
 	return scrtc;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..a4036ee44cf8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,8 @@ struct sun4i_crtc {
 
 	struct sun4i_backend		*backend;
 	struct sun4i_tcon		*tcon;
-	struct sun4i_layer		**layers;
+	void				**layers;
+	const struct sunxi_layer_ops	*layer_ops;
 };
 
 static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..bc4a70d6968b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,7 +16,9 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
+#include "sunxi_layer.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
@@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
 	},
 };
 
+static struct drm_plane *sun4i_layer_get_plane(void *layer)
+{
+	struct sun4i_layer *sun4i_layer = layer;
+
+	return &sun4i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun4i_layer_get_plane,
+};
+
 static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 						struct sun4i_backend *backend,
 						const struct sun4i_plane_desc *plane)
@@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend)
+				       struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
+	struct sun4i_backend *backend = crtc->backend;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 		layers[i] = layer;
 	};
 
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
 	return layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..425eea7b9e3b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 }
 
 struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_backend *backend);
+				       struct sun4i_crtc *crtc);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
new file mode 100644
index 000000000000..d8838ec39299
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_LAYER_H_
+#define _SUNXI_LAYER_H_
+
+struct sunxi_layer_ops {
+	struct drm_plane *(*get_plane)(void *layer);
+};
+
+#endif /* _SUNXI_LAYER_H_ */
-- 
2.12.0

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

* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

As we are going to add support for the Allwinner DE2 mixer in sun4i-drm
driver, we will finally have two types of display mixers -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, so I choose to call them both "mixer" here.

Abstract the mixer type to void * and a ops struct, which contains
functions that should be called outside the mixer-specified code (in
TCON, CRTC or TV Encoder code).

A dedicated Kconfig option is also added to control whether
sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should
be built. As we removed the codes in CRTC code that directly call the
layer code, we can now extract the layer part and combine it with the
backend part into a new module, sun4i-backend.ko.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig         | 10 ++++++++++
 drivers/gpu/drm/sun4i/Makefile        |  6 ++++--
 drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +++++++++++++++++++-------
 drivers/gpu/drm/sun4i/sun4i_backend.h |  5 -----
 drivers/gpu/drm/sun4i/sun4i_crtc.c    | 14 +++++++-------
 drivers/gpu/drm/sun4i/sun4i_crtc.h    |  7 ++++---
 drivers/gpu/drm/sun4i/sun4i_drv.h     |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c   |  7 +++----
 drivers/gpu/drm/sun4i/sun4i_layer.h   |  6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c    |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c      |  8 +++-----
 drivers/gpu/drm/sun4i/sunxi_mixer.h   | 22 ++++++++++++++++++++++
 12 files changed, 78 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..5a8227f37cc4 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,13 @@ config DRM_SUN4I
 	  Choose this option if you have an Allwinner SoC with a
 	  Display Engine. If M is selected the module will be called
 	  sun4i-drm.
+
+config DRM_SUN4I_BACKEND
+	tristate "Support for Allwinner A10 Display Engine Backend"
+	depends on DRM_SUN4I
+	default DRM_SUN4I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  original Allwinner Display Engine, which has a backend to
+	  do some alpha blending and feed graphics to TCON. If M is
+	  selected the module will be called sun4i-backend.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..1db1068b9be1 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
 sun4i-tcon-y += sun4i_dotclock.o
 sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_layer.o
+
+sun4i-backend-y += sun4i_layer.o
+sun4i-backend-y += sun4i_backend.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..35ea51b686e6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -23,6 +23,8 @@
 
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_mixer.h"
 
 static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -30,9 +32,10 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_apply_color_correction(void *mixer)
 {
 	int i;
+	struct sun4i_backend *backend = mixer;
 
 	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
 
@@ -44,27 +47,28 @@ void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
 		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
 			     sunxi_rgb2yuv_coef[i]);
 }
-EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
 
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_disable_color_correction(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Disabling color correction\n");
 
 	/* Disable color correction */
 	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
 			   SUN4I_BACKEND_OCCTL_ENABLE, 0);
 }
-EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
 
-void sun4i_backend_commit(struct sun4i_backend *backend)
+static void sun4i_backend_commit(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Committing changes\n");
 
 	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
 		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
 		     SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
 }
-EXPORT_SYMBOL(sun4i_backend_commit);
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable)
@@ -288,6 +292,13 @@ static int sun4i_backend_free_sat(struct device *dev) {
 	return 0;
 }
 
+static const struct sunxi_mixer_ops sun4i_backend_mixer_ops = {
+	.apply_color_correction = sun4i_backend_apply_color_correction,
+	.disable_color_correction = sun4i_backend_disable_color_correction,
+	.commit = sun4i_backend_commit,
+	.layers_init = sun4i_layers_init,
+};
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -310,7 +321,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (!backend)
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
-	drv->backend = backend;
+	drv->mixer = backend;
+	drv->mixer_ops = &sun4i_backend_mixer_ops;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..65ef521de7d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,11 +151,6 @@ struct sun4i_backend {
 	struct reset_control	*sat_reset;
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
-
-void sun4i_backend_commit(struct sun4i_backend *backend);
-
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable);
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 33854ee7f636..938dfe7188ff 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,11 +25,10 @@
 
 #include <video/videomode.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_layer.h"
 #include "sunxi_layer.h"
+#include "sunxi_mixer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	scrtc->mixer_ops->commit(scrtc->mixer);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 	.disable_vblank		= sun4i_crtc_disable_vblank,
 };
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
 	if (!scrtc)
 		return ERR_PTR(-ENOMEM);
-	scrtc->backend = backend;
+	scrtc->mixer = mixer;
+	scrtc->mixer_ops = mixer_ops;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
+	scrtc->layers = mixer_ops->layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index a4036ee44cf8..808019046397 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,8 @@ struct sun4i_crtc {
 	struct drm_crtc			crtc;
 	struct drm_pending_vblank_event	*event;
 
-	struct sun4i_backend		*backend;
+	void				*mixer;
+	const struct sunxi_mixer_ops	*mixer_ops;
 	struct sun4i_tcon		*tcon;
 	void				**layers;
 	const struct sunxi_layer_ops	*layer_ops;
@@ -28,8 +29,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 	return container_of(crtc, struct sun4i_crtc, crtc);
 }
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..97666b3e6381 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -17,8 +17,9 @@
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct sun4i_backend	*backend;
+	void			*mixer;
 	struct sun4i_tcon	*tcon;
+	const struct sunxi_mixer_ops *mixer_ops;
 
 	struct drm_fbdev_cma	*fbdev;
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index bc4a70d6968b..972e1eb0bb2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -141,11 +141,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	return layer;
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc)
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
-	struct sun4i_backend *backend = crtc->backend;
+	struct sun4i_backend *backend = crtc->mixer;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -198,5 +197,5 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 	/* Assign layer ops to the CRTC */
 	crtc->layer_ops = &layer_ops;
 
-	return layers;
+	return (void **)layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 425eea7b9e3b..e6a08216d038 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -13,6 +13,8 @@
 #ifndef _SUN4I_LAYER_H_
 #define _SUN4I_LAYER_H_
 
+struct sun4i_crtc;
+
 struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
@@ -26,7 +28,5 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 	return container_of(plane, struct sun4i_layer, plane);
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc);
-
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..2f330e4e2ead 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, drv->mixer, drv->mixer_ops, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..5950736610aa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -22,10 +22,10 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_tcon.h"
+#include "sunxi_mixer.h"
 
 #define SUN4I_TVE_EN_REG		0x000
 #define SUN4I_TVE_EN_DAC_MAP_MASK		GENMASK(19, 4)
@@ -353,7 +353,6 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
@@ -362,7 +361,7 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
-	sun4i_backend_disable_color_correction(backend);
+	crtc->mixer_ops->disable_color_correction(crtc->mixer);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +369,10 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
-	sun4i_backend_apply_color_correction(backend);
+	crtc->mixer_ops->apply_color_correction(crtc->mixer);
 
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
new file mode 100644
index 000000000000..11bdd20269ef
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_MIXER_H_
+#define _SUNXI_MIXER_H_
+
+struct sun4i_crtc;
+
+struct sunxi_mixer_ops {
+	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
+	void (*apply_color_correction)(void *mixer);
+	void (*disable_color_correction)(void *mixer);
+	void (*commit)(void *mixer);
+};
+
+#endif /* _SUNXI_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

As we are going to add support for the Allwinner DE2 mixer in sun4i-drm
driver, we will finally have two types of display mixers -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, so I choose to call them both "mixer" here.

Abstract the mixer type to void * and a ops struct, which contains
functions that should be called outside the mixer-specified code (in
TCON, CRTC or TV Encoder code).

A dedicated Kconfig option is also added to control whether
sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should
be built. As we removed the codes in CRTC code that directly call the
layer code, we can now extract the layer part and combine it with the
backend part into a new module, sun4i-backend.ko.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig         | 10 ++++++++++
 drivers/gpu/drm/sun4i/Makefile        |  6 ++++--
 drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +++++++++++++++++++-------
 drivers/gpu/drm/sun4i/sun4i_backend.h |  5 -----
 drivers/gpu/drm/sun4i/sun4i_crtc.c    | 14 +++++++-------
 drivers/gpu/drm/sun4i/sun4i_crtc.h    |  7 ++++---
 drivers/gpu/drm/sun4i/sun4i_drv.h     |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c   |  7 +++----
 drivers/gpu/drm/sun4i/sun4i_layer.h   |  6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c    |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c      |  8 +++-----
 drivers/gpu/drm/sun4i/sunxi_mixer.h   | 22 ++++++++++++++++++++++
 12 files changed, 78 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..5a8227f37cc4 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,13 @@ config DRM_SUN4I
 	  Choose this option if you have an Allwinner SoC with a
 	  Display Engine. If M is selected the module will be called
 	  sun4i-drm.
+
+config DRM_SUN4I_BACKEND
+	tristate "Support for Allwinner A10 Display Engine Backend"
+	depends on DRM_SUN4I
+	default DRM_SUN4I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  original Allwinner Display Engine, which has a backend to
+	  do some alpha blending and feed graphics to TCON. If M is
+	  selected the module will be called sun4i-backend.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..1db1068b9be1 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
 sun4i-tcon-y += sun4i_dotclock.o
 sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_layer.o
+
+sun4i-backend-y += sun4i_layer.o
+sun4i-backend-y += sun4i_backend.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..35ea51b686e6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -23,6 +23,8 @@
 
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_mixer.h"
 
 static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -30,9 +32,10 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_apply_color_correction(void *mixer)
 {
 	int i;
+	struct sun4i_backend *backend = mixer;
 
 	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
 
@@ -44,27 +47,28 @@ void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
 		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
 			     sunxi_rgb2yuv_coef[i]);
 }
-EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
 
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_disable_color_correction(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Disabling color correction\n");
 
 	/* Disable color correction */
 	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
 			   SUN4I_BACKEND_OCCTL_ENABLE, 0);
 }
-EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
 
-void sun4i_backend_commit(struct sun4i_backend *backend)
+static void sun4i_backend_commit(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Committing changes\n");
 
 	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
 		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
 		     SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
 }
-EXPORT_SYMBOL(sun4i_backend_commit);
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable)
@@ -288,6 +292,13 @@ static int sun4i_backend_free_sat(struct device *dev) {
 	return 0;
 }
 
+static const struct sunxi_mixer_ops sun4i_backend_mixer_ops = {
+	.apply_color_correction = sun4i_backend_apply_color_correction,
+	.disable_color_correction = sun4i_backend_disable_color_correction,
+	.commit = sun4i_backend_commit,
+	.layers_init = sun4i_layers_init,
+};
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -310,7 +321,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (!backend)
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
-	drv->backend = backend;
+	drv->mixer = backend;
+	drv->mixer_ops = &sun4i_backend_mixer_ops;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..65ef521de7d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,11 +151,6 @@ struct sun4i_backend {
 	struct reset_control	*sat_reset;
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
-
-void sun4i_backend_commit(struct sun4i_backend *backend);
-
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable);
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 33854ee7f636..938dfe7188ff 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,11 +25,10 @@
 
 #include <video/videomode.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_layer.h"
 #include "sunxi_layer.h"
+#include "sunxi_mixer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	scrtc->mixer_ops->commit(scrtc->mixer);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 	.disable_vblank		= sun4i_crtc_disable_vblank,
 };
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
 	if (!scrtc)
 		return ERR_PTR(-ENOMEM);
-	scrtc->backend = backend;
+	scrtc->mixer = mixer;
+	scrtc->mixer_ops = mixer_ops;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
+	scrtc->layers = mixer_ops->layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index a4036ee44cf8..808019046397 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,8 @@ struct sun4i_crtc {
 	struct drm_crtc			crtc;
 	struct drm_pending_vblank_event	*event;
 
-	struct sun4i_backend		*backend;
+	void				*mixer;
+	const struct sunxi_mixer_ops	*mixer_ops;
 	struct sun4i_tcon		*tcon;
 	void				**layers;
 	const struct sunxi_layer_ops	*layer_ops;
@@ -28,8 +29,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 	return container_of(crtc, struct sun4i_crtc, crtc);
 }
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..97666b3e6381 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -17,8 +17,9 @@
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct sun4i_backend	*backend;
+	void			*mixer;
 	struct sun4i_tcon	*tcon;
+	const struct sunxi_mixer_ops *mixer_ops;
 
 	struct drm_fbdev_cma	*fbdev;
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index bc4a70d6968b..972e1eb0bb2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -141,11 +141,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	return layer;
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc)
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
-	struct sun4i_backend *backend = crtc->backend;
+	struct sun4i_backend *backend = crtc->mixer;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -198,5 +197,5 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 	/* Assign layer ops to the CRTC */
 	crtc->layer_ops = &layer_ops;
 
-	return layers;
+	return (void **)layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 425eea7b9e3b..e6a08216d038 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -13,6 +13,8 @@
 #ifndef _SUN4I_LAYER_H_
 #define _SUN4I_LAYER_H_
 
+struct sun4i_crtc;
+
 struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
@@ -26,7 +28,5 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 	return container_of(plane, struct sun4i_layer, plane);
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc);
-
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..2f330e4e2ead 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, drv->mixer, drv->mixer_ops, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..5950736610aa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -22,10 +22,10 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_tcon.h"
+#include "sunxi_mixer.h"
 
 #define SUN4I_TVE_EN_REG		0x000
 #define SUN4I_TVE_EN_DAC_MAP_MASK		GENMASK(19, 4)
@@ -353,7 +353,6 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
@@ -362,7 +361,7 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
-	sun4i_backend_disable_color_correction(backend);
+	crtc->mixer_ops->disable_color_correction(crtc->mixer);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +369,10 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
-	sun4i_backend_apply_color_correction(backend);
+	crtc->mixer_ops->apply_color_correction(crtc->mixer);
 
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
new file mode 100644
index 000000000000..11bdd20269ef
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_MIXER_H_
+#define _SUNXI_MIXER_H_
+
+struct sun4i_crtc;
+
+struct sunxi_mixer_ops {
+	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
+	void (*apply_color_correction)(void *mixer);
+	void (*disable_color_correction)(void *mixer);
+	void (*commit)(void *mixer);
+};
+
+#endif /* _SUNXI_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, linux-clk,
	linux-arm-kernel, Icenowy Zheng

As we are going to add support for the Allwinner DE2 mixer in sun4i-drm
driver, we will finally have two types of display mixers -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, so I choose to call them both "mixer" here.

Abstract the mixer type to void * and a ops struct, which contains
functions that should be called outside the mixer-specified code (in
TCON, CRTC or TV Encoder code).

A dedicated Kconfig option is also added to control whether
sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should
be built. As we removed the codes in CRTC code that directly call the
layer code, we can now extract the layer part and combine it with the
backend part into a new module, sun4i-backend.ko.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig         | 10 ++++++++++
 drivers/gpu/drm/sun4i/Makefile        |  6 ++++--
 drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +++++++++++++++++++-------
 drivers/gpu/drm/sun4i/sun4i_backend.h |  5 -----
 drivers/gpu/drm/sun4i/sun4i_crtc.c    | 14 +++++++-------
 drivers/gpu/drm/sun4i/sun4i_crtc.h    |  7 ++++---
 drivers/gpu/drm/sun4i/sun4i_drv.h     |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c   |  7 +++----
 drivers/gpu/drm/sun4i/sun4i_layer.h   |  6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c    |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c      |  8 +++-----
 drivers/gpu/drm/sun4i/sunxi_mixer.h   | 22 ++++++++++++++++++++++
 12 files changed, 78 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..5a8227f37cc4 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,13 @@ config DRM_SUN4I
 	  Choose this option if you have an Allwinner SoC with a
 	  Display Engine. If M is selected the module will be called
 	  sun4i-drm.
+
+config DRM_SUN4I_BACKEND
+	tristate "Support for Allwinner A10 Display Engine Backend"
+	depends on DRM_SUN4I
+	default DRM_SUN4I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  original Allwinner Display Engine, which has a backend to
+	  do some alpha blending and feed graphics to TCON. If M is
+	  selected the module will be called sun4i-backend.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..1db1068b9be1 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
 sun4i-tcon-y += sun4i_dotclock.o
 sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_layer.o
+
+sun4i-backend-y += sun4i_layer.o
+sun4i-backend-y += sun4i_backend.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..35ea51b686e6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -23,6 +23,8 @@
 
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_mixer.h"
 
 static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -30,9 +32,10 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_apply_color_correction(void *mixer)
 {
 	int i;
+	struct sun4i_backend *backend = mixer;
 
 	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
 
@@ -44,27 +47,28 @@ void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
 		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
 			     sunxi_rgb2yuv_coef[i]);
 }
-EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
 
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_disable_color_correction(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Disabling color correction\n");
 
 	/* Disable color correction */
 	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
 			   SUN4I_BACKEND_OCCTL_ENABLE, 0);
 }
-EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
 
-void sun4i_backend_commit(struct sun4i_backend *backend)
+static void sun4i_backend_commit(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Committing changes\n");
 
 	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
 		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
 		     SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
 }
-EXPORT_SYMBOL(sun4i_backend_commit);
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable)
@@ -288,6 +292,13 @@ static int sun4i_backend_free_sat(struct device *dev) {
 	return 0;
 }
 
+static const struct sunxi_mixer_ops sun4i_backend_mixer_ops = {
+	.apply_color_correction = sun4i_backend_apply_color_correction,
+	.disable_color_correction = sun4i_backend_disable_color_correction,
+	.commit = sun4i_backend_commit,
+	.layers_init = sun4i_layers_init,
+};
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -310,7 +321,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (!backend)
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
-	drv->backend = backend;
+	drv->mixer = backend;
+	drv->mixer_ops = &sun4i_backend_mixer_ops;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..65ef521de7d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,11 +151,6 @@ struct sun4i_backend {
 	struct reset_control	*sat_reset;
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
-
-void sun4i_backend_commit(struct sun4i_backend *backend);
-
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable);
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 33854ee7f636..938dfe7188ff 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,11 +25,10 @@
 
 #include <video/videomode.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_layer.h"
 #include "sunxi_layer.h"
+#include "sunxi_mixer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	scrtc->mixer_ops->commit(scrtc->mixer);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 	.disable_vblank		= sun4i_crtc_disable_vblank,
 };
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
 	if (!scrtc)
 		return ERR_PTR(-ENOMEM);
-	scrtc->backend = backend;
+	scrtc->mixer = mixer;
+	scrtc->mixer_ops = mixer_ops;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
+	scrtc->layers = mixer_ops->layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index a4036ee44cf8..808019046397 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,8 @@ struct sun4i_crtc {
 	struct drm_crtc			crtc;
 	struct drm_pending_vblank_event	*event;
 
-	struct sun4i_backend		*backend;
+	void				*mixer;
+	const struct sunxi_mixer_ops	*mixer_ops;
 	struct sun4i_tcon		*tcon;
 	void				**layers;
 	const struct sunxi_layer_ops	*layer_ops;
@@ -28,8 +29,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 	return container_of(crtc, struct sun4i_crtc, crtc);
 }
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..97666b3e6381 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -17,8 +17,9 @@
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct sun4i_backend	*backend;
+	void			*mixer;
 	struct sun4i_tcon	*tcon;
+	const struct sunxi_mixer_ops *mixer_ops;
 
 	struct drm_fbdev_cma	*fbdev;
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index bc4a70d6968b..972e1eb0bb2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -141,11 +141,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	return layer;
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc)
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
-	struct sun4i_backend *backend = crtc->backend;
+	struct sun4i_backend *backend = crtc->mixer;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -198,5 +197,5 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 	/* Assign layer ops to the CRTC */
 	crtc->layer_ops = &layer_ops;
 
-	return layers;
+	return (void **)layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 425eea7b9e3b..e6a08216d038 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -13,6 +13,8 @@
 #ifndef _SUN4I_LAYER_H_
 #define _SUN4I_LAYER_H_
 
+struct sun4i_crtc;
+
 struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
@@ -26,7 +28,5 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 	return container_of(plane, struct sun4i_layer, plane);
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc);
-
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..2f330e4e2ead 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, drv->mixer, drv->mixer_ops, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..5950736610aa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -22,10 +22,10 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_tcon.h"
+#include "sunxi_mixer.h"
 
 #define SUN4I_TVE_EN_REG		0x000
 #define SUN4I_TVE_EN_DAC_MAP_MASK		GENMASK(19, 4)
@@ -353,7 +353,6 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
@@ -362,7 +361,7 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
-	sun4i_backend_disable_color_correction(backend);
+	crtc->mixer_ops->disable_color_correction(crtc->mixer);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +369,10 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
-	sun4i_backend_apply_color_correction(backend);
+	crtc->mixer_ops->apply_color_correction(crtc->mixer);
 
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
new file mode 100644
index 000000000000..11bdd20269ef
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_MIXER_H_
+#define _SUNXI_MIXER_H_
+
+struct sun4i_crtc;
+
+struct sunxi_mixer_ops {
+	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
+	void (*apply_color_correction)(void *mixer);
+	void (*disable_color_correction)(void *mixer);
+	void (*commit)(void *mixer);
+};
+
+#endif /* _SUNXI_MIXER_H_ */
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

As we are going to add support for the Allwinner DE2 mixer in sun4i-drm
driver, we will finally have two types of display mixers -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, so I choose to call them both "mixer" here.

Abstract the mixer type to void * and a ops struct, which contains
functions that should be called outside the mixer-specified code (in
TCON, CRTC or TV Encoder code).

A dedicated Kconfig option is also added to control whether
sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should
be built. As we removed the codes in CRTC code that directly call the
layer code, we can now extract the layer part and combine it with the
backend part into a new module, sun4i-backend.ko.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig         | 10 ++++++++++
 drivers/gpu/drm/sun4i/Makefile        |  6 ++++--
 drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +++++++++++++++++++-------
 drivers/gpu/drm/sun4i/sun4i_backend.h |  5 -----
 drivers/gpu/drm/sun4i/sun4i_crtc.c    | 14 +++++++-------
 drivers/gpu/drm/sun4i/sun4i_crtc.h    |  7 ++++---
 drivers/gpu/drm/sun4i/sun4i_drv.h     |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.c   |  7 +++----
 drivers/gpu/drm/sun4i/sun4i_layer.h   |  6 +++---
 drivers/gpu/drm/sun4i/sun4i_tcon.c    |  2 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c      |  8 +++-----
 drivers/gpu/drm/sun4i/sunxi_mixer.h   | 22 ++++++++++++++++++++++
 12 files changed, 78 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..5a8227f37cc4 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,13 @@ config DRM_SUN4I
 	  Choose this option if you have an Allwinner SoC with a
 	  Display Engine. If M is selected the module will be called
 	  sun4i-drm.
+
+config DRM_SUN4I_BACKEND
+	tristate "Support for Allwinner A10 Display Engine Backend"
+	depends on DRM_SUN4I
+	default DRM_SUN4I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  original Allwinner Display Engine, which has a backend to
+	  do some alpha blending and feed graphics to TCON. If M is
+	  selected the module will be called sun4i-backend.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..1db1068b9be1 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o
 sun4i-tcon-y += sun4i_rgb.o
 sun4i-tcon-y += sun4i_dotclock.o
 sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_layer.o
+
+sun4i-backend-y += sun4i_layer.o
+sun4i-backend-y += sun4i_backend.o
 
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..35ea51b686e6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -23,6 +23,8 @@
 
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_mixer.h"
 
 static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -30,9 +32,10 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_apply_color_correction(void *mixer)
 {
 	int i;
+	struct sun4i_backend *backend = mixer;
 
 	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
 
@@ -44,27 +47,28 @@ void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
 		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
 			     sunxi_rgb2yuv_coef[i]);
 }
-EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
 
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_disable_color_correction(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Disabling color correction\n");
 
 	/* Disable color correction */
 	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
 			   SUN4I_BACKEND_OCCTL_ENABLE, 0);
 }
-EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
 
-void sun4i_backend_commit(struct sun4i_backend *backend)
+static void sun4i_backend_commit(void *mixer)
 {
+	struct sun4i_backend *backend = mixer;
+
 	DRM_DEBUG_DRIVER("Committing changes\n");
 
 	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
 		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
 		     SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
 }
-EXPORT_SYMBOL(sun4i_backend_commit);
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable)
@@ -288,6 +292,13 @@ static int sun4i_backend_free_sat(struct device *dev) {
 	return 0;
 }
 
+static const struct sunxi_mixer_ops sun4i_backend_mixer_ops = {
+	.apply_color_correction = sun4i_backend_apply_color_correction,
+	.disable_color_correction = sun4i_backend_disable_color_correction,
+	.commit = sun4i_backend_commit,
+	.layers_init = sun4i_layers_init,
+};
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -310,7 +321,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (!backend)
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
-	drv->backend = backend;
+	drv->mixer = backend;
+	drv->mixer_ops = &sun4i_backend_mixer_ops;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..65ef521de7d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,11 +151,6 @@ struct sun4i_backend {
 	struct reset_control	*sat_reset;
 };
 
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
-
-void sun4i_backend_commit(struct sun4i_backend *backend);
-
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable);
 int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 33854ee7f636..938dfe7188ff 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,11 +25,10 @@
 
 #include <video/videomode.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_layer.h"
 #include "sunxi_layer.h"
+#include "sunxi_mixer.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	scrtc->mixer_ops->commit(scrtc->mixer);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 	.disable_vblank		= sun4i_crtc_disable_vblank,
 };
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
 	if (!scrtc)
 		return ERR_PTR(-ENOMEM);
-	scrtc->backend = backend;
+	scrtc->mixer = mixer;
+	scrtc->mixer_ops = mixer_ops;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
+	scrtc->layers = mixer_ops->layers_init(drm, scrtc);
 	if (IS_ERR(scrtc->layers)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index a4036ee44cf8..808019046397 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,8 @@ struct sun4i_crtc {
 	struct drm_crtc			crtc;
 	struct drm_pending_vblank_event	*event;
 
-	struct sun4i_backend		*backend;
+	void				*mixer;
+	const struct sunxi_mixer_ops	*mixer_ops;
 	struct sun4i_tcon		*tcon;
 	void				**layers;
 	const struct sunxi_layer_ops	*layer_ops;
@@ -28,8 +29,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 	return container_of(crtc, struct sun4i_crtc, crtc);
 }
 
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+				   const struct sunxi_mixer_ops *mixer_ops,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..97666b3e6381 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -17,8 +17,9 @@
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct sun4i_backend	*backend;
+	void			*mixer;
 	struct sun4i_tcon	*tcon;
+	const struct sunxi_mixer_ops *mixer_ops;
 
 	struct drm_fbdev_cma	*fbdev;
 };
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index bc4a70d6968b..972e1eb0bb2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -141,11 +141,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 	return layer;
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc)
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
 {
 	struct sun4i_layer **layers;
-	struct sun4i_backend *backend = crtc->backend;
+	struct sun4i_backend *backend = crtc->mixer;
 	int i;
 
 	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -198,5 +197,5 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 	/* Assign layer ops to the CRTC */
 	crtc->layer_ops = &layer_ops;
 
-	return layers;
+	return (void **)layers;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 425eea7b9e3b..e6a08216d038 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -13,6 +13,8 @@
 #ifndef _SUN4I_LAYER_H_
 #define _SUN4I_LAYER_H_
 
+struct sun4i_crtc;
+
 struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
@@ -26,7 +28,5 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 	return container_of(plane, struct sun4i_layer, plane);
 }
 
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
-				       struct sun4i_crtc *crtc);
-
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..2f330e4e2ead 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, drv->mixer, drv->mixer_ops, tcon);
 	if (IS_ERR(tcon->crtc)) {
 		dev_err(dev, "Couldn't create our CRTC\n");
 		ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..5950736610aa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -22,10 +22,10 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
 #include "sun4i_tcon.h"
+#include "sunxi_mixer.h"
 
 #define SUN4I_TVE_EN_REG		0x000
 #define SUN4I_TVE_EN_DAC_MAP_MASK		GENMASK(19, 4)
@@ -353,7 +353,6 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
 
@@ -362,7 +361,7 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
 			   0);
-	sun4i_backend_disable_color_correction(backend);
+	crtc->mixer_ops->disable_color_correction(crtc->mixer);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +369,10 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
 	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
 	struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
 	struct sun4i_tcon *tcon = crtc->tcon;
-	struct sun4i_backend *backend = crtc->backend;
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
-	sun4i_backend_apply_color_correction(backend);
+	crtc->mixer_ops->apply_color_correction(crtc->mixer);
 
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
new file mode 100644
index 000000000000..11bdd20269ef
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_MIXER_H_
+#define _SUNXI_MIXER_H_
+
+struct sun4i_crtc;
+
+struct sunxi_mixer_ops {
+	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
+	void (*apply_color_correction)(void *mixer);
+	void (*disable_color_correction)(void *mixer);
+	void (*commit)(void *mixer);
+};
+
+#endif /* _SUNXI_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig       |  10 +
 drivers/gpu/drm/sun4i/Makefile      |   4 +
 drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 ++++++++++++
 6 files changed, 722 insertions(+)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5a8227f37cc4..15557484520d 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
 	  original Allwinner Display Engine, which has a backend to
 	  do some alpha blending and feed graphics to TCON. If M is
 	  selected the module will be called sun4i-backend.
+
+config DRM_SUN4I_SUN8I_MIXER
+	tristate "Support for Allwinner Display Engine 2.0 Mixer"
+	depends on DRM_SUN4I
+	default MACH_SUN8I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  Allwinner Display Engine 2.0, which has a mixer to do some
+	  graphics mixture and feed graphics to TCON, If M is
+	  selected the module will be called sun8i-mixer.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1db1068b9be1..7625c2dad1bb 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
 sun4i-backend-y += sun4i_layer.o
 sun4i-backend-y += sun4i_backend.o
 
+sun8i-mixer-y += sun8i_layer.o
+sun8i-mixer-y += sun8i_mixer.o
+
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
new file mode 100644
index 000000000000..5cc4a7f8a7ae
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_crtc.h"
+#include "sun8i_layer.h"
+#include "sun8i_mixer.h"
+#include "sunxi_layer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
+					       struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_layer_enable(mixer, layer->id, false);
+}
+
+static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+	sun8i_mixer_layer_enable(mixer, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
+	.atomic_check	= sun8i_mixer_layer_atomic_check,
+	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
+	.atomic_update	= sun8i_mixer_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_layer_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_layer_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+	},
+};
+
+static struct drm_plane *sun8i_layer_get_plane(void *layer)
+{
+	struct sun8i_layer *sun8i_layer = layer;
+
+	return &sun8i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun8i_layer_get_plane,
+};
+
+static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
+						struct sun8i_mixer *mixer,
+						const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &layer->plane, 0,
+				       &sun8i_mixer_layer_funcs,
+				       plane->formats, plane->nformats,
+				       plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane,
+			     &sun8i_mixer_layer_helper_funcs);
+	layer->mixer = mixer;
+
+	return layer;
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
+{
+	struct sun8i_layer **layers;
+	struct sun8i_mixer *mixer = crtc->mixer;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*layers), GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_layer *layer;
+
+		layer = sun8i_layer_init_one(drm, mixer, plane);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		layer->id = i;
+		layers[i] = layer;
+	};
+
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
+	return (void **)layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
new file mode 100644
index 000000000000..9f145ce842f2
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_LAYER_H_
+#define _SUN8I_LAYER_H_
+
+struct sun4i_crtc;
+
+struct sun8i_layer {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_layer, plane);
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
+#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..1399d1a6c678
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_backend.c, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun4i_drv.h"
+#include "sun8i_mixer.h"
+#include "sun8i_layer.h"
+#include "sunxi_mixer.h"
+
+void sun8i_mixer_commit(void *mixer)
+{
+	struct sun8i_mixer *sun8i_mixer = mixer;
+
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable)
+{
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	/* Set the alpha configuration */
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+					     u32 format, u32 *mode)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int i;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating blender size\n");
+		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+			regmap_write(mixer->regs,
+				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+				     SUN8I_MIXER_SIZE(state->crtc_w,
+						      state->crtc_h));
+		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating channel size\n");
+		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     fb->pitches[0]);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+			   interlaced ?
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+						&val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return ret;
+	}
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	dma_addr_t paddr;
+	uint32_t paddr_u32;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = fb->format->cpp[0];
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	paddr_u32 = (uint32_t) paddr;
+
+	regmap_write(mixer->regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     paddr_u32);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
+	.commit = sun8i_mixer_commit,
+	.layers_init = sun8i_layers_init,
+};
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun8i_mixer *mixer;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	dev_set_drvdata(dev, mixer);
+	drv->mixer = mixer;
+	drv->mixer_ops = &sun8i_mixer_mixer_ops;
+
+	mixer->cfg = of_device_get_match_data(dev);
+	if (!mixer->cfg)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun8i_mixer_regmap_config);
+	if (IS_ERR(mixer->regs)) {
+		dev_err(dev, "Couldn't create the mixer regmap\n");
+		return PTR_ERR(mixer->regs);
+	}
+
+	mixer->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(mixer->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(mixer->reset);
+	}
+
+	ret = reset_control_deassert(mixer->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	mixer->bus_clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(mixer->bus_clk)) {
+		dev_err(dev, "Couldn't get the mixer bus clock\n");
+		ret = PTR_ERR(mixer->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(mixer->bus_clk);
+
+	mixer->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(mixer->mod_clk)) {
+		dev_err(dev, "Couldn't get the mixer module clock\n");
+		ret = PTR_ERR(mixer->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(mixer->mod_clk);
+
+	/* Reset the registers */
+	for (i = 0x0; i < 0x20000; i += 4)
+		regmap_write(mixer->regs, i, 0);
+
+	/* Enable the mixer */
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Initialize blender */
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+		regmap_write(mixer->regs,
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+	/* Select the first UI channel */
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+			 mixer->cfg->vi_num);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+		     mixer->cfg->vi_num);
+
+	return 0;
+
+	clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+	reset_control_assert(mixer->reset);
+	return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(mixer->mod_clk);
+	clk_disable_unprepare(mixer->bus_clk);
+	reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+	.bind	= sun8i_mixer_bind,
+	.unbind	= sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun8i_mixer_ops);
+
+	return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.vi_num = 2,
+	.ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+	{
+		.compatible = "allwinner,sun8i-v3s-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+	.probe		= sun8i_mixer_probe,
+	.remove		= sun8i_mixer_remove,
+	.driver		= {
+		.name		= "sun8i-mixer",
+		.of_match_table	= sun8i_mixer_of_table,
+	},
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..7b3b9d747d7d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT		4
+
+#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_STATUS		0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE			0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN			0x20000
+#define SUN8I_MIXER_GSU1_EN			0x30000
+#define SUN8I_MIXER_GSU2_EN			0x40000
+#define SUN8I_MIXER_GSU3_EN			0x50000
+#define SUN8I_MIXER_FCE_EN			0xa0000
+#define SUN8I_MIXER_BWS_EN			0xa2000
+#define SUN8I_MIXER_LTI_EN			0xa4000
+#define SUN8I_MIXER_PEAK_EN			0xa6000
+#define SUN8I_MIXER_ASE_EN			0xa8000
+#define SUN8I_MIXER_FCC_EN			0xaa000
+#define SUN8I_MIXER_DCSC_EN			0xb0000
+
+struct sun8i_mixer_cfg {
+	int		vi_num;
+	int		ui_num;
+};
+
+struct sun8i_mixer {
+	struct regmap			*regs;
+
+	const struct sun8i_mixer_cfg	*cfg;
+
+	struct reset_control		*reset;
+
+	struct clk			*bus_clk;
+	struct clk			*mod_clk;
+};
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane);
+#endif /* _SUN8I_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig       |  10 +
 drivers/gpu/drm/sun4i/Makefile      |   4 +
 drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 ++++++++++++
 6 files changed, 722 insertions(+)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5a8227f37cc4..15557484520d 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
 	  original Allwinner Display Engine, which has a backend to
 	  do some alpha blending and feed graphics to TCON. If M is
 	  selected the module will be called sun4i-backend.
+
+config DRM_SUN4I_SUN8I_MIXER
+	tristate "Support for Allwinner Display Engine 2.0 Mixer"
+	depends on DRM_SUN4I
+	default MACH_SUN8I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  Allwinner Display Engine 2.0, which has a mixer to do some
+	  graphics mixture and feed graphics to TCON, If M is
+	  selected the module will be called sun8i-mixer.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1db1068b9be1..7625c2dad1bb 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
 sun4i-backend-y += sun4i_layer.o
 sun4i-backend-y += sun4i_backend.o
 
+sun8i-mixer-y += sun8i_layer.o
+sun8i-mixer-y += sun8i_mixer.o
+
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
new file mode 100644
index 000000000000..5cc4a7f8a7ae
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_crtc.h"
+#include "sun8i_layer.h"
+#include "sun8i_mixer.h"
+#include "sunxi_layer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
+					       struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_layer_enable(mixer, layer->id, false);
+}
+
+static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+	sun8i_mixer_layer_enable(mixer, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
+	.atomic_check	= sun8i_mixer_layer_atomic_check,
+	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
+	.atomic_update	= sun8i_mixer_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_layer_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_layer_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+	},
+};
+
+static struct drm_plane *sun8i_layer_get_plane(void *layer)
+{
+	struct sun8i_layer *sun8i_layer = layer;
+
+	return &sun8i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun8i_layer_get_plane,
+};
+
+static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
+						struct sun8i_mixer *mixer,
+						const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &layer->plane, 0,
+				       &sun8i_mixer_layer_funcs,
+				       plane->formats, plane->nformats,
+				       plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane,
+			     &sun8i_mixer_layer_helper_funcs);
+	layer->mixer = mixer;
+
+	return layer;
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
+{
+	struct sun8i_layer **layers;
+	struct sun8i_mixer *mixer = crtc->mixer;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*layers), GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_layer *layer;
+
+		layer = sun8i_layer_init_one(drm, mixer, plane);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		layer->id = i;
+		layers[i] = layer;
+	};
+
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
+	return (void **)layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
new file mode 100644
index 000000000000..9f145ce842f2
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_LAYER_H_
+#define _SUN8I_LAYER_H_
+
+struct sun4i_crtc;
+
+struct sun8i_layer {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_layer, plane);
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
+#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..1399d1a6c678
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_backend.c, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun4i_drv.h"
+#include "sun8i_mixer.h"
+#include "sun8i_layer.h"
+#include "sunxi_mixer.h"
+
+void sun8i_mixer_commit(void *mixer)
+{
+	struct sun8i_mixer *sun8i_mixer = mixer;
+
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable)
+{
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	/* Set the alpha configuration */
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+					     u32 format, u32 *mode)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int i;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating blender size\n");
+		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+			regmap_write(mixer->regs,
+				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+				     SUN8I_MIXER_SIZE(state->crtc_w,
+						      state->crtc_h));
+		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating channel size\n");
+		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     fb->pitches[0]);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+			   interlaced ?
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+						&val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return ret;
+	}
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	dma_addr_t paddr;
+	uint32_t paddr_u32;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = fb->format->cpp[0];
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	paddr_u32 = (uint32_t) paddr;
+
+	regmap_write(mixer->regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     paddr_u32);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
+	.commit = sun8i_mixer_commit,
+	.layers_init = sun8i_layers_init,
+};
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun8i_mixer *mixer;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	dev_set_drvdata(dev, mixer);
+	drv->mixer = mixer;
+	drv->mixer_ops = &sun8i_mixer_mixer_ops;
+
+	mixer->cfg = of_device_get_match_data(dev);
+	if (!mixer->cfg)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun8i_mixer_regmap_config);
+	if (IS_ERR(mixer->regs)) {
+		dev_err(dev, "Couldn't create the mixer regmap\n");
+		return PTR_ERR(mixer->regs);
+	}
+
+	mixer->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(mixer->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(mixer->reset);
+	}
+
+	ret = reset_control_deassert(mixer->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	mixer->bus_clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(mixer->bus_clk)) {
+		dev_err(dev, "Couldn't get the mixer bus clock\n");
+		ret = PTR_ERR(mixer->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(mixer->bus_clk);
+
+	mixer->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(mixer->mod_clk)) {
+		dev_err(dev, "Couldn't get the mixer module clock\n");
+		ret = PTR_ERR(mixer->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(mixer->mod_clk);
+
+	/* Reset the registers */
+	for (i = 0x0; i < 0x20000; i += 4)
+		regmap_write(mixer->regs, i, 0);
+
+	/* Enable the mixer */
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Initialize blender */
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+		regmap_write(mixer->regs,
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+	/* Select the first UI channel */
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+			 mixer->cfg->vi_num);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+		     mixer->cfg->vi_num);
+
+	return 0;
+
+	clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+	reset_control_assert(mixer->reset);
+	return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(mixer->mod_clk);
+	clk_disable_unprepare(mixer->bus_clk);
+	reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+	.bind	= sun8i_mixer_bind,
+	.unbind	= sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun8i_mixer_ops);
+
+	return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.vi_num = 2,
+	.ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+	{
+		.compatible = "allwinner,sun8i-v3s-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+	.probe		= sun8i_mixer_probe,
+	.remove		= sun8i_mixer_remove,
+	.driver		= {
+		.name		= "sun8i-mixer",
+		.of_match_table	= sun8i_mixer_of_table,
+	},
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..7b3b9d747d7d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT		4
+
+#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_STATUS		0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE			0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN			0x20000
+#define SUN8I_MIXER_GSU1_EN			0x30000
+#define SUN8I_MIXER_GSU2_EN			0x40000
+#define SUN8I_MIXER_GSU3_EN			0x50000
+#define SUN8I_MIXER_FCE_EN			0xa0000
+#define SUN8I_MIXER_BWS_EN			0xa2000
+#define SUN8I_MIXER_LTI_EN			0xa4000
+#define SUN8I_MIXER_PEAK_EN			0xa6000
+#define SUN8I_MIXER_ASE_EN			0xa8000
+#define SUN8I_MIXER_FCC_EN			0xaa000
+#define SUN8I_MIXER_DCSC_EN			0xb0000
+
+struct sun8i_mixer_cfg {
+	int		vi_num;
+	int		ui_num;
+};
+
+struct sun8i_mixer {
+	struct regmap			*regs;
+
+	const struct sun8i_mixer_cfg	*cfg;
+
+	struct reset_control		*reset;
+
+	struct clk			*bus_clk;
+	struct clk			*mod_clk;
+};
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane);
+#endif /* _SUN8I_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, linux-clk,
	linux-arm-kernel, Icenowy Zheng

Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig       |  10 +
 drivers/gpu/drm/sun4i/Makefile      |   4 +
 drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 ++++++++++++
 6 files changed, 722 insertions(+)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5a8227f37cc4..15557484520d 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
 	  original Allwinner Display Engine, which has a backend to
 	  do some alpha blending and feed graphics to TCON. If M is
 	  selected the module will be called sun4i-backend.
+
+config DRM_SUN4I_SUN8I_MIXER
+	tristate "Support for Allwinner Display Engine 2.0 Mixer"
+	depends on DRM_SUN4I
+	default MACH_SUN8I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  Allwinner Display Engine 2.0, which has a mixer to do some
+	  graphics mixture and feed graphics to TCON, If M is
+	  selected the module will be called sun8i-mixer.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1db1068b9be1..7625c2dad1bb 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
 sun4i-backend-y += sun4i_layer.o
 sun4i-backend-y += sun4i_backend.o
 
+sun8i-mixer-y += sun8i_layer.o
+sun8i-mixer-y += sun8i_mixer.o
+
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
new file mode 100644
index 000000000000..5cc4a7f8a7ae
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_crtc.h"
+#include "sun8i_layer.h"
+#include "sun8i_mixer.h"
+#include "sunxi_layer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
+					       struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_layer_enable(mixer, layer->id, false);
+}
+
+static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+	sun8i_mixer_layer_enable(mixer, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
+	.atomic_check	= sun8i_mixer_layer_atomic_check,
+	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
+	.atomic_update	= sun8i_mixer_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_layer_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_layer_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+	},
+};
+
+static struct drm_plane *sun8i_layer_get_plane(void *layer)
+{
+	struct sun8i_layer *sun8i_layer = layer;
+
+	return &sun8i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun8i_layer_get_plane,
+};
+
+static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
+						struct sun8i_mixer *mixer,
+						const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &layer->plane, 0,
+				       &sun8i_mixer_layer_funcs,
+				       plane->formats, plane->nformats,
+				       plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane,
+			     &sun8i_mixer_layer_helper_funcs);
+	layer->mixer = mixer;
+
+	return layer;
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
+{
+	struct sun8i_layer **layers;
+	struct sun8i_mixer *mixer = crtc->mixer;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*layers), GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_layer *layer;
+
+		layer = sun8i_layer_init_one(drm, mixer, plane);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		layer->id = i;
+		layers[i] = layer;
+	};
+
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
+	return (void **)layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
new file mode 100644
index 000000000000..9f145ce842f2
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_LAYER_H_
+#define _SUN8I_LAYER_H_
+
+struct sun4i_crtc;
+
+struct sun8i_layer {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_layer, plane);
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
+#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..1399d1a6c678
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_backend.c, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun4i_drv.h"
+#include "sun8i_mixer.h"
+#include "sun8i_layer.h"
+#include "sunxi_mixer.h"
+
+void sun8i_mixer_commit(void *mixer)
+{
+	struct sun8i_mixer *sun8i_mixer = mixer;
+
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable)
+{
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	/* Set the alpha configuration */
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+					     u32 format, u32 *mode)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int i;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating blender size\n");
+		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+			regmap_write(mixer->regs,
+				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+				     SUN8I_MIXER_SIZE(state->crtc_w,
+						      state->crtc_h));
+		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating channel size\n");
+		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     fb->pitches[0]);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+			   interlaced ?
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+						&val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return ret;
+	}
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	dma_addr_t paddr;
+	uint32_t paddr_u32;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = fb->format->cpp[0];
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	paddr_u32 = (uint32_t) paddr;
+
+	regmap_write(mixer->regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     paddr_u32);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
+	.commit = sun8i_mixer_commit,
+	.layers_init = sun8i_layers_init,
+};
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun8i_mixer *mixer;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	dev_set_drvdata(dev, mixer);
+	drv->mixer = mixer;
+	drv->mixer_ops = &sun8i_mixer_mixer_ops;
+
+	mixer->cfg = of_device_get_match_data(dev);
+	if (!mixer->cfg)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun8i_mixer_regmap_config);
+	if (IS_ERR(mixer->regs)) {
+		dev_err(dev, "Couldn't create the mixer regmap\n");
+		return PTR_ERR(mixer->regs);
+	}
+
+	mixer->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(mixer->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(mixer->reset);
+	}
+
+	ret = reset_control_deassert(mixer->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	mixer->bus_clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(mixer->bus_clk)) {
+		dev_err(dev, "Couldn't get the mixer bus clock\n");
+		ret = PTR_ERR(mixer->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(mixer->bus_clk);
+
+	mixer->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(mixer->mod_clk)) {
+		dev_err(dev, "Couldn't get the mixer module clock\n");
+		ret = PTR_ERR(mixer->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(mixer->mod_clk);
+
+	/* Reset the registers */
+	for (i = 0x0; i < 0x20000; i += 4)
+		regmap_write(mixer->regs, i, 0);
+
+	/* Enable the mixer */
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Initialize blender */
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+		regmap_write(mixer->regs,
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+	/* Select the first UI channel */
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+			 mixer->cfg->vi_num);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+		     mixer->cfg->vi_num);
+
+	return 0;
+
+	clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+	reset_control_assert(mixer->reset);
+	return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(mixer->mod_clk);
+	clk_disable_unprepare(mixer->bus_clk);
+	reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+	.bind	= sun8i_mixer_bind,
+	.unbind	= sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun8i_mixer_ops);
+
+	return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.vi_num = 2,
+	.ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+	{
+		.compatible = "allwinner,sun8i-v3s-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+	.probe		= sun8i_mixer_probe,
+	.remove		= sun8i_mixer_remove,
+	.driver		= {
+		.name		= "sun8i-mixer",
+		.of_match_table	= sun8i_mixer_of_table,
+	},
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..7b3b9d747d7d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT		4
+
+#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_STATUS		0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE			0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN			0x20000
+#define SUN8I_MIXER_GSU1_EN			0x30000
+#define SUN8I_MIXER_GSU2_EN			0x40000
+#define SUN8I_MIXER_GSU3_EN			0x50000
+#define SUN8I_MIXER_FCE_EN			0xa0000
+#define SUN8I_MIXER_BWS_EN			0xa2000
+#define SUN8I_MIXER_LTI_EN			0xa4000
+#define SUN8I_MIXER_PEAK_EN			0xa6000
+#define SUN8I_MIXER_ASE_EN			0xa8000
+#define SUN8I_MIXER_FCC_EN			0xaa000
+#define SUN8I_MIXER_DCSC_EN			0xb0000
+
+struct sun8i_mixer_cfg {
+	int		vi_num;
+	int		ui_num;
+};
+
+struct sun8i_mixer {
+	struct regmap			*regs;
+
+	const struct sun8i_mixer_cfg	*cfg;
+
+	struct reset_control		*reset;
+
+	struct clk			*bus_clk;
+	struct clk			*mod_clk;
+};
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane);
+#endif /* _SUN8I_MIXER_H_ */
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.

Add support for the mixer on Allwinner V3s SoC; it's the simplest one.

Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Refactored patch in v3.

 drivers/gpu/drm/sun4i/Kconfig       |  10 +
 drivers/gpu/drm/sun4i/Makefile      |   4 +
 drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 ++++++++++++
 6 files changed, 722 insertions(+)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5a8227f37cc4..15557484520d 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
 	  original Allwinner Display Engine, which has a backend to
 	  do some alpha blending and feed graphics to TCON. If M is
 	  selected the module will be called sun4i-backend.
+
+config DRM_SUN4I_SUN8I_MIXER
+	tristate "Support for Allwinner Display Engine 2.0 Mixer"
+	depends on DRM_SUN4I
+	default MACH_SUN8I
+	help
+	  Choose this option if you have an Allwinner SoC with the
+	  Allwinner Display Engine 2.0, which has a mixer to do some
+	  graphics mixture and feed graphics to TCON, If M is
+	  selected the module will be called sun8i-mixer.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1db1068b9be1..7625c2dad1bb 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
 sun4i-backend-y += sun4i_layer.o
 sun4i-backend-y += sun4i_backend.o
 
+sun8i-mixer-y += sun8i_layer.o
+sun8i-mixer-y += sun8i_mixer.o
+
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
 obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
 obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
new file mode 100644
index 000000000000..5cc4a7f8a7ae
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_crtc.h"
+#include "sun8i_layer.h"
+#include "sun8i_mixer.h"
+#include "sunxi_layer.h"
+
+struct sun8i_plane_desc {
+	       enum drm_plane_type     type;
+	       const uint32_t          *formats;
+	       uint32_t                nformats;
+};
+
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
+					       struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_layer_enable(mixer, layer->id, false);
+}
+
+static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+	sun8i_mixer_layer_enable(mixer, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
+	.atomic_check	= sun8i_mixer_layer_atomic_check,
+	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
+	.atomic_update	= sun8i_mixer_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_layer_formats[] = {
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+	{
+		.type = DRM_PLANE_TYPE_PRIMARY,
+		.formats = sun8i_mixer_layer_formats,
+		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+	},
+};
+
+static struct drm_plane *sun8i_layer_get_plane(void *layer)
+{
+	struct sun8i_layer *sun8i_layer = layer;
+
+	return &sun8i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+	.get_plane = sun8i_layer_get_plane,
+};
+
+static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
+						struct sun8i_mixer *mixer,
+						const struct sun8i_plane_desc *plane)
+{
+	struct sun8i_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &layer->plane, 0,
+				       &sun8i_mixer_layer_funcs,
+				       plane->formats, plane->nformats,
+				       plane->type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane,
+			     &sun8i_mixer_layer_helper_funcs);
+	layer->mixer = mixer;
+
+	return layer;
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
+{
+	struct sun8i_layer **layers;
+	struct sun8i_mixer *mixer = crtc->mixer;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+			      sizeof(*layers), GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+		struct sun8i_layer *layer;
+
+		layer = sun8i_layer_init_one(drm, mixer, plane);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		layer->id = i;
+		layers[i] = layer;
+	};
+
+	/* Assign layer ops to the CRTC */
+	crtc->layer_ops = &layer_ops;
+
+	return (void **)layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
new file mode 100644
index 000000000000..9f145ce842f2
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_layer.h, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ *   Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_LAYER_H_
+#define _SUN8I_LAYER_H_
+
+struct sun4i_crtc;
+
+struct sun8i_layer {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	struct sun8i_mixer	*mixer;
+	int			id;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_layer, plane);
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
+#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..1399d1a6c678
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * Based on sun4i_backend.c, which is:
+ *   Copyright (C) 2015 Free Electrons
+ *   Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun4i_drv.h"
+#include "sun8i_mixer.h"
+#include "sun8i_layer.h"
+#include "sunxi_mixer.h"
+
+void sun8i_mixer_commit(void *mixer)
+{
+	struct sun8i_mixer *sun8i_mixer = mixer;
+
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable)
+{
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	/* Set the alpha configuration */
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+					     u32 format, u32 *mode)
+{
+	switch (format) {
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int i;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating blender size\n");
+		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+			regmap_write(mixer->regs,
+				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+				     SUN8I_MIXER_SIZE(state->crtc_w,
+						      state->crtc_h));
+		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+		DRM_DEBUG_DRIVER("Updating channel size\n");
+		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_SIZE(state->crtc_w,
+					      state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     fb->pitches[0]);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+			   interlaced ?
+			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+						&val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return ret;
+	}
+
+	regmap_update_bits(mixer->regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	dma_addr_t paddr;
+	uint32_t paddr_u32;
+	/* Currently the first UI channel is used */
+	int chan = mixer->cfg->vi_num;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = fb->format->cpp[0];
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	paddr_u32 = (uint32_t) paddr;
+
+	regmap_write(mixer->regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     paddr_u32);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
+	.commit = sun8i_mixer_commit,
+	.layers_init = sun8i_layers_init,
+};
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun8i_mixer *mixer;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	dev_set_drvdata(dev, mixer);
+	drv->mixer = mixer;
+	drv->mixer_ops = &sun8i_mixer_mixer_ops;
+
+	mixer->cfg = of_device_get_match_data(dev);
+	if (!mixer->cfg)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	mixer->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun8i_mixer_regmap_config);
+	if (IS_ERR(mixer->regs)) {
+		dev_err(dev, "Couldn't create the mixer regmap\n");
+		return PTR_ERR(mixer->regs);
+	}
+
+	mixer->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(mixer->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(mixer->reset);
+	}
+
+	ret = reset_control_deassert(mixer->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	mixer->bus_clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(mixer->bus_clk)) {
+		dev_err(dev, "Couldn't get the mixer bus clock\n");
+		ret = PTR_ERR(mixer->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(mixer->bus_clk);
+
+	mixer->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(mixer->mod_clk)) {
+		dev_err(dev, "Couldn't get the mixer module clock\n");
+		ret = PTR_ERR(mixer->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(mixer->mod_clk);
+
+	/* Reset the registers */
+	for (i = 0x0; i < 0x20000; i += 4)
+		regmap_write(mixer->regs, i, 0);
+
+	/* Enable the mixer */
+	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+	/* Initialize blender */
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+		     SUN8I_MIXER_BLEND_MODE_DEF);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+		regmap_write(mixer->regs,
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+	/* Select the first UI channel */
+	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+			 mixer->cfg->vi_num);
+	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+		     mixer->cfg->vi_num);
+
+	return 0;
+
+	clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+	reset_control_assert(mixer->reset);
+	return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(mixer->mod_clk);
+	clk_disable_unprepare(mixer->bus_clk);
+	reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+	.bind	= sun8i_mixer_bind,
+	.unbind	= sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun8i_mixer_ops);
+
+	return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+	.vi_num = 2,
+	.ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+	{
+		.compatible = "allwinner,sun8i-v3s-de2-mixer",
+		.data = &sun8i_v3s_mixer_cfg,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+	.probe		= sun8i_mixer_probe,
+	.remove		= sun8i_mixer_remove,
+	.driver		= {
+		.name		= "sun8i-mixer",
+		.of_match_table	= sun8i_mixer_of_table,
+	},
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..7b3b9d747d7d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT		4
+
+#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL			0x0
+#define SUN8I_MIXER_GLOBAL_STATUS		0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
+#define SUN8I_MIXER_GLOBAL_SIZE			0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE			0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
+#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN			0x20000
+#define SUN8I_MIXER_GSU1_EN			0x30000
+#define SUN8I_MIXER_GSU2_EN			0x40000
+#define SUN8I_MIXER_GSU3_EN			0x50000
+#define SUN8I_MIXER_FCE_EN			0xa0000
+#define SUN8I_MIXER_BWS_EN			0xa2000
+#define SUN8I_MIXER_LTI_EN			0xa4000
+#define SUN8I_MIXER_PEAK_EN			0xa6000
+#define SUN8I_MIXER_ASE_EN			0xa8000
+#define SUN8I_MIXER_FCC_EN			0xaa000
+#define SUN8I_MIXER_DCSC_EN			0xb0000
+
+struct sun8i_mixer_cfg {
+	int		vi_num;
+	int		ui_num;
+};
+
+struct sun8i_mixer {
+	struct regmap			*regs;
+
+	const struct sun8i_mixer_cfg	*cfg;
+
+	struct reset_control		*reset;
+
+	struct clk			*bus_clk;
+	struct clk			*mod_clk;
+};
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+				int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+				     int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+				       int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+				      int layer, struct drm_plane *plane);
+#endif /* _SUN8I_MIXER_H_ */
-- 
2.12.0

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

* [PATCH v3 07/11] drm/sun4i: Add compatible string for V3s display engine
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

Allwinner V3s features the new "Display Engine 2.0", which can now also
be driven with our subdrivers in sun4i-drm.

Add the compatible string for in sun4i_drv.c, in order to make the
display engine and its components probed.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Patch splited in v3.

 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 8ddd72cd5873..68c0b754cdb5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -294,6 +294,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31-display-engine" },
 	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
+	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
-- 
2.12.0

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

* [PATCH v3 07/11] drm/sun4i: Add compatible string for V3s display engine
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

Allwinner V3s features the new "Display Engine 2.0", which can now also
be driven with our subdrivers in sun4i-drm.

Add the compatible string for in sun4i_drv.c, in order to make the
display engine and its components probed.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Patch splited in v3.

 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 8ddd72cd5873..68c0b754cdb5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -294,6 +294,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31-display-engine" },
 	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
+	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
-- 
2.12.0

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

* [PATCH v3 07/11] drm/sun4i: Add compatible string for V3s display engine
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

Allwinner V3s features the new "Display Engine 2.0", which can now also
be driven with our subdrivers in sun4i-drm.

Add the compatible string for in sun4i_drv.c, in order to make the
display engine and its components probed.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
Patch splited in v3.

 drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 8ddd72cd5873..68c0b754cdb5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -294,6 +294,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun6i-a31-display-engine" },
 	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
+	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
-- 
2.12.0

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

* [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 68c0b754cdb5..736b28e47281 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -176,7 +176,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
-		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
 static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 2f330e4e2ead..1a710d7d6a74 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	/* nothing is supported */
 };
 
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.12.0

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

* [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 68c0b754cdb5..736b28e47281 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -176,7 +176,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
-		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
 static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 2f330e4e2ead..1a710d7d6a74 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	/* nothing is supported */
 };
 
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.12.0

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

* [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 68c0b754cdb5..736b28e47281 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -176,7 +176,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
-		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
 static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 2f330e4e2ead..1a710d7d6a74 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	/* nothing is supported */
 };
 
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 drivers/gpu/drm/sun4i/sun4i_drv.c  | 3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 68c0b754cdb5..736b28e47281 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -176,7 +176,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
-		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
 }
 
 static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 2f330e4e2ead..1a710d7d6a74 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	/* nothing is supported */
 };
 
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
-- 
2.12.0

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

* [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.

Add device nodes for it as well as the TCON.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Change the size of de2_clocks regs according to the binding example.

 arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..ae23746731a8 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -59,6 +63,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-v3s-display-engine";
+		allwinner,pipelines = <&de2_mixer0>;
+		status = "disabled";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
 		#size-cells = <1>;
 		ranges;
 
+		de2_clocks: clock@01000000 {
+			compatible = "allwinner,sun50i-h5-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		de2_mixer0: mixer@01100000 {
+			compatible = "allwinner,sun8i-v3s-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&de2_clocks CLK_MIXER0>,
+				 <&de2_clocks CLK_BUS_MIXER0>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&de2_clocks RST_MIXER0>;
+			assigned-clocks = <&de2_clocks CLK_MIXER0>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun8i-v3s-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON0>,
+				 <&ccu CLK_TCON0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON0>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.12.0

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

* [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.

Add device nodes for it as well as the TCON.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Change the size of de2_clocks regs according to the binding example.

 arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..ae23746731a8 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -59,6 +63,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-v3s-display-engine";
+		allwinner,pipelines = <&de2_mixer0>;
+		status = "disabled";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
 		#size-cells = <1>;
 		ranges;
 
+		de2_clocks: clock@01000000 {
+			compatible = "allwinner,sun50i-h5-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		de2_mixer0: mixer@01100000 {
+			compatible = "allwinner,sun8i-v3s-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&de2_clocks CLK_MIXER0>,
+				 <&de2_clocks CLK_BUS_MIXER0>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&de2_clocks RST_MIXER0>;
+			assigned-clocks = <&de2_clocks CLK_MIXER0>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun8i-v3s-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON0>,
+				 <&ccu CLK_TCON0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON0>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.12.0

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

* [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.

Add device nodes for it as well as the TCON.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Change the size of de2_clocks regs according to the binding example.

 arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..ae23746731a8 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -59,6 +63,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-v3s-display-engine";
+		allwinner,pipelines = <&de2_mixer0>;
+		status = "disabled";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
 		#size-cells = <1>;
 		ranges;
 
+		de2_clocks: clock@01000000 {
+			compatible = "allwinner,sun50i-h5-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		de2_mixer0: mixer@01100000 {
+			compatible = "allwinner,sun8i-v3s-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&de2_clocks CLK_MIXER0>,
+				 <&de2_clocks CLK_BUS_MIXER0>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&de2_clocks RST_MIXER0>;
+			assigned-clocks = <&de2_clocks CLK_MIXER0>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun8i-v3s-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON0>,
+				 <&ccu CLK_TCON0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON0>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.

Add device nodes for it as well as the TCON.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes in v3:
- Change the size of de2_clocks regs according to the binding example.

 arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..ae23746731a8 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -59,6 +63,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-v3s-display-engine";
+		allwinner,pipelines = <&de2_mixer0>;
+		status = "disabled";
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
 		#size-cells = <1>;
 		ranges;
 
+		de2_clocks: clock at 01000000 {
+			compatible = "allwinner,sun50i-h5-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		de2_mixer0: mixer at 01100000 {
+			compatible = "allwinner,sun8i-v3s-de2-mixer";
+			reg = <0x01100000 0x100000>;
+			clocks = <&de2_clocks CLK_MIXER0>,
+				 <&de2_clocks CLK_BUS_MIXER0>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&de2_clocks RST_MIXER0>;
+			assigned-clocks = <&de2_clocks CLK_MIXER0>;
+			assigned-clock-rates = <150000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					mixer0_out_tcon0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_mixer0>;
+					};
+				};
+			};
+		};
+
+		tcon0: lcd-controller at 01c0c000 {
+			compatible = "allwinner,sun8i-v3s-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON0>,
+				 <&ccu CLK_TCON0>;
+			clock-names = "ahb",
+				      "tcon-ch0";
+			clock-output-names = "tcon-pixel-clock";
+			resets = <&ccu RST_BUS_TCON0>;
+			reset-names = "lcd";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_mixer0: endpoint at 0 {
+						reg = <0>;
+						remote-endpoint = <&mixer0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
-- 
2.12.0

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

* [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.

Add pinctrl node for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index ae23746731a8..ac783a8a4fd3 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
 				function = "i2c0";
 			};
 
+			lcd_rgb666_pins: lcd_rgb666@0 {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE10", "PE11", "PE12", "PE13", "PE14",
+				       "PE15", "PE16", "PE17", "PE18", "PE19",
+				       "PE23", "PE24";
+				function = "lcd";
+			};
+
 			uart0_pins_a: uart0@0 {
 				pins = "PB8", "PB9";
 				function = "uart0";
-- 
2.12.0

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

* [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.

Add pinctrl node for them.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index ae23746731a8..ac783a8a4fd3 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
 				function = "i2c0";
 			};
 
+			lcd_rgb666_pins: lcd_rgb666@0 {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE10", "PE11", "PE12", "PE13", "PE14",
+				       "PE15", "PE16", "PE17", "PE18", "PE19",
+				       "PE23", "PE24";
+				function = "lcd";
+			};
+
 			uart0_pins_a: uart0@0 {
 				pins = "PB8", "PB9";
 				function = "uart0";
-- 
2.12.0

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

* [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.

Add pinctrl node for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index ae23746731a8..ac783a8a4fd3 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
 				function = "i2c0";
 			};
 
+			lcd_rgb666_pins: lcd_rgb666@0 {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE10", "PE11", "PE12", "PE13", "PE14",
+				       "PE15", "PE16", "PE17", "PE18", "PE19",
+				       "PE23", "PE24";
+				function = "lcd";
+			};
+
 			uart0_pins_a: uart0@0 {
 				pins = "PB8", "PB9";
 				function = "uart0";
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.

Add pinctrl node for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index ae23746731a8..ac783a8a4fd3 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
 				function = "i2c0";
 			};
 
+			lcd_rgb666_pins: lcd_rgb666 at 0 {
+				pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+				       "PE5", "PE6", "PE7", "PE8", "PE9",
+				       "PE10", "PE11", "PE12", "PE13", "PE14",
+				       "PE15", "PE16", "PE17", "PE18", "PE19",
+				       "PE23", "PE24";
+				function = "lcd";
+			};
+
 			uart0_pins_a: uart0 at 0 {
 				pins = "PB8", "PB9";
 				function = "uart0";
-- 
2.12.0

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

* [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.xyz>

A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.

This commit connects this panel to Lichee Pi Zero.

Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
 			gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
 		};
 	};
+
+	panel: panel {
+		compatible = "qiaodian,qd43003c0-40", "simple-panel";
+		enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
 };
 
 &mmc0 {
@@ -86,6 +108,20 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-0 = <&uart0_pins_a>;
 	pinctrl-names = "default";
-- 
2.12.0

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

* [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>

A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.

This commit connects this panel to Lichee Pi Zero.

Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.

Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
 			gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
 		};
 	};
+
+	panel: panel {
+		compatible = "qiaodian,qd43003c0-40", "simple-panel";
+		enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
 };
 
 &mmc0 {
@@ -86,6 +108,20 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-0 = <&uart0_pins_a>;
 	pinctrl-names = "default";
-- 
2.12.0

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

* [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
  Cc: devicetree, linux-kernel, dri-devel, linux-sunxi, Icenowy Zheng,
	linux-clk, linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.

This commit connects this panel to Lichee Pi Zero.

Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
 			gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
 		};
 	};
+
+	panel: panel {
+		compatible = "qiaodian,qd43003c0-40", "simple-panel";
+		enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
 };
 
 &mmc0 {
@@ -86,6 +108,20 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-0 = <&uart0_pins_a>;
 	pinctrl-names = "default";
-- 
2.12.0


_______________________________________________
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] 82+ messages in thread

* [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
@ 2017-03-29 19:46   ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: Icenowy Zheng <icenowy@aosc.xyz>

A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.

This commit connects this panel to Lichee Pi Zero.

Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
 arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
 			gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
 		};
 	};
+
+	panel: panel {
+		compatible = "qiaodian,qd43003c0-40", "simple-panel";
+		enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			panel_input: endpoint at 0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_out_lcd>;
+			};
+		};
+	};
+};
+
+&de {
+	status = "okay";
 };
 
 &mmc0 {
@@ -86,6 +108,20 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+
+};
+
+&tcon0_out {
+	tcon0_out_lcd: endpoint at 0 {
+		reg = <0>;
+		remote-endpoint = <&panel_input>;
+	};
+};
+
 &uart0 {
 	pinctrl-0 = <&uart0_pins_a>;
 	pinctrl-names = "default";
-- 
2.12.0

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

* Re: [linux-sunxi] [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 22:33     ` Jernej Škrabec
  0 siblings, 0 replies; 82+ messages in thread
From: Jernej Škrabec @ 2017-03-29 22:33 UTC (permalink / raw)
  To: linux-sunxi, icenowy
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, linux-clk, devicetree,
	linux-arm-kernel, linux-kernel, dri-devel

Hi,

Dne sreda, 29. marec 2017 ob 21:46:08 CEST je Icenowy Zheng napisal(a):
> Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
> with mixers to do graphic processing and feed data to TCON, like the old
> backends and frontends.
> 
> Add support for the mixer on Allwinner V3s SoC; it's the simplest one.
> 
> Currently a lot of functions are still missing -- more investigations
> are needed to gain enough information for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/Kconfig       |  10 +
>  drivers/gpu/drm/sun4i/Makefile      |   4 +
>  drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 386
> ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun8i_mixer.h |
> 131 ++++++++++++
>  6 files changed, 722 insertions(+)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> index 5a8227f37cc4..15557484520d 100644
> --- a/drivers/gpu/drm/sun4i/Kconfig
> +++ b/drivers/gpu/drm/sun4i/Kconfig
> @@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
>  	  original Allwinner Display Engine, which has a backend to
>  	  do some alpha blending and feed graphics to TCON. If M is
>  	  selected the module will be called sun4i-backend.
> +
> +config DRM_SUN4I_SUN8I_MIXER
> +	tristate "Support for Allwinner Display Engine 2.0 Mixer"
> +	depends on DRM_SUN4I
> +	default MACH_SUN8I
> +	help
> +	  Choose this option if you have an Allwinner SoC with the
> +	  Allwinner Display Engine 2.0, which has a mixer to do some
> +	  graphics mixture and feed graphics to TCON, If M is
> +	  selected the module will be called sun8i-mixer.
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 1db1068b9be1..7625c2dad1bb 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
>  sun4i-backend-y += sun4i_layer.o
>  sun4i-backend-y += sun4i_backend.o
> 
> +sun8i-mixer-y += sun8i_layer.o
> +sun8i-mixer-y += sun8i_mixer.o
> +
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c
> b/drivers/gpu/drm/sun4i/sun8i_layer.c new file mode 100644
> index 000000000000..5cc4a7f8a7ae
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
> @@ -0,0 +1,156 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun8i_layer.h"
> +#include "sun8i_mixer.h"
> +#include "sunxi_layer.h"
> +
> +struct sun8i_plane_desc {
> +	       enum drm_plane_type     type;
> +	       const uint32_t          *formats;
> +	       uint32_t                nformats;
> +};
> +
> +static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
> +					    struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
> +					       struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_layer_enable(mixer, layer->id, false);
> +}
> +
> +static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
> +					      struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
> +	sun8i_mixer_layer_enable(mixer, layer->id, true);
> +}
> +
> +static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
> +	.atomic_check	= sun8i_mixer_layer_atomic_check,
> +	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
> +	.atomic_update	= sun8i_mixer_layer_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
> +	.destroy		= drm_plane_cleanup,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.reset			= drm_atomic_helper_plane_reset,
> +	.update_plane		= drm_atomic_helper_update_plane,
> +};
> +
> +static const uint32_t sun8i_mixer_layer_formats[] = {
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
> +	{
> +		.type = DRM_PLANE_TYPE_PRIMARY,
> +		.formats = sun8i_mixer_layer_formats,
> +		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
> +	},
> +};
> +
> +static struct drm_plane *sun8i_layer_get_plane(void *layer)
> +{
> +	struct sun8i_layer *sun8i_layer = layer;
> +
> +	return &sun8i_layer->plane;
> +}
> +
> +static const struct sunxi_layer_ops layer_ops = {
> +	.get_plane = sun8i_layer_get_plane,
> +};
> +
> +static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
> +						struct sun8i_mixer *mixer,
> +						const struct sun8i_plane_desc *plane)
> +{
> +	struct sun8i_layer *layer;
> +	int ret;
> +
> +	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
> +	if (!layer)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* possible crtcs are set later */
> +	ret = drm_universal_plane_init(drm, &layer->plane, 0,
> +				       &sun8i_mixer_layer_funcs,
> +				       plane->formats, plane->nformats,
> +				       plane->type, NULL);
> +	if (ret) {
> +		dev_err(drm->dev, "Couldn't initialize layer\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	drm_plane_helper_add(&layer->plane,
> +			     &sun8i_mixer_layer_helper_funcs);
> +	layer->mixer = mixer;
> +
> +	return layer;
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
> +{
> +	struct sun8i_layer **layers;
> +	struct sun8i_mixer *mixer = crtc->mixer;
> +	int i;
> +
> +	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
> +			      sizeof(*layers), GFP_KERNEL);
> +	if (!layers)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
> +		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
> +		struct sun8i_layer *layer;
> +
> +		layer = sun8i_layer_init_one(drm, mixer, plane);
> +		if (IS_ERR(layer)) {
> +			dev_err(drm->dev, "Couldn't initialize %s plane\n",
> +				i ? "overlay" : "primary");
> +			return ERR_CAST(layer);
> +		};
> +
> +		layer->id = i;
> +		layers[i] = layer;
> +	};
> +
> +	/* Assign layer ops to the CRTC */
> +	crtc->layer_ops = &layer_ops;
> +
> +	return (void **)layers;
> +}
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h
> b/drivers/gpu/drm/sun4i/sun8i_layer.h new file mode 100644
> index 000000000000..9f145ce842f2
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_LAYER_H_
> +#define _SUN8I_LAYER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sun8i_layer {
> +	struct drm_plane	plane;
> +	struct sun4i_drv	*drv;
> +	struct sun8i_mixer	*mixer;
> +	int			id;
> +};
> +
> +static inline struct sun8i_layer *
> +plane_to_sun8i_layer(struct drm_plane *plane)
> +{
> +	return container_of(plane, struct sun8i_layer, plane);
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
> +#endif /* _SUN8I_LAYER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c new file mode 100644
> index 000000000000..1399d1a6c678
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -0,0 +1,386 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_backend.c, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include <linux/component.h>
> +#include <linux/reset.h>
> +#include <linux/of_device.h>
> +
> +#include "sun4i_drv.h"
> +#include "sun8i_mixer.h"
> +#include "sun8i_layer.h"
> +#include "sunxi_mixer.h"
> +
> +void sun8i_mixer_commit(void *mixer)
> +{
> +	struct sun8i_mixer *sun8i_mixer = mixer;
> +
> +	DRM_DEBUG_DRIVER("Committing changes\n");
> +
> +	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
> +		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
> +}
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable)
> +{

Layer parameter will be always 0 for now, right?

> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +
> +	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
> +
> +	if (enable)
> +		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> +	else
> +		val = 0;
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> +
> +	/* Set the alpha configuration */
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
> +}
> +EXPORT_SYMBOL(sun8i_mixer_layer_enable);
> +
> +static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
> +					     u32 format, u32 *mode)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_XRGB8888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
> +		break;
> +
> +	case DRM_FORMAT_RGB888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int i;
> +
> +	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> +
> +	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
> +		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
> +				 state->crtc_w, state->crtc_h);
> +		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating blender size\n");
> +		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +			regmap_write(mixer->regs,
> +				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
> +				     SUN8I_MIXER_SIZE(state->crtc_w,
> +						      state->crtc_h));

Since only one blend channel is used, you only have to set the first for now.

> +		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating channel size\n");
> +		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +	}
> +
> +	/* Set the line width */
> +	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
> +		     fb->pitches[0]);
> +
> +	/* Set height and width */
> +	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
> +			 state->crtc_w, state->crtc_h);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
> +		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
> +
> +	/* Set base coordinates */
> +	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
> +			 state->crtc_x, state->crtc_y);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
> +		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
> +
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	bool interlaced = false;
> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int ret;
> +
> +	if (plane->state->crtc)
> +		interlaced = plane->state->crtc->state->adjusted_mode.flags
> +			& DRM_MODE_FLAG_INTERLACE;
> +
> +	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
> +			   interlaced ?
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
> +
> +	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
> +			 interlaced ? "on" : "off");
> +
> +	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
> +						&val);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("Invalid format\n");
> +		return ret;
> +	}
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
> +
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	struct drm_gem_cma_object *gem;
> +	dma_addr_t paddr;
> +	uint32_t paddr_u32;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int bpp;
> +
> +	/* Get the physical address of the buffer in memory */
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
> +
> +	/* Compute the start of the displayed memory */
> +	bpp = fb->format->cpp[0];
> +	paddr = gem->paddr + fb->offsets[0];
> +	paddr += (state->src_x >> 16) * bpp;
> +	paddr += (state->src_y >> 16) * fb->pitches[0];
> +
> +	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> +
> +	paddr_u32 = (uint32_t) paddr;
> +
> +	regmap_write(mixer->regs,
> +		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
> +		     paddr_u32);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
> +
> +static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
> +	.commit = sun8i_mixer_commit,
> +	.layers_init = sun8i_layers_init,
> +};
> +
> +static struct regmap_config sun8i_mixer_regmap_config = {
> +	.reg_bits	= 32,
> +	.val_bits	= 32,
> +	.reg_stride	= 4,
> +	.max_register	= 0xbffc, /* guessed */
> +};
> +
> +static int sun8i_mixer_bind(struct device *dev, struct device *master,
> +			      void *data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct drm_device *drm = data;
> +	struct sun4i_drv *drv = drm->dev_private;
> +	struct sun8i_mixer *mixer;
> +	struct resource *res;
> +	void __iomem *regs;
> +	int i, ret;
> +
> +	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
> +	if (!mixer)
> +		return -ENOMEM;
> +	dev_set_drvdata(dev, mixer);
> +	drv->mixer = mixer;
> +	drv->mixer_ops = &sun8i_mixer_mixer_ops;
> +
> +	mixer->cfg = of_device_get_match_data(dev);
> +	if (!mixer->cfg)
> +		return -EINVAL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	mixer->regs = devm_regmap_init_mmio(dev, regs,
> +					      &sun8i_mixer_regmap_config);
> +	if (IS_ERR(mixer->regs)) {
> +		dev_err(dev, "Couldn't create the mixer regmap\n");
> +		return PTR_ERR(mixer->regs);
> +	}
> +
> +	mixer->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(mixer->reset)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(mixer->reset);
> +	}
> +
> +	ret = reset_control_deassert(mixer->reset);
> +	if (ret) {
> +		dev_err(dev, "Couldn't deassert our reset line\n");
> +		return ret;
> +	}
> +
> +	mixer->bus_clk = devm_clk_get(dev, "bus");
> +	if (IS_ERR(mixer->bus_clk)) {
> +		dev_err(dev, "Couldn't get the mixer bus clock\n");
> +		ret = PTR_ERR(mixer->bus_clk);
> +		goto err_assert_reset;
> +	}
> +	clk_prepare_enable(mixer->bus_clk);
> +
> +	mixer->mod_clk = devm_clk_get(dev, "mod");
> +	if (IS_ERR(mixer->mod_clk)) {
> +		dev_err(dev, "Couldn't get the mixer module clock\n");
> +		ret = PTR_ERR(mixer->mod_clk);
> +		goto err_disable_bus_clk;
> +	}
> +	clk_prepare_enable(mixer->mod_clk);
> +
> +	/* Reset the registers */
> +	for (i = 0x0; i < 0x20000; i += 4)
> +		regmap_write(mixer->regs, i, 0);
> +
> +	/* Enable the mixer */
> +	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
> +		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
> +
> +	/* Initialize blender */
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
> +		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
> +		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
> +		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);

Blend mode has to be set only for active layers, so above statement is not 
needed currently.

> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
> +		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
> +
> +	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +		regmap_write(mixer->regs,
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);

Ditto. Setting first layer is enough.

> +
> +	/* Select the first UI channel */
> +	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
> +			 mixer->cfg->vi_num);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
> +		     mixer->cfg->vi_num);
> +
> +	return 0;
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +err_disable_bus_clk:
> +	clk_disable_unprepare(mixer->bus_clk);
> +err_assert_reset:
> +	reset_control_assert(mixer->reset);
> +	return ret;
> +}
> +
> +static void sun8i_mixer_unbind(struct device *dev, struct device *master,
> +				 void *data)
> +{
> +	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +	clk_disable_unprepare(mixer->bus_clk);
> +	reset_control_assert(mixer->reset);
> +}
> +
> +static const struct component_ops sun8i_mixer_ops = {
> +	.bind	= sun8i_mixer_bind,
> +	.unbind	= sun8i_mixer_unbind,
> +};
> +
> +static int sun8i_mixer_probe(struct platform_device *pdev)
> +{
> +	return component_add(&pdev->dev, &sun8i_mixer_ops);
> +}
> +
> +static int sun8i_mixer_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &sun8i_mixer_ops);
> +
> +	return 0;
> +}
> +
> +static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
> +	.vi_num = 2,
> +	.ui_num = 1,
> +};
> +
> +static const struct of_device_id sun8i_mixer_of_table[] = {
> +	{
> +		.compatible = "allwinner,sun8i-v3s-de2-mixer",
> +		.data = &sun8i_v3s_mixer_cfg,
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
> +
> +static struct platform_driver sun8i_mixer_platform_driver = {
> +	.probe		= sun8i_mixer_probe,
> +	.remove		= sun8i_mixer_remove,
> +	.driver		= {
> +		.name		= "sun8i-mixer",
> +		.of_match_table	= sun8i_mixer_of_table,
> +	},
> +};
> +module_platform_driver(sun8i_mixer_platform_driver);
> +
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
> +MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h new file mode 100644
> index 000000000000..7b3b9d747d7d
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -0,0 +1,131 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_MIXER_H_
> +#define _SUN8I_MIXER_H_
> +
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include "sun4i_layer.h"
> +
> +#define SUN8I_MIXER_MAX_CHAN_COUNT		4
> +
> +#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
> +#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
> +
> +#define SUN8I_MIXER_GLOBAL_CTL			0x0
> +#define SUN8I_MIXER_GLOBAL_STATUS		0x4
> +#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
> +#define SUN8I_MIXER_GLOBAL_SIZE			0xc
> +
> +#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
> +
> +#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
> +
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
> +#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
> +#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
> +#define SUN8I_MIXER_BLEND_ROUTE			0x1080
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
> +#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
> +#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
> +#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
> +#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
> +#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
> +
> +/* The following numbers are some still unknown magic numbers */
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
> +#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
> +#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
> +#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
> +
> +#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
> +
> +/*
> + * VI channels are not used now, but the support of them may be introduced
> in + * the future.
> + */
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
> +#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
> +#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
> +#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
> +
> +/*
> + * These sun-engines are still unknown now, the EN registers are here only

Typo, should be "sub".

Regards,
Jernej

> to + * be used to disable these sub-engines.
> + */
> +#define SUN8I_MIXER_VSU_EN			0x20000
> +#define SUN8I_MIXER_GSU1_EN			0x30000
> +#define SUN8I_MIXER_GSU2_EN			0x40000
> +#define SUN8I_MIXER_GSU3_EN			0x50000
> +#define SUN8I_MIXER_FCE_EN			0xa0000
> +#define SUN8I_MIXER_BWS_EN			0xa2000
> +#define SUN8I_MIXER_LTI_EN			0xa4000
> +#define SUN8I_MIXER_PEAK_EN			0xa6000
> +#define SUN8I_MIXER_ASE_EN			0xa8000
> +#define SUN8I_MIXER_FCC_EN			0xaa000
> +#define SUN8I_MIXER_DCSC_EN			0xb0000
> +
> +struct sun8i_mixer_cfg {
> +	int		vi_num;
> +	int		ui_num;
> +};
> +
> +struct sun8i_mixer {
> +	struct regmap			*regs;
> +
> +	const struct sun8i_mixer_cfg	*cfg;
> +
> +	struct reset_control		*reset;
> +
> +	struct clk			*bus_clk;
> +	struct clk			*mod_clk;
> +};
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable);
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane);
> +#endif /* _SUN8I_MIXER_H_ */
> --
> 2.12.0
> 
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group. To unsubscribe from this group and stop receiving
> emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 22:33     ` Jernej Škrabec
  0 siblings, 0 replies; 82+ messages in thread
From: Jernej Škrabec @ 2017-03-29 22:33 UTC (permalink / raw)
  To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, icenowy-h8G6r0blFSE
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Hi,

Dne sreda, 29. marec 2017 ob 21:46:08 CEST je Icenowy Zheng napisal(a):
> Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
> with mixers to do graphic processing and feed data to TCON, like the old
> backends and frontends.
> 
> Add support for the mixer on Allwinner V3s SoC; it's the simplest one.
> 
> Currently a lot of functions are still missing -- more investigations
> are needed to gain enough information for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/Kconfig       |  10 +
>  drivers/gpu/drm/sun4i/Makefile      |   4 +
>  drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 386
> ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun8i_mixer.h |
> 131 ++++++++++++
>  6 files changed, 722 insertions(+)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> index 5a8227f37cc4..15557484520d 100644
> --- a/drivers/gpu/drm/sun4i/Kconfig
> +++ b/drivers/gpu/drm/sun4i/Kconfig
> @@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
>  	  original Allwinner Display Engine, which has a backend to
>  	  do some alpha blending and feed graphics to TCON. If M is
>  	  selected the module will be called sun4i-backend.
> +
> +config DRM_SUN4I_SUN8I_MIXER
> +	tristate "Support for Allwinner Display Engine 2.0 Mixer"
> +	depends on DRM_SUN4I
> +	default MACH_SUN8I
> +	help
> +	  Choose this option if you have an Allwinner SoC with the
> +	  Allwinner Display Engine 2.0, which has a mixer to do some
> +	  graphics mixture and feed graphics to TCON, If M is
> +	  selected the module will be called sun8i-mixer.
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 1db1068b9be1..7625c2dad1bb 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
>  sun4i-backend-y += sun4i_layer.o
>  sun4i-backend-y += sun4i_backend.o
> 
> +sun8i-mixer-y += sun8i_layer.o
> +sun8i-mixer-y += sun8i_mixer.o
> +
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c
> b/drivers/gpu/drm/sun4i/sun8i_layer.c new file mode 100644
> index 000000000000..5cc4a7f8a7ae
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
> @@ -0,0 +1,156 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun8i_layer.h"
> +#include "sun8i_mixer.h"
> +#include "sunxi_layer.h"
> +
> +struct sun8i_plane_desc {
> +	       enum drm_plane_type     type;
> +	       const uint32_t          *formats;
> +	       uint32_t                nformats;
> +};
> +
> +static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
> +					    struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
> +					       struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_layer_enable(mixer, layer->id, false);
> +}
> +
> +static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
> +					      struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
> +	sun8i_mixer_layer_enable(mixer, layer->id, true);
> +}
> +
> +static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
> +	.atomic_check	= sun8i_mixer_layer_atomic_check,
> +	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
> +	.atomic_update	= sun8i_mixer_layer_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
> +	.destroy		= drm_plane_cleanup,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.reset			= drm_atomic_helper_plane_reset,
> +	.update_plane		= drm_atomic_helper_update_plane,
> +};
> +
> +static const uint32_t sun8i_mixer_layer_formats[] = {
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
> +	{
> +		.type = DRM_PLANE_TYPE_PRIMARY,
> +		.formats = sun8i_mixer_layer_formats,
> +		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
> +	},
> +};
> +
> +static struct drm_plane *sun8i_layer_get_plane(void *layer)
> +{
> +	struct sun8i_layer *sun8i_layer = layer;
> +
> +	return &sun8i_layer->plane;
> +}
> +
> +static const struct sunxi_layer_ops layer_ops = {
> +	.get_plane = sun8i_layer_get_plane,
> +};
> +
> +static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
> +						struct sun8i_mixer *mixer,
> +						const struct sun8i_plane_desc *plane)
> +{
> +	struct sun8i_layer *layer;
> +	int ret;
> +
> +	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
> +	if (!layer)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* possible crtcs are set later */
> +	ret = drm_universal_plane_init(drm, &layer->plane, 0,
> +				       &sun8i_mixer_layer_funcs,
> +				       plane->formats, plane->nformats,
> +				       plane->type, NULL);
> +	if (ret) {
> +		dev_err(drm->dev, "Couldn't initialize layer\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	drm_plane_helper_add(&layer->plane,
> +			     &sun8i_mixer_layer_helper_funcs);
> +	layer->mixer = mixer;
> +
> +	return layer;
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
> +{
> +	struct sun8i_layer **layers;
> +	struct sun8i_mixer *mixer = crtc->mixer;
> +	int i;
> +
> +	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
> +			      sizeof(*layers), GFP_KERNEL);
> +	if (!layers)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
> +		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
> +		struct sun8i_layer *layer;
> +
> +		layer = sun8i_layer_init_one(drm, mixer, plane);
> +		if (IS_ERR(layer)) {
> +			dev_err(drm->dev, "Couldn't initialize %s plane\n",
> +				i ? "overlay" : "primary");
> +			return ERR_CAST(layer);
> +		};
> +
> +		layer->id = i;
> +		layers[i] = layer;
> +	};
> +
> +	/* Assign layer ops to the CRTC */
> +	crtc->layer_ops = &layer_ops;
> +
> +	return (void **)layers;
> +}
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h
> b/drivers/gpu/drm/sun4i/sun8i_layer.h new file mode 100644
> index 000000000000..9f145ce842f2
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_LAYER_H_
> +#define _SUN8I_LAYER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sun8i_layer {
> +	struct drm_plane	plane;
> +	struct sun4i_drv	*drv;
> +	struct sun8i_mixer	*mixer;
> +	int			id;
> +};
> +
> +static inline struct sun8i_layer *
> +plane_to_sun8i_layer(struct drm_plane *plane)
> +{
> +	return container_of(plane, struct sun8i_layer, plane);
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
> +#endif /* _SUN8I_LAYER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c new file mode 100644
> index 000000000000..1399d1a6c678
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -0,0 +1,386 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * Based on sun4i_backend.c, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include <linux/component.h>
> +#include <linux/reset.h>
> +#include <linux/of_device.h>
> +
> +#include "sun4i_drv.h"
> +#include "sun8i_mixer.h"
> +#include "sun8i_layer.h"
> +#include "sunxi_mixer.h"
> +
> +void sun8i_mixer_commit(void *mixer)
> +{
> +	struct sun8i_mixer *sun8i_mixer = mixer;
> +
> +	DRM_DEBUG_DRIVER("Committing changes\n");
> +
> +	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
> +		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
> +}
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable)
> +{

Layer parameter will be always 0 for now, right?

> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +
> +	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
> +
> +	if (enable)
> +		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> +	else
> +		val = 0;
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> +
> +	/* Set the alpha configuration */
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
> +}
> +EXPORT_SYMBOL(sun8i_mixer_layer_enable);
> +
> +static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
> +					     u32 format, u32 *mode)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_XRGB8888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
> +		break;
> +
> +	case DRM_FORMAT_RGB888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int i;
> +
> +	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> +
> +	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
> +		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
> +				 state->crtc_w, state->crtc_h);
> +		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating blender size\n");
> +		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +			regmap_write(mixer->regs,
> +				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
> +				     SUN8I_MIXER_SIZE(state->crtc_w,
> +						      state->crtc_h));

Since only one blend channel is used, you only have to set the first for now.

> +		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating channel size\n");
> +		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +	}
> +
> +	/* Set the line width */
> +	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
> +		     fb->pitches[0]);
> +
> +	/* Set height and width */
> +	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
> +			 state->crtc_w, state->crtc_h);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
> +		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
> +
> +	/* Set base coordinates */
> +	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
> +			 state->crtc_x, state->crtc_y);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
> +		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
> +
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	bool interlaced = false;
> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int ret;
> +
> +	if (plane->state->crtc)
> +		interlaced = plane->state->crtc->state->adjusted_mode.flags
> +			& DRM_MODE_FLAG_INTERLACE;
> +
> +	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
> +			   interlaced ?
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
> +
> +	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
> +			 interlaced ? "on" : "off");
> +
> +	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
> +						&val);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("Invalid format\n");
> +		return ret;
> +	}
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
> +
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	struct drm_gem_cma_object *gem;
> +	dma_addr_t paddr;
> +	uint32_t paddr_u32;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int bpp;
> +
> +	/* Get the physical address of the buffer in memory */
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
> +
> +	/* Compute the start of the displayed memory */
> +	bpp = fb->format->cpp[0];
> +	paddr = gem->paddr + fb->offsets[0];
> +	paddr += (state->src_x >> 16) * bpp;
> +	paddr += (state->src_y >> 16) * fb->pitches[0];
> +
> +	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> +
> +	paddr_u32 = (uint32_t) paddr;
> +
> +	regmap_write(mixer->regs,
> +		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
> +		     paddr_u32);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
> +
> +static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
> +	.commit = sun8i_mixer_commit,
> +	.layers_init = sun8i_layers_init,
> +};
> +
> +static struct regmap_config sun8i_mixer_regmap_config = {
> +	.reg_bits	= 32,
> +	.val_bits	= 32,
> +	.reg_stride	= 4,
> +	.max_register	= 0xbffc, /* guessed */
> +};
> +
> +static int sun8i_mixer_bind(struct device *dev, struct device *master,
> +			      void *data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct drm_device *drm = data;
> +	struct sun4i_drv *drv = drm->dev_private;
> +	struct sun8i_mixer *mixer;
> +	struct resource *res;
> +	void __iomem *regs;
> +	int i, ret;
> +
> +	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
> +	if (!mixer)
> +		return -ENOMEM;
> +	dev_set_drvdata(dev, mixer);
> +	drv->mixer = mixer;
> +	drv->mixer_ops = &sun8i_mixer_mixer_ops;
> +
> +	mixer->cfg = of_device_get_match_data(dev);
> +	if (!mixer->cfg)
> +		return -EINVAL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	mixer->regs = devm_regmap_init_mmio(dev, regs,
> +					      &sun8i_mixer_regmap_config);
> +	if (IS_ERR(mixer->regs)) {
> +		dev_err(dev, "Couldn't create the mixer regmap\n");
> +		return PTR_ERR(mixer->regs);
> +	}
> +
> +	mixer->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(mixer->reset)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(mixer->reset);
> +	}
> +
> +	ret = reset_control_deassert(mixer->reset);
> +	if (ret) {
> +		dev_err(dev, "Couldn't deassert our reset line\n");
> +		return ret;
> +	}
> +
> +	mixer->bus_clk = devm_clk_get(dev, "bus");
> +	if (IS_ERR(mixer->bus_clk)) {
> +		dev_err(dev, "Couldn't get the mixer bus clock\n");
> +		ret = PTR_ERR(mixer->bus_clk);
> +		goto err_assert_reset;
> +	}
> +	clk_prepare_enable(mixer->bus_clk);
> +
> +	mixer->mod_clk = devm_clk_get(dev, "mod");
> +	if (IS_ERR(mixer->mod_clk)) {
> +		dev_err(dev, "Couldn't get the mixer module clock\n");
> +		ret = PTR_ERR(mixer->mod_clk);
> +		goto err_disable_bus_clk;
> +	}
> +	clk_prepare_enable(mixer->mod_clk);
> +
> +	/* Reset the registers */
> +	for (i = 0x0; i < 0x20000; i += 4)
> +		regmap_write(mixer->regs, i, 0);
> +
> +	/* Enable the mixer */
> +	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
> +		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
> +
> +	/* Initialize blender */
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
> +		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
> +		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
> +		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);

Blend mode has to be set only for active layers, so above statement is not 
needed currently.

> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
> +		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
> +
> +	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +		regmap_write(mixer->regs,
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);

Ditto. Setting first layer is enough.

> +
> +	/* Select the first UI channel */
> +	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
> +			 mixer->cfg->vi_num);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
> +		     mixer->cfg->vi_num);
> +
> +	return 0;
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +err_disable_bus_clk:
> +	clk_disable_unprepare(mixer->bus_clk);
> +err_assert_reset:
> +	reset_control_assert(mixer->reset);
> +	return ret;
> +}
> +
> +static void sun8i_mixer_unbind(struct device *dev, struct device *master,
> +				 void *data)
> +{
> +	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +	clk_disable_unprepare(mixer->bus_clk);
> +	reset_control_assert(mixer->reset);
> +}
> +
> +static const struct component_ops sun8i_mixer_ops = {
> +	.bind	= sun8i_mixer_bind,
> +	.unbind	= sun8i_mixer_unbind,
> +};
> +
> +static int sun8i_mixer_probe(struct platform_device *pdev)
> +{
> +	return component_add(&pdev->dev, &sun8i_mixer_ops);
> +}
> +
> +static int sun8i_mixer_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &sun8i_mixer_ops);
> +
> +	return 0;
> +}
> +
> +static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
> +	.vi_num = 2,
> +	.ui_num = 1,
> +};
> +
> +static const struct of_device_id sun8i_mixer_of_table[] = {
> +	{
> +		.compatible = "allwinner,sun8i-v3s-de2-mixer",
> +		.data = &sun8i_v3s_mixer_cfg,
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
> +
> +static struct platform_driver sun8i_mixer_platform_driver = {
> +	.probe		= sun8i_mixer_probe,
> +	.remove		= sun8i_mixer_remove,
> +	.driver		= {
> +		.name		= "sun8i-mixer",
> +		.of_match_table	= sun8i_mixer_of_table,
> +	},
> +};
> +module_platform_driver(sun8i_mixer_platform_driver);
> +
> +MODULE_AUTHOR("Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>");
> +MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h new file mode 100644
> index 000000000000..7b3b9d747d7d
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -0,0 +1,131 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_MIXER_H_
> +#define _SUN8I_MIXER_H_
> +
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include "sun4i_layer.h"
> +
> +#define SUN8I_MIXER_MAX_CHAN_COUNT		4
> +
> +#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
> +#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
> +
> +#define SUN8I_MIXER_GLOBAL_CTL			0x0
> +#define SUN8I_MIXER_GLOBAL_STATUS		0x4
> +#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
> +#define SUN8I_MIXER_GLOBAL_SIZE			0xc
> +
> +#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
> +
> +#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
> +
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
> +#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
> +#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
> +#define SUN8I_MIXER_BLEND_ROUTE			0x1080
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
> +#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
> +#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
> +#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
> +#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
> +#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
> +
> +/* The following numbers are some still unknown magic numbers */
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
> +#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
> +#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
> +#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
> +
> +#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
> +
> +/*
> + * VI channels are not used now, but the support of them may be introduced
> in + * the future.
> + */
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
> +#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
> +#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
> +#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
> +
> +/*
> + * These sun-engines are still unknown now, the EN registers are here only

Typo, should be "sub".

Regards,
Jernej

> to + * be used to disable these sub-engines.
> + */
> +#define SUN8I_MIXER_VSU_EN			0x20000
> +#define SUN8I_MIXER_GSU1_EN			0x30000
> +#define SUN8I_MIXER_GSU2_EN			0x40000
> +#define SUN8I_MIXER_GSU3_EN			0x50000
> +#define SUN8I_MIXER_FCE_EN			0xa0000
> +#define SUN8I_MIXER_BWS_EN			0xa2000
> +#define SUN8I_MIXER_LTI_EN			0xa4000
> +#define SUN8I_MIXER_PEAK_EN			0xa6000
> +#define SUN8I_MIXER_ASE_EN			0xa8000
> +#define SUN8I_MIXER_FCC_EN			0xaa000
> +#define SUN8I_MIXER_DCSC_EN			0xb0000
> +
> +struct sun8i_mixer_cfg {
> +	int		vi_num;
> +	int		ui_num;
> +};
> +
> +struct sun8i_mixer {
> +	struct regmap			*regs;
> +
> +	const struct sun8i_mixer_cfg	*cfg;
> +
> +	struct reset_control		*reset;
> +
> +	struct clk			*bus_clk;
> +	struct clk			*mod_clk;
> +};
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable);
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane);
> +#endif /* _SUN8I_MIXER_H_ */
> --
> 2.12.0
> 
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group. To unsubscribe from this group and stop receiving
> emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [linux-sunxi] [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
@ 2017-03-29 22:33     ` Jernej Škrabec
  0 siblings, 0 replies; 82+ messages in thread
From: Jernej Škrabec @ 2017-03-29 22:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Dne sreda, 29. marec 2017 ob 21:46:08 CEST je Icenowy Zheng napisal(a):
> Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
> with mixers to do graphic processing and feed data to TCON, like the old
> backends and frontends.
> 
> Add support for the mixer on Allwinner V3s SoC; it's the simplest one.
> 
> Currently a lot of functions are still missing -- more investigations
> are needed to gain enough information for them.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/Kconfig       |  10 +
>  drivers/gpu/drm/sun4i/Makefile      |   4 +
>  drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_layer.h |  35 ++++
>  drivers/gpu/drm/sun4i/sun8i_mixer.c | 386
> ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun8i_mixer.h |
> 131 ++++++++++++
>  6 files changed, 722 insertions(+)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
> index 5a8227f37cc4..15557484520d 100644
> --- a/drivers/gpu/drm/sun4i/Kconfig
> +++ b/drivers/gpu/drm/sun4i/Kconfig
> @@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
>  	  original Allwinner Display Engine, which has a backend to
>  	  do some alpha blending and feed graphics to TCON. If M is
>  	  selected the module will be called sun4i-backend.
> +
> +config DRM_SUN4I_SUN8I_MIXER
> +	tristate "Support for Allwinner Display Engine 2.0 Mixer"
> +	depends on DRM_SUN4I
> +	default MACH_SUN8I
> +	help
> +	  Choose this option if you have an Allwinner SoC with the
> +	  Allwinner Display Engine 2.0, which has a mixer to do some
> +	  graphics mixture and feed graphics to TCON, If M is
> +	  selected the module will be called sun8i-mixer.
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 1db1068b9be1..7625c2dad1bb 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
>  sun4i-backend-y += sun4i_layer.o
>  sun4i-backend-y += sun4i_backend.o
> 
> +sun8i-mixer-y += sun8i_layer.o
> +sun8i-mixer-y += sun8i_mixer.o
> +
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
>  obj-$(CONFIG_DRM_SUN4I_BACKEND)	+= sun4i-backend.o
> +obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun6i_drc.o
>  obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c
> b/drivers/gpu/drm/sun4i/sun8i_layer.c new file mode 100644
> index 000000000000..5cc4a7f8a7ae
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
> @@ -0,0 +1,156 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_plane_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "sun4i_crtc.h"
> +#include "sun8i_layer.h"
> +#include "sun8i_mixer.h"
> +#include "sunxi_layer.h"
> +
> +struct sun8i_plane_desc {
> +	       enum drm_plane_type     type;
> +	       const uint32_t          *formats;
> +	       uint32_t                nformats;
> +};
> +
> +static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
> +					    struct drm_plane_state *state)
> +{
> +	return 0;
> +}
> +
> +static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
> +					       struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_layer_enable(mixer, layer->id, false);
> +}
> +
> +static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
> +					      struct drm_plane_state *old_state)
> +{
> +	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
> +	struct sun8i_mixer *mixer = layer->mixer;
> +
> +	sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
> +	sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
> +	sun8i_mixer_layer_enable(mixer, layer->id, true);
> +}
> +
> +static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
> +	.atomic_check	= sun8i_mixer_layer_atomic_check,
> +	.atomic_disable	= sun8i_mixer_layer_atomic_disable,
> +	.atomic_update	= sun8i_mixer_layer_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
> +	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
> +	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
> +	.destroy		= drm_plane_cleanup,
> +	.disable_plane		= drm_atomic_helper_disable_plane,
> +	.reset			= drm_atomic_helper_plane_reset,
> +	.update_plane		= drm_atomic_helper_update_plane,
> +};
> +
> +static const uint32_t sun8i_mixer_layer_formats[] = {
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
> +	{
> +		.type = DRM_PLANE_TYPE_PRIMARY,
> +		.formats = sun8i_mixer_layer_formats,
> +		.nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
> +	},
> +};
> +
> +static struct drm_plane *sun8i_layer_get_plane(void *layer)
> +{
> +	struct sun8i_layer *sun8i_layer = layer;
> +
> +	return &sun8i_layer->plane;
> +}
> +
> +static const struct sunxi_layer_ops layer_ops = {
> +	.get_plane = sun8i_layer_get_plane,
> +};
> +
> +static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
> +						struct sun8i_mixer *mixer,
> +						const struct sun8i_plane_desc *plane)
> +{
> +	struct sun8i_layer *layer;
> +	int ret;
> +
> +	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
> +	if (!layer)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* possible crtcs are set later */
> +	ret = drm_universal_plane_init(drm, &layer->plane, 0,
> +				       &sun8i_mixer_layer_funcs,
> +				       plane->formats, plane->nformats,
> +				       plane->type, NULL);
> +	if (ret) {
> +		dev_err(drm->dev, "Couldn't initialize layer\n");
> +		return ERR_PTR(ret);
> +	}
> +
> +	drm_plane_helper_add(&layer->plane,
> +			     &sun8i_mixer_layer_helper_funcs);
> +	layer->mixer = mixer;
> +
> +	return layer;
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
> +{
> +	struct sun8i_layer **layers;
> +	struct sun8i_mixer *mixer = crtc->mixer;
> +	int i;
> +
> +	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
> +			      sizeof(*layers), GFP_KERNEL);
> +	if (!layers)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
> +		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
> +		struct sun8i_layer *layer;
> +
> +		layer = sun8i_layer_init_one(drm, mixer, plane);
> +		if (IS_ERR(layer)) {
> +			dev_err(drm->dev, "Couldn't initialize %s plane\n",
> +				i ? "overlay" : "primary");
> +			return ERR_CAST(layer);
> +		};
> +
> +		layer->id = i;
> +		layers[i] = layer;
> +	};
> +
> +	/* Assign layer ops to the CRTC */
> +	crtc->layer_ops = &layer_ops;
> +
> +	return (void **)layers;
> +}
> diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h
> b/drivers/gpu/drm/sun4i/sun8i_layer.h new file mode 100644
> index 000000000000..9f145ce842f2
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_layer.h, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + *   Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_LAYER_H_
> +#define _SUN8I_LAYER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sun8i_layer {
> +	struct drm_plane	plane;
> +	struct sun4i_drv	*drv;
> +	struct sun8i_mixer	*mixer;
> +	int			id;
> +};
> +
> +static inline struct sun8i_layer *
> +plane_to_sun8i_layer(struct drm_plane *plane)
> +{
> +	return container_of(plane, struct sun8i_layer, plane);
> +}
> +
> +void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
> +#endif /* _SUN8I_LAYER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> b/drivers/gpu/drm/sun4i/sun8i_mixer.c new file mode 100644
> index 000000000000..1399d1a6c678
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -0,0 +1,386 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Based on sun4i_backend.c, which is:
> + *   Copyright (C) 2015 Free Electrons
> + *   Copyright (C) 2015 NextThing Co
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include <linux/component.h>
> +#include <linux/reset.h>
> +#include <linux/of_device.h>
> +
> +#include "sun4i_drv.h"
> +#include "sun8i_mixer.h"
> +#include "sun8i_layer.h"
> +#include "sunxi_mixer.h"
> +
> +void sun8i_mixer_commit(void *mixer)
> +{
> +	struct sun8i_mixer *sun8i_mixer = mixer;
> +
> +	DRM_DEBUG_DRIVER("Committing changes\n");
> +
> +	regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
> +		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
> +}
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable)
> +{

Layer parameter will be always 0 for now, right?

> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +
> +	DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
> +
> +	if (enable)
> +		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
> +	else
> +		val = 0;
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
> +
> +	/* Set the alpha configuration */
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
> +}
> +EXPORT_SYMBOL(sun8i_mixer_layer_enable);
> +
> +static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
> +					     u32 format, u32 *mode)
> +{
> +	switch (format) {
> +	case DRM_FORMAT_XRGB8888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
> +		break;
> +
> +	case DRM_FORMAT_RGB888:
> +		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int i;
> +
> +	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
> +
> +	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
> +		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
> +				 state->crtc_w, state->crtc_h);
> +		regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating blender size\n");
> +		for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +			regmap_write(mixer->regs,
> +				     SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
> +				     SUN8I_MIXER_SIZE(state->crtc_w,
> +						      state->crtc_h));

Since only one blend channel is used, you only have to set the first for now.

> +		regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +		DRM_DEBUG_DRIVER("Updating channel size\n");
> +		regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
> +			     SUN8I_MIXER_SIZE(state->crtc_w,
> +					      state->crtc_h));
> +	}
> +
> +	/* Set the line width */
> +	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
> +		     fb->pitches[0]);
> +
> +	/* Set height and width */
> +	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
> +			 state->crtc_w, state->crtc_h);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
> +		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
> +
> +	/* Set base coordinates */
> +	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
> +			 state->crtc_x, state->crtc_y);
> +	regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
> +		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
> +
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	bool interlaced = false;
> +	u32 val;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int ret;
> +
> +	if (plane->state->crtc)
> +		interlaced = plane->state->crtc->state->adjusted_mode.flags
> +			& DRM_MODE_FLAG_INTERLACE;
> +
> +	regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
> +			   interlaced ?
> +			   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
> +
> +	DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
> +			 interlaced ? "on" : "off");
> +
> +	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
> +						&val);
> +	if (ret) {
> +		DRM_DEBUG_DRIVER("Invalid format\n");
> +		return ret;
> +	}
> +
> +	regmap_update_bits(mixer->regs,
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
> +			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
> +
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state = plane->state;
> +	struct drm_framebuffer *fb = state->fb;
> +	struct drm_gem_cma_object *gem;
> +	dma_addr_t paddr;
> +	uint32_t paddr_u32;
> +	/* Currently the first UI channel is used */
> +	int chan = mixer->cfg->vi_num;
> +	int bpp;
> +
> +	/* Get the physical address of the buffer in memory */
> +	gem = drm_fb_cma_get_gem_obj(fb, 0);
> +
> +	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
> +
> +	/* Compute the start of the displayed memory */
> +	bpp = fb->format->cpp[0];
> +	paddr = gem->paddr + fb->offsets[0];
> +	paddr += (state->src_x >> 16) * bpp;
> +	paddr += (state->src_y >> 16) * fb->pitches[0];
> +
> +	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
> +
> +	paddr_u32 = (uint32_t) paddr;
> +
> +	regmap_write(mixer->regs,
> +		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
> +		     paddr_u32);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
> +
> +static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
> +	.commit = sun8i_mixer_commit,
> +	.layers_init = sun8i_layers_init,
> +};
> +
> +static struct regmap_config sun8i_mixer_regmap_config = {
> +	.reg_bits	= 32,
> +	.val_bits	= 32,
> +	.reg_stride	= 4,
> +	.max_register	= 0xbffc, /* guessed */
> +};
> +
> +static int sun8i_mixer_bind(struct device *dev, struct device *master,
> +			      void *data)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct drm_device *drm = data;
> +	struct sun4i_drv *drv = drm->dev_private;
> +	struct sun8i_mixer *mixer;
> +	struct resource *res;
> +	void __iomem *regs;
> +	int i, ret;
> +
> +	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
> +	if (!mixer)
> +		return -ENOMEM;
> +	dev_set_drvdata(dev, mixer);
> +	drv->mixer = mixer;
> +	drv->mixer_ops = &sun8i_mixer_mixer_ops;
> +
> +	mixer->cfg = of_device_get_match_data(dev);
> +	if (!mixer->cfg)
> +		return -EINVAL;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	mixer->regs = devm_regmap_init_mmio(dev, regs,
> +					      &sun8i_mixer_regmap_config);
> +	if (IS_ERR(mixer->regs)) {
> +		dev_err(dev, "Couldn't create the mixer regmap\n");
> +		return PTR_ERR(mixer->regs);
> +	}
> +
> +	mixer->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(mixer->reset)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(mixer->reset);
> +	}
> +
> +	ret = reset_control_deassert(mixer->reset);
> +	if (ret) {
> +		dev_err(dev, "Couldn't deassert our reset line\n");
> +		return ret;
> +	}
> +
> +	mixer->bus_clk = devm_clk_get(dev, "bus");
> +	if (IS_ERR(mixer->bus_clk)) {
> +		dev_err(dev, "Couldn't get the mixer bus clock\n");
> +		ret = PTR_ERR(mixer->bus_clk);
> +		goto err_assert_reset;
> +	}
> +	clk_prepare_enable(mixer->bus_clk);
> +
> +	mixer->mod_clk = devm_clk_get(dev, "mod");
> +	if (IS_ERR(mixer->mod_clk)) {
> +		dev_err(dev, "Couldn't get the mixer module clock\n");
> +		ret = PTR_ERR(mixer->mod_clk);
> +		goto err_disable_bus_clk;
> +	}
> +	clk_prepare_enable(mixer->mod_clk);
> +
> +	/* Reset the registers */
> +	for (i = 0x0; i < 0x20000; i += 4)
> +		regmap_write(mixer->regs, i, 0);
> +
> +	/* Enable the mixer */
> +	regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
> +		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
> +
> +	/* Initialize blender */
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
> +		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
> +		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
> +		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
> +		     SUN8I_MIXER_BLEND_MODE_DEF);

Blend mode has to be set only for active layers, so above statement is not 
needed currently.

> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
> +		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
> +
> +	for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
> +		regmap_write(mixer->regs,
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
> +			     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);

Ditto. Setting first layer is enough.

> +
> +	/* Select the first UI channel */
> +	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
> +			 mixer->cfg->vi_num);
> +	regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
> +		     mixer->cfg->vi_num);
> +
> +	return 0;
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +err_disable_bus_clk:
> +	clk_disable_unprepare(mixer->bus_clk);
> +err_assert_reset:
> +	reset_control_assert(mixer->reset);
> +	return ret;
> +}
> +
> +static void sun8i_mixer_unbind(struct device *dev, struct device *master,
> +				 void *data)
> +{
> +	struct sun8i_mixer *mixer = dev_get_drvdata(dev);
> +
> +	clk_disable_unprepare(mixer->mod_clk);
> +	clk_disable_unprepare(mixer->bus_clk);
> +	reset_control_assert(mixer->reset);
> +}
> +
> +static const struct component_ops sun8i_mixer_ops = {
> +	.bind	= sun8i_mixer_bind,
> +	.unbind	= sun8i_mixer_unbind,
> +};
> +
> +static int sun8i_mixer_probe(struct platform_device *pdev)
> +{
> +	return component_add(&pdev->dev, &sun8i_mixer_ops);
> +}
> +
> +static int sun8i_mixer_remove(struct platform_device *pdev)
> +{
> +	component_del(&pdev->dev, &sun8i_mixer_ops);
> +
> +	return 0;
> +}
> +
> +static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
> +	.vi_num = 2,
> +	.ui_num = 1,
> +};
> +
> +static const struct of_device_id sun8i_mixer_of_table[] = {
> +	{
> +		.compatible = "allwinner,sun8i-v3s-de2-mixer",
> +		.data = &sun8i_v3s_mixer_cfg,
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
> +
> +static struct platform_driver sun8i_mixer_platform_driver = {
> +	.probe		= sun8i_mixer_probe,
> +	.remove		= sun8i_mixer_remove,
> +	.driver		= {
> +		.name		= "sun8i-mixer",
> +		.of_match_table	= sun8i_mixer_of_table,
> +	},
> +};
> +module_platform_driver(sun8i_mixer_platform_driver);
> +
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.xyz>");
> +MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> b/drivers/gpu/drm/sun4i/sun8i_mixer.h new file mode 100644
> index 000000000000..7b3b9d747d7d
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -0,0 +1,131 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUN8I_MIXER_H_
> +#define _SUN8I_MIXER_H_
> +
> +#include <linux/clk.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include "sun4i_layer.h"
> +
> +#define SUN8I_MIXER_MAX_CHAN_COUNT		4
> +
> +#define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
> +#define SUN8I_MIXER_COORD(x, y)			((y) << 16 | (x))
> +
> +#define SUN8I_MIXER_GLOBAL_CTL			0x0
> +#define SUN8I_MIXER_GLOBAL_STATUS		0x4
> +#define SUN8I_MIXER_GLOBAL_DBUFF		0x8
> +#define SUN8I_MIXER_GLOBAL_SIZE			0xc
> +
> +#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
> +
> +#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
> +
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x)	(0x1004 + 0x10 * (x) + 0x0)
> +#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x)	(0x1004 + 0x10 * (x) + 0x4)
> +#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x)	(0x1004 + 0x10 * (x) + 0x8)
> +#define SUN8I_MIXER_BLEND_ROUTE			0x1080
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
> +#define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
> +#define SUN8I_MIXER_BLEND_OUTSIZE		0x108c
> +#define SUN8I_MIXER_BLEND_MODE(x)		(0x1090 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_CTL		0x10b0
> +#define SUN8I_MIXER_BLEND_CK_CFG		0x10b4
> +#define SUN8I_MIXER_BLEND_CK_MAX(x)		(0x10c0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
> +#define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
> +
> +/* The following numbers are some still unknown magic numbers */
> +#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF	0xff000000
> +#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
> +#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF	0x0
> +#define SUN8I_MIXER_BLEND_BKCOLOR_DEF		0xff000000
> +#define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
> +#define SUN8I_MIXER_BLEND_CK_CTL_DEF		0x0
> +
> +#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
> +
> +/*
> + * VI channels are not used now, but the support of them may be introduced
> in + * the future.
> + */
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
> +			(0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
> +#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x80)
> +#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch)	(0x2000 + 0x1000 * (ch) + 0x84)
> +#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0x88)
> +
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN		BIT(0)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK	GENMASK(2, 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(11, 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF	(1 << 1)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888	(0 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888	(4 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888	(8 << 8)
> +#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF	(0xff << 24)
> +
> +/*
> + * These sun-engines are still unknown now, the EN registers are here only

Typo, should be "sub".

Regards,
Jernej

> to + * be used to disable these sub-engines.
> + */
> +#define SUN8I_MIXER_VSU_EN			0x20000
> +#define SUN8I_MIXER_GSU1_EN			0x30000
> +#define SUN8I_MIXER_GSU2_EN			0x40000
> +#define SUN8I_MIXER_GSU3_EN			0x50000
> +#define SUN8I_MIXER_FCE_EN			0xa0000
> +#define SUN8I_MIXER_BWS_EN			0xa2000
> +#define SUN8I_MIXER_LTI_EN			0xa4000
> +#define SUN8I_MIXER_PEAK_EN			0xa6000
> +#define SUN8I_MIXER_ASE_EN			0xa8000
> +#define SUN8I_MIXER_FCC_EN			0xaa000
> +#define SUN8I_MIXER_DCSC_EN			0xb0000
> +
> +struct sun8i_mixer_cfg {
> +	int		vi_num;
> +	int		ui_num;
> +};
> +
> +struct sun8i_mixer {
> +	struct regmap			*regs;
> +
> +	const struct sun8i_mixer_cfg	*cfg;
> +
> +	struct reset_control		*reset;
> +
> +	struct clk			*bus_clk;
> +	struct clk			*mod_clk;
> +};
> +
> +void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
> +				int layer, bool enable);
> +int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
> +				     int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
> +				       int layer, struct drm_plane *plane);
> +int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
> +				      int layer, struct drm_plane *plane);
> +#endif /* _SUN8I_MIXER_H_ */
> --
> 2.12.0
> 
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group. To unsubscribe from this group and stop receiving
> emails from it, send an email to linux-sunxi+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-04-03  8:00     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:00 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, linux-clk, devicetree,
	linux-arm-kernel, linux-kernel, dri-devel, linux-sunxi,
	Icenowy Zheng

[-- Attachment #1: Type: text/plain, Size: 2536 bytes --]

On Thu, Mar 30, 2017 at 03:46:05AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
> 
> Add document for it (new compatibles and the new "mixer" part).
> 
> The paragraph of TCON is also refactored, for furtherly add TCONs in
> A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Remove the description of having a BE directly as allwinner,pipeline.
> 
>  .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c00449468..38de5e96f359 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -31,11 +31,11 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> - - clocks: phandles to the clocks feeding the TCON. Three are needed:
> + - clocks: phandles to the clocks feeding the TCON
>     - 'ahb': the interface clocks
> -   - 'tcon-ch0': The clock driving the TCON channel 0
>   - resets: phandles to the reset controllers driving the encoder
>     - "lcd": the reset line for the TCON channel 0
>  
> @@ -52,7 +52,12 @@ Required properties:
>    second the block connected to the TCON channel 1 (usually the TV
>    encoder)
>  
> -On SoCs other than the A33, there is one more clock required:
> +On TCONs that have a channel 0 (currently all TCONs supported), there
> +is one more clock required:
> +   - 'tcon-ch0': The clock driving the TCON channel 0
> +

Why did you change that if they all have a channel 0?

> +On TCONs that have a channel 1 (currently all TCONs except the ones in
> +A33 and V3s), there is one more clock required:
>     - 'tcon-ch1': The clock driving the TCON channel 1

And that can be added too just by saying "On SoCs other than the A33
and V3".

Looks good otherwise, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-04-03  8:00     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:00 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

[-- Attachment #1: Type: text/plain, Size: 2512 bytes --]

On Thu, Mar 30, 2017 at 03:46:05AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> 
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
> 
> Add document for it (new compatibles and the new "mixer" part).
> 
> The paragraph of TCON is also refactored, for furtherly add TCONs in
> A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
> 
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> ---
> Changes in v3:
> - Remove the description of having a BE directly as allwinner,pipeline.
> 
>  .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c00449468..38de5e96f359 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -31,11 +31,11 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> - - clocks: phandles to the clocks feeding the TCON. Three are needed:
> + - clocks: phandles to the clocks feeding the TCON
>     - 'ahb': the interface clocks
> -   - 'tcon-ch0': The clock driving the TCON channel 0
>   - resets: phandles to the reset controllers driving the encoder
>     - "lcd": the reset line for the TCON channel 0
>  
> @@ -52,7 +52,12 @@ Required properties:
>    second the block connected to the TCON channel 1 (usually the TV
>    encoder)
>  
> -On SoCs other than the A33, there is one more clock required:
> +On TCONs that have a channel 0 (currently all TCONs supported), there
> +is one more clock required:
> +   - 'tcon-ch0': The clock driving the TCON channel 0
> +

Why did you change that if they all have a channel 0?

> +On TCONs that have a channel 1 (currently all TCONs except the ones in
> +A33 and V3s), there is one more clock required:
>     - 'tcon-ch1': The clock driving the TCON channel 1

And that can be added too just by saying "On SoCs other than the A33
and V3".

Looks good otherwise, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

* Re: [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-04-03  8:00     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:00 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Chen-Yu Tsai, Rob Herring, Icenowy Zheng, linux-clk,
	linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2536 bytes --]

On Thu, Mar 30, 2017 at 03:46:05AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
> 
> Add document for it (new compatibles and the new "mixer" part).
> 
> The paragraph of TCON is also refactored, for furtherly add TCONs in
> A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Remove the description of having a BE directly as allwinner,pipeline.
> 
>  .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c00449468..38de5e96f359 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -31,11 +31,11 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> - - clocks: phandles to the clocks feeding the TCON. Three are needed:
> + - clocks: phandles to the clocks feeding the TCON
>     - 'ahb': the interface clocks
> -   - 'tcon-ch0': The clock driving the TCON channel 0
>   - resets: phandles to the reset controllers driving the encoder
>     - "lcd": the reset line for the TCON channel 0
>  
> @@ -52,7 +52,12 @@ Required properties:
>    second the block connected to the TCON channel 1 (usually the TV
>    encoder)
>  
> -On SoCs other than the A33, there is one more clock required:
> +On TCONs that have a channel 0 (currently all TCONs supported), there
> +is one more clock required:
> +   - 'tcon-ch0': The clock driving the TCON channel 0
> +

Why did you change that if they all have a channel 0?

> +On TCONs that have a channel 1 (currently all TCONs except the ones in
> +A33 and V3s), there is one more clock required:
>     - 'tcon-ch1': The clock driving the TCON channel 1

And that can be added too just by saying "On SoCs other than the A33
and V3".

Looks good otherwise, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 82+ messages in thread

* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
@ 2017-04-03  8:00     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 30, 2017 at 03:46:05AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner V3s SoC have a display engine which have a different pipeline
> with older SoCs.
> 
> Add document for it (new compatibles and the new "mixer" part).
> 
> The paragraph of TCON is also refactored, for furtherly add TCONs in
> A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Remove the description of having a BE directly as allwinner,pipeline.
> 
>  .../bindings/display/sunxi/sun4i-drm.txt           | 37 +++++++++++++++++++---
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index b82c00449468..38de5e96f359 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -31,11 +31,11 @@ Required properties:
>     * allwinner,sun6i-a31-tcon
>     * allwinner,sun6i-a31s-tcon
>     * allwinner,sun8i-a33-tcon
> +   * allwinner,sun8i-v3s-tcon
>   - reg: base address and size of memory-mapped region
>   - interrupts: interrupt associated to this IP
> - - clocks: phandles to the clocks feeding the TCON. Three are needed:
> + - clocks: phandles to the clocks feeding the TCON
>     - 'ahb': the interface clocks
> -   - 'tcon-ch0': The clock driving the TCON channel 0
>   - resets: phandles to the reset controllers driving the encoder
>     - "lcd": the reset line for the TCON channel 0
>  
> @@ -52,7 +52,12 @@ Required properties:
>    second the block connected to the TCON channel 1 (usually the TV
>    encoder)
>  
> -On SoCs other than the A33, there is one more clock required:
> +On TCONs that have a channel 0 (currently all TCONs supported), there
> +is one more clock required:
> +   - 'tcon-ch0': The clock driving the TCON channel 0
> +

Why did you change that if they all have a channel 0?

> +On TCONs that have a channel 1 (currently all TCONs except the ones in
> +A33 and V3s), there is one more clock required:
>     - 'tcon-ch1': The clock driving the TCON channel 1

And that can be added too just by saying "On SoCs other than the A33
and V3".

Looks good otherwise, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170403/90e9c978/attachment.sig>

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03  8:14     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:14 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, linux-clk, devicetree,
	linux-arm-kernel, linux-kernel, dri-devel, linux-sunxi

[-- Attachment #1: Type: text/plain, Size: 3582 bytes --]

Hi,

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;

I think the logic should be reversed here, the CRTC shouldn't care
(much) about the layers at all.

We should modify sun4i_crtc_init to get the argument it needs (primary
and cursor planes for example) through its parameters, and have the
caller (which iirc is sun4i_drv) call it with the right parameters
depending on whether you're using DE or DE2.

If we're doing that, I don't think we even need the pointer to the
array of layers in struct sun4i_crtc, which will make it easier to
deal with.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03  8:14     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:14 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

[-- Attachment #1: Type: text/plain, Size: 3509 bytes --]

Hi,

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;

I think the logic should be reversed here, the CRTC shouldn't care
(much) about the layers at all.

We should modify sun4i_crtc_init to get the argument it needs (primary
and cursor planes for example) through its parameters, and have the
caller (which iirc is sun4i_drv) call it with the right parameters
depending on whether you're using DE or DE2.

If we're doing that, I don't think we even need the pointer to the
array of layers in struct sun4i_crtc, which will make it easier to
deal with.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03  8:14     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:14 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Chen-Yu Tsai, Rob Herring, linux-clk, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 3582 bytes --]

Hi,

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;

I think the logic should be reversed here, the CRTC shouldn't care
(much) about the layers at all.

We should modify sun4i_crtc_init to get the argument it needs (primary
and cursor planes for example) through its parameters, and have the
caller (which iirc is sun4i_drv) call it with the right parameters
depending on whether you're using DE or DE2.

If we're doing that, I don't think we even need the pointer to the
array of layers in struct sun4i_crtc, which will make it easier to
deal with.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 82+ messages in thread

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03  8:14     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;

I think the logic should be reversed here, the CRTC shouldn't care
(much) about the layers at all.

We should modify sun4i_crtc_init to get the argument it needs (primary
and cursor planes for example) through its parameters, and have the
caller (which iirc is sun4i_drv) call it with the right parameters
depending on whether you're using DE or DE2.

If we're doing that, I don't think we even need the pointer to the
array of layers in struct sun4i_crtc, which will make it easier to
deal with.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170403/045d7d47/attachment.sig>

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

* Re: [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-04-03  8:24     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:24 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec, linux-clk, devicetree,
	linux-arm-kernel, linux-kernel, dri-devel, linux-sunxi

[-- Attachment #1: Type: text/plain, Size: 3766 bytes --]

Hi,

That's much better thanks, but I have a bunch of (minor) comments.

On Thu, Mar 30, 2017 at 03:46:07AM +0800, Icenowy Zheng wrote:
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 33854ee7f636..938dfe7188ff 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -25,11 +25,10 @@
>  
>  #include <video/videomode.h>
>  
> -#include "sun4i_backend.h"
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
> -#include "sun4i_layer.h"
>  #include "sunxi_layer.h"
> +#include "sunxi_mixer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>  	DRM_DEBUG_DRIVER("Committing plane changes\n");
>  
> -	sun4i_backend_commit(scrtc->backend);
> +	scrtc->mixer_ops->commit(scrtc->mixer);

The caller would also have to care about whether that pointer is NULL
or not. This is not really a big deal in the commit case that I expect
to always be filled, but it might be for the color correction.

How about defining some inline functions that would check the
mixer_ops pointer and return if it's NULL?

>  	if (event) {
>  		crtc->state->event = NULL;
> @@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
>  	.disable_vblank		= sun4i_crtc_disable_vblank,
>  };
>  
> -struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
> -				   struct sun4i_backend *backend,
> +struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
> +				   const struct sunxi_mixer_ops *mixer_ops,
>  				   struct sun4i_tcon *tcon)
>  {
>  	struct sun4i_crtc *scrtc;
> @@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
>  	if (!scrtc)
>  		return ERR_PTR(-ENOMEM);
> -	scrtc->backend = backend;
> +	scrtc->mixer = mixer;
> +	scrtc->mixer_ops = mixer_ops;
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
> +	scrtc->layers = mixer_ops->layers_init(drm, scrtc);

I don't really see why we need the mixer and ops in the CRTC, we
already have it in sun4i_drv, don't we? Can't we just use that
instead?

That would allow just like in the previous patch to loosen the
relationship between the CRTC and what's before it, which will make
our life easier down the road.

> diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> new file mode 100644
> index 000000000000..11bdd20269ef
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUNXI_MIXER_H_
> +#define _SUNXI_MIXER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sunxi_mixer_ops {
> +	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
> +	void (*apply_color_correction)(void *mixer);
> +	void (*disable_color_correction)(void *mixer);
> +	void (*commit)(void *mixer);
> +};
> +
> +#endif /* _SUNXI_MIXER_H_ */

I don't really like the "mixer" name here, and backend doesn't seem
appropriate either.

What about "engine"? It sounds more like it covers both cases.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* Re: [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-04-03  8:24     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:24 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw

[-- Attachment #1: Type: text/plain, Size: 3786 bytes --]

Hi,

That's much better thanks, but I have a bunch of (minor) comments.

On Thu, Mar 30, 2017 at 03:46:07AM +0800, Icenowy Zheng wrote:
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 33854ee7f636..938dfe7188ff 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -25,11 +25,10 @@
>  
>  #include <video/videomode.h>
>  
> -#include "sun4i_backend.h"
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
> -#include "sun4i_layer.h"
>  #include "sunxi_layer.h"
> +#include "sunxi_mixer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>  	DRM_DEBUG_DRIVER("Committing plane changes\n");
>  
> -	sun4i_backend_commit(scrtc->backend);
> +	scrtc->mixer_ops->commit(scrtc->mixer);

The caller would also have to care about whether that pointer is NULL
or not. This is not really a big deal in the commit case that I expect
to always be filled, but it might be for the color correction.

How about defining some inline functions that would check the
mixer_ops pointer and return if it's NULL?

>  	if (event) {
>  		crtc->state->event = NULL;
> @@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
>  	.disable_vblank		= sun4i_crtc_disable_vblank,
>  };
>  
> -struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
> -				   struct sun4i_backend *backend,
> +struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
> +				   const struct sunxi_mixer_ops *mixer_ops,
>  				   struct sun4i_tcon *tcon)
>  {
>  	struct sun4i_crtc *scrtc;
> @@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
>  	if (!scrtc)
>  		return ERR_PTR(-ENOMEM);
> -	scrtc->backend = backend;
> +	scrtc->mixer = mixer;
> +	scrtc->mixer_ops = mixer_ops;
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
> +	scrtc->layers = mixer_ops->layers_init(drm, scrtc);

I don't really see why we need the mixer and ops in the CRTC, we
already have it in sun4i_drv, don't we? Can't we just use that
instead?

That would allow just like in the previous patch to loosen the
relationship between the CRTC and what's before it, which will make
our life easier down the road.

> diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> new file mode 100644
> index 000000000000..11bdd20269ef
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUNXI_MIXER_H_
> +#define _SUNXI_MIXER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sunxi_mixer_ops {
> +	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
> +	void (*apply_color_correction)(void *mixer);
> +	void (*disable_color_correction)(void *mixer);
> +	void (*commit)(void *mixer);
> +};
> +
> +#endif /* _SUNXI_MIXER_H_ */

I don't really like the "mixer" name here, and backend doesn't seem
appropriate either.

What about "engine"? It sounds more like it covers both cases.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
@ 2017-04-03  8:24     ` Maxime Ripard
  0 siblings, 0 replies; 82+ messages in thread
From: Maxime Ripard @ 2017-04-03  8:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

That's much better thanks, but I have a bunch of (minor) comments.

On Thu, Mar 30, 2017 at 03:46:07AM +0800, Icenowy Zheng wrote:
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 33854ee7f636..938dfe7188ff 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -25,11 +25,10 @@
>  
>  #include <video/videomode.h>
>  
> -#include "sun4i_backend.h"
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
> -#include "sun4i_layer.h"
>  #include "sunxi_layer.h"
> +#include "sunxi_mixer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
>  
>  	DRM_DEBUG_DRIVER("Committing plane changes\n");
>  
> -	sun4i_backend_commit(scrtc->backend);
> +	scrtc->mixer_ops->commit(scrtc->mixer);

The caller would also have to care about whether that pointer is NULL
or not. This is not really a big deal in the commit case that I expect
to always be filled, but it might be for the color correction.

How about defining some inline functions that would check the
mixer_ops pointer and return if it's NULL?

>  	if (event) {
>  		crtc->state->event = NULL;
> @@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
>  	.disable_vblank		= sun4i_crtc_disable_vblank,
>  };
>  
> -struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
> -				   struct sun4i_backend *backend,
> +struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
> +				   const struct sunxi_mixer_ops *mixer_ops,
>  				   struct sun4i_tcon *tcon)
>  {
>  	struct sun4i_crtc *scrtc;
> @@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
>  	if (!scrtc)
>  		return ERR_PTR(-ENOMEM);
> -	scrtc->backend = backend;
> +	scrtc->mixer = mixer;
> +	scrtc->mixer_ops = mixer_ops;
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
> +	scrtc->layers = mixer_ops->layers_init(drm, scrtc);

I don't really see why we need the mixer and ops in the CRTC, we
already have it in sun4i_drv, don't we? Can't we just use that
instead?

That would allow just like in the previous patch to loosen the
relationship between the CRTC and what's before it, which will make
our life easier down the road.

> diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> new file mode 100644
> index 000000000000..11bdd20269ef
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUNXI_MIXER_H_
> +#define _SUNXI_MIXER_H_
> +
> +struct sun4i_crtc;
> +
> +struct sunxi_mixer_ops {
> +	void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
> +	void (*apply_color_correction)(void *mixer);
> +	void (*disable_color_correction)(void *mixer);
> +	void (*commit)(void *mixer);
> +};
> +
> +#endif /* _SUNXI_MIXER_H_ */

I don't really like the "mixer" name here, and backend doesn't seem
appropriate either.

What about "engine"? It sounds more like it covers both cases.

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170403/dfb6220d/attachment-0001.sig>

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
  2017-04-03  8:14     ` Maxime Ripard
  (?)
@ 2017-04-03 10:51       ` Chen-Yu Tsai
  -1 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-03 10:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Icenowy Zheng, Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi

On Mon, Apr 3, 2017 at 4:14 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       scrtc->tcon = tcon;
>>
>>       /* Create our layers */
>> -     scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +     scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>       if (IS_ERR(scrtc->layers)) {
>>               dev_err(drm->dev, "Couldn't create the planes\n");
>>               return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>       /* find primary and cursor planes for drm_crtc_init_with_planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             switch (layer->plane.type) {
>> +             switch (plane->type) {
>>               case DRM_PLANE_TYPE_PRIMARY:
>> -                     primary = &layer->plane;
>> +                     primary = plane;
>>                       break;
>>               case DRM_PLANE_TYPE_CURSOR:
>> -                     cursor = &layer->plane;
>> +                     cursor = plane;
>>                       break;
>>               default:
>>                       break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       /* Set possible_crtcs to this crtc for overlay planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>>               uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -                     layer->plane.possible_crtcs = possible_crtcs;
>> +             if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +                     plane->possible_crtcs = possible_crtcs;
>
> I think the logic should be reversed here, the CRTC shouldn't care
> (much) about the layers at all.

Correct. It shouldn't. However since the layers are tied to a specific
crtc, they get created as part of the crtc init sequence.

> We should modify sun4i_crtc_init to get the argument it needs (primary
> and cursor planes for example) through its parameters, and have the
> caller (which iirc is sun4i_drv) call it with the right parameters

The caller is (now) sun4i_crtc_init.

> depending on whether you're using DE or DE2.

Ack.

>
> If we're doing that, I don't think we even need the pointer to the
> array of layers in struct sun4i_crtc, which will make it easier to
> deal with.

Ack.

ChenYu

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03 10:51       ` Chen-Yu Tsai
  0 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-03 10:51 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Icenowy Zheng, Rob Herring, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk, devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi

On Mon, Apr 3, 2017 at 4:14 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi,
>
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       scrtc->tcon = tcon;
>>
>>       /* Create our layers */
>> -     scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +     scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>       if (IS_ERR(scrtc->layers)) {
>>               dev_err(drm->dev, "Couldn't create the planes\n");
>>               return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>       /* find primary and cursor planes for drm_crtc_init_with_planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             switch (layer->plane.type) {
>> +             switch (plane->type) {
>>               case DRM_PLANE_TYPE_PRIMARY:
>> -                     primary = &layer->plane;
>> +                     primary = plane;
>>                       break;
>>               case DRM_PLANE_TYPE_CURSOR:
>> -                     cursor = &layer->plane;
>> +                     cursor = plane;
>>                       break;
>>               default:
>>                       break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       /* Set possible_crtcs to this crtc for overlay planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>>               uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -                     layer->plane.possible_crtcs = possible_crtcs;
>> +             if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +                     plane->possible_crtcs = possible_crtcs;
>
> I think the logic should be reversed here, the CRTC shouldn't care
> (much) about the layers at all.

Correct. It shouldn't. However since the layers are tied to a specific
crtc, they get created as part of the crtc init sequence.

> We should modify sun4i_crtc_init to get the argument it needs (primary
> and cursor planes for example) through its parameters, and have the
> caller (which iirc is sun4i_drv) call it with the right parameters

The caller is (now) sun4i_crtc_init.

> depending on whether you're using DE or DE2.

Ack.

>
> If we're doing that, I don't think we even need the pointer to the
> array of layers in struct sun4i_crtc, which will make it easier to
> deal with.

Ack.

ChenYu

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-03 10:51       ` Chen-Yu Tsai
  0 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-03 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 3, 2017 at 4:14 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       scrtc->tcon = tcon;
>>
>>       /* Create our layers */
>> -     scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +     scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>       if (IS_ERR(scrtc->layers)) {
>>               dev_err(drm->dev, "Couldn't create the planes\n");
>>               return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>       /* find primary and cursor planes for drm_crtc_init_with_planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             switch (layer->plane.type) {
>> +             switch (plane->type) {
>>               case DRM_PLANE_TYPE_PRIMARY:
>> -                     primary = &layer->plane;
>> +                     primary = plane;
>>                       break;
>>               case DRM_PLANE_TYPE_CURSOR:
>> -                     cursor = &layer->plane;
>> +                     cursor = plane;
>>                       break;
>>               default:
>>                       break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>       /* Set possible_crtcs to this crtc for overlay planes */
>>       for (i = 0; scrtc->layers[i]; i++) {
>>               uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -             struct sun4i_layer *layer = scrtc->layers[i];
>> +             void *layer = scrtc->layers[i];
>> +             struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -             if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -                     layer->plane.possible_crtcs = possible_crtcs;
>> +             if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +                     plane->possible_crtcs = possible_crtcs;
>
> I think the logic should be reversed here, the CRTC shouldn't care
> (much) about the layers at all.

Correct. It shouldn't. However since the layers are tied to a specific
crtc, they get created as part of the crtc init sequence.

> We should modify sun4i_crtc_init to get the argument it needs (primary
> and cursor planes for example) through its parameters, and have the
> caller (which iirc is sun4i_drv) call it with the right parameters

The caller is (now) sun4i_crtc_init.

> depending on whether you're using DE or DE2.

Ack.

>
> If we're doing that, I don't think we even need the pointer to the
> array of layers in struct sun4i_crtc, which will make it easier to
> deal with.

Ack.

ChenYu

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

* Re: [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 15:33     ` Rob Herring
  0 siblings, 0 replies; 82+ messages in thread
From: Rob Herring @ 2017-04-03 15:33 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, linux-clk,
	devicetree, linux-arm-kernel, linux-kernel, dri-devel,
	linux-sunxi, Icenowy Zheng

On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner "Display Engine 2.0" contains some clock controls in it.
> 
> In order to add them as clock drivers, we need a device tree binding.
> Add the binding here.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

Why? You waste virtual memory space making this bigger than it needs to 
be. Not an issue so much for 64-bit.

> 
>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> new file mode 100644
> index 000000000000..34cf79c05f13
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> @@ -0,0 +1,31 @@
> +Allwinner Display Engine 2.0 Clock Control Binding
> +--------------------------------------------------
> +
> +Required properties :
> +- compatible: must contain one of the following compatibles:
> +		- "allwinner,sun8i-a83t-de2-clk"
> +		- "allwinner,sun50i-a64-de2-clk"
> +		- "allwinner,sun50i-h5-de2-clk"
> +
> +- reg: Must contain the registers base address and length
> +- clocks: phandle to the clocks feeding the display engine subsystem.
> +	  Three are needed:
> +  - "mod": the display engine module clock
> +  - "bus": the bus clock for the whole display engine subsystem
> +- clock-names: Must contain the clock names described just above
> +- resets: phandle to the reset control for the display engine subsystem.
> +- #clock-cells : must contain 1
> +- #reset-cells : must contain 1
> +
> +Example:
> +de2_clocks: clock@01000000 {

Drop the leading 0s. dtc in linux-next will now warn on this with W=1 
compile. Looks like sunxi has a lot of them. Please fix so we don't keep 
repeating this same copy-n-paste.

> +	compatible = "allwinner,sun50i-a64-de2-clk";
> +	reg = <0x01000000 0x100000>;
> +	clocks = <&ccu CLK_DE>,
> +		 <&ccu CLK_BUS_DE>;
> +	clock-names = "mod",
> +		      "bus";
> +	resets = <&ccu RST_BUS_DE>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> -- 
> 2.12.0
> 

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

* Re: [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 15:33     ` Rob Herring
  0 siblings, 0 replies; 82+ messages in thread
From: Rob Herring @ 2017-04-03 15:33 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng

On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> 
> Allwinner "Display Engine 2.0" contains some clock controls in it.
> 
> In order to add them as clock drivers, we need a device tree binding.
> Add the binding here.
> 
> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
> ---
> Changes in v3:
> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

Why? You waste virtual memory space making this bigger than it needs to 
be. Not an issue so much for 64-bit.

> 
>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> new file mode 100644
> index 000000000000..34cf79c05f13
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> @@ -0,0 +1,31 @@
> +Allwinner Display Engine 2.0 Clock Control Binding
> +--------------------------------------------------
> +
> +Required properties :
> +- compatible: must contain one of the following compatibles:
> +		- "allwinner,sun8i-a83t-de2-clk"
> +		- "allwinner,sun50i-a64-de2-clk"
> +		- "allwinner,sun50i-h5-de2-clk"
> +
> +- reg: Must contain the registers base address and length
> +- clocks: phandle to the clocks feeding the display engine subsystem.
> +	  Three are needed:
> +  - "mod": the display engine module clock
> +  - "bus": the bus clock for the whole display engine subsystem
> +- clock-names: Must contain the clock names described just above
> +- resets: phandle to the reset control for the display engine subsystem.
> +- #clock-cells : must contain 1
> +- #reset-cells : must contain 1
> +
> +Example:
> +de2_clocks: clock@01000000 {

Drop the leading 0s. dtc in linux-next will now warn on this with W=1 
compile. Looks like sunxi has a lot of them. Please fix so we don't keep 
repeating this same copy-n-paste.

> +	compatible = "allwinner,sun50i-a64-de2-clk";
> +	reg = <0x01000000 0x100000>;
> +	clocks = <&ccu CLK_DE>,
> +		 <&ccu CLK_BUS_DE>;
> +	clock-names = "mod",
> +		      "bus";
> +	resets = <&ccu RST_BUS_DE>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> -- 
> 2.12.0
> 

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

* Re: [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 15:33     ` Rob Herring
  0 siblings, 0 replies; 82+ messages in thread
From: Rob Herring @ 2017-04-03 15:33 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Chen-Yu Tsai, Icenowy Zheng, Maxime Ripard, linux-clk,
	linux-arm-kernel

On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner "Display Engine 2.0" contains some clock controls in it.
> 
> In order to add them as clock drivers, we need a device tree binding.
> Add the binding here.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

Why? You waste virtual memory space making this bigger than it needs to 
be. Not an issue so much for 64-bit.

> 
>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> new file mode 100644
> index 000000000000..34cf79c05f13
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> @@ -0,0 +1,31 @@
> +Allwinner Display Engine 2.0 Clock Control Binding
> +--------------------------------------------------
> +
> +Required properties :
> +- compatible: must contain one of the following compatibles:
> +		- "allwinner,sun8i-a83t-de2-clk"
> +		- "allwinner,sun50i-a64-de2-clk"
> +		- "allwinner,sun50i-h5-de2-clk"
> +
> +- reg: Must contain the registers base address and length
> +- clocks: phandle to the clocks feeding the display engine subsystem.
> +	  Three are needed:
> +  - "mod": the display engine module clock
> +  - "bus": the bus clock for the whole display engine subsystem
> +- clock-names: Must contain the clock names described just above
> +- resets: phandle to the reset control for the display engine subsystem.
> +- #clock-cells : must contain 1
> +- #reset-cells : must contain 1
> +
> +Example:
> +de2_clocks: clock@01000000 {

Drop the leading 0s. dtc in linux-next will now warn on this with W=1 
compile. Looks like sunxi has a lot of them. Please fix so we don't keep 
repeating this same copy-n-paste.

> +	compatible = "allwinner,sun50i-a64-de2-clk";
> +	reg = <0x01000000 0x100000>;
> +	clocks = <&ccu CLK_DE>,
> +		 <&ccu CLK_BUS_DE>;
> +	clock-names = "mod",
> +		      "bus";
> +	resets = <&ccu RST_BUS_DE>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> -- 
> 2.12.0
> 

_______________________________________________
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] 82+ messages in thread

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 15:33     ` Rob Herring
  0 siblings, 0 replies; 82+ messages in thread
From: Rob Herring @ 2017-04-03 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
> From: Icenowy Zheng <icenowy@aosc.xyz>
> 
> Allwinner "Display Engine 2.0" contains some clock controls in it.
> 
> In order to add them as clock drivers, we need a device tree binding.
> Add the binding here.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes in v3:
> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.

Why? You waste virtual memory space making this bigger than it needs to 
be. Not an issue so much for 64-bit.

> 
>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
> 
> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> new file mode 100644
> index 000000000000..34cf79c05f13
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
> @@ -0,0 +1,31 @@
> +Allwinner Display Engine 2.0 Clock Control Binding
> +--------------------------------------------------
> +
> +Required properties :
> +- compatible: must contain one of the following compatibles:
> +		- "allwinner,sun8i-a83t-de2-clk"
> +		- "allwinner,sun50i-a64-de2-clk"
> +		- "allwinner,sun50i-h5-de2-clk"
> +
> +- reg: Must contain the registers base address and length
> +- clocks: phandle to the clocks feeding the display engine subsystem.
> +	  Three are needed:
> +  - "mod": the display engine module clock
> +  - "bus": the bus clock for the whole display engine subsystem
> +- clock-names: Must contain the clock names described just above
> +- resets: phandle to the reset control for the display engine subsystem.
> +- #clock-cells : must contain 1
> +- #reset-cells : must contain 1
> +
> +Example:
> +de2_clocks: clock at 01000000 {

Drop the leading 0s. dtc in linux-next will now warn on this with W=1 
compile. Looks like sunxi has a lot of them. Please fix so we don't keep 
repeating this same copy-n-paste.

> +	compatible = "allwinner,sun50i-a64-de2-clk";
> +	reg = <0x01000000 0x100000>;
> +	clocks = <&ccu CLK_DE>,
> +		 <&ccu CLK_BUS_DE>;
> +	clock-names = "mod",
> +		      "bus";
> +	resets = <&ccu RST_BUS_DE>;
> +	#clock-cells = <1>;
> +	#reset-cells = <1>;
> +};
> -- 
> 2.12.0
> 

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

* Re: [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
  2017-04-03 15:33     ` Rob Herring
  (?)
@ 2017-04-03 16:18       ` Icenowy Zheng
  -1 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-03 16:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng



在 2017年04月03日 23:33, Rob Herring 写道:
> On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
>> From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>>
>> Allwinner "Display Engine 2.0" contains some clock controls in it.
>>
>> In order to add them as clock drivers, we need a device tree binding.
>> Add the binding here.
>>
>> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>> ---
>> Changes in v3:
>> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.
>
> Why? You waste virtual memory space making this bigger than it needs to
> be. Not an issue so much for 64-bit.
>
>>
>>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
>> new file mode 100644
>> index 000000000000..34cf79c05f13
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
>> @@ -0,0 +1,31 @@
>> +Allwinner Display Engine 2.0 Clock Control Binding
>> +--------------------------------------------------
>> +
>> +Required properties :
>> +- compatible: must contain one of the following compatibles:
>> +		- "allwinner,sun8i-a83t-de2-clk"
>> +		- "allwinner,sun50i-a64-de2-clk"
>> +		- "allwinner,sun50i-h5-de2-clk"
>> +
>> +- reg: Must contain the registers base address and length
>> +- clocks: phandle to the clocks feeding the display engine subsystem.
>> +	  Three are needed:
>> +  - "mod": the display engine module clock
>> +  - "bus": the bus clock for the whole display engine subsystem
>> +- clock-names: Must contain the clock names described just above
>> +- resets: phandle to the reset control for the display engine subsystem.
>> +- #clock-cells : must contain 1
>> +- #reset-cells : must contain 1
>> +
>> +Example:
>> +de2_clocks: clock@01000000 {
>
> Drop the leading 0s. dtc in linux-next will now warn on this with W=1
> compile. Looks like sunxi has a lot of them. Please fix so we don't keep
> repeating this same copy-n-paste.

Thanks ;-)

I will try to kill them all ;-)

>
>> +	compatible = "allwinner,sun50i-a64-de2-clk";
>> +	reg = <0x01000000 0x100000>;
>> +	clocks = <&ccu CLK_DE>,
>> +		 <&ccu CLK_BUS_DE>;
>> +	clock-names = "mod",
>> +		      "bus";
>> +	resets = <&ccu RST_BUS_DE>;
>> +	#clock-cells = <1>;
>> +	#reset-cells = <1>;
>> +};
>> --
>> 2.12.0
>>

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

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

* Re: [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 16:18       ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-03 16:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Chen-Yu Tsai, Icenowy Zheng, Maxime Ripard, linux-clk,
	linux-arm-kernel

CgrlnKggMjAxN+W5tDA05pyIMDPml6UgMjM6MzMsIFJvYiBIZXJyaW5nIOWGmemBkzoKPiBPbiBU
aHUsIE1hciAzMCwgMjAxNyBhdCAwMzo0NjowM0FNICswODAwLCBJY2Vub3d5IFpoZW5nIHdyb3Rl
Ogo+PiBGcm9tOiBJY2Vub3d5IFpoZW5nIDxpY2Vub3d5QGFvc2MueHl6Pgo+Pgo+PiBBbGx3aW5u
ZXIgIkRpc3BsYXkgRW5naW5lIDIuMCIgY29udGFpbnMgc29tZSBjbG9jayBjb250cm9scyBpbiBp
dC4KPj4KPj4gSW4gb3JkZXIgdG8gYWRkIHRoZW0gYXMgY2xvY2sgZHJpdmVycywgd2UgbmVlZCBh
IGRldmljZSB0cmVlIGJpbmRpbmcuCj4+IEFkZCB0aGUgYmluZGluZyBoZXJlLgo+Pgo+PiBTaWdu
ZWQtb2ZmLWJ5OiBJY2Vub3d5IFpoZW5nIDxpY2Vub3d5QGFvc2MueHl6Pgo+PiAtLS0KPj4gQ2hh
bmdlcyBpbiB2MzoKPj4gLSBGaWxsIHRoZSBhZGRyZXNzIHNwYWNlIGxlbmd0aCBvZiBERTIgQ0NV
IHRvIDB4MTAwMDAwLCBqdXN0IHJlYWNoIHRoZSBzdGFydCBvZiBtaXhlcjAuCj4KPiBXaHk/IFlv
dSB3YXN0ZSB2aXJ0dWFsIG1lbW9yeSBzcGFjZSBtYWtpbmcgdGhpcyBiaWdnZXIgdGhhbiBpdCBu
ZWVkcyB0bwo+IGJlLiBOb3QgYW4gaXNzdWUgc28gbXVjaCBmb3IgNjQtYml0Lgo+Cj4+Cj4+ICAu
Li4vZGV2aWNldHJlZS9iaW5kaW5ncy9jbG9jay9zdW44aS1kZTIudHh0ICAgICAgICB8IDMxICsr
KysrKysrKysrKysrKysrKysrKysKPj4gIDEgZmlsZSBjaGFuZ2VkLCAzMSBpbnNlcnRpb25zKCsp
Cj4+ICBjcmVhdGUgbW9kZSAxMDA2NDQgRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz
L2Nsb2NrL3N1bjhpLWRlMi50eHQKPj4KPj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2
aWNldHJlZS9iaW5kaW5ncy9jbG9jay9zdW44aS1kZTIudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZp
Y2V0cmVlL2JpbmRpbmdzL2Nsb2NrL3N1bjhpLWRlMi50eHQKPj4gbmV3IGZpbGUgbW9kZSAxMDA2
NDQKPj4gaW5kZXggMDAwMDAwMDAwMDAwLi4zNGNmNzljMDVmMTMKPj4gLS0tIC9kZXYvbnVsbAo+
PiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvY2xvY2svc3VuOGktZGUy
LnR4dAo+PiBAQCAtMCwwICsxLDMxIEBACj4+ICtBbGx3aW5uZXIgRGlzcGxheSBFbmdpbmUgMi4w
IENsb2NrIENvbnRyb2wgQmluZGluZwo+PiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4gKwo+PiArUmVxdWlyZWQgcHJvcGVydGllcyA6Cj4+ICst
IGNvbXBhdGlibGU6IG11c3QgY29udGFpbiBvbmUgb2YgdGhlIGZvbGxvd2luZyBjb21wYXRpYmxl
czoKPj4gKwkJLSAiYWxsd2lubmVyLHN1bjhpLWE4M3QtZGUyLWNsayIKPj4gKwkJLSAiYWxsd2lu
bmVyLHN1bjUwaS1hNjQtZGUyLWNsayIKPj4gKwkJLSAiYWxsd2lubmVyLHN1bjUwaS1oNS1kZTIt
Y2xrIgo+PiArCj4+ICstIHJlZzogTXVzdCBjb250YWluIHRoZSByZWdpc3RlcnMgYmFzZSBhZGRy
ZXNzIGFuZCBsZW5ndGgKPj4gKy0gY2xvY2tzOiBwaGFuZGxlIHRvIHRoZSBjbG9ja3MgZmVlZGlu
ZyB0aGUgZGlzcGxheSBlbmdpbmUgc3Vic3lzdGVtLgo+PiArCSAgVGhyZWUgYXJlIG5lZWRlZDoK
Pj4gKyAgLSAibW9kIjogdGhlIGRpc3BsYXkgZW5naW5lIG1vZHVsZSBjbG9jawo+PiArICAtICJi
dXMiOiB0aGUgYnVzIGNsb2NrIGZvciB0aGUgd2hvbGUgZGlzcGxheSBlbmdpbmUgc3Vic3lzdGVt
Cj4+ICstIGNsb2NrLW5hbWVzOiBNdXN0IGNvbnRhaW4gdGhlIGNsb2NrIG5hbWVzIGRlc2NyaWJl
ZCBqdXN0IGFib3ZlCj4+ICstIHJlc2V0czogcGhhbmRsZSB0byB0aGUgcmVzZXQgY29udHJvbCBm
b3IgdGhlIGRpc3BsYXkgZW5naW5lIHN1YnN5c3RlbS4KPj4gKy0gI2Nsb2NrLWNlbGxzIDogbXVz
dCBjb250YWluIDEKPj4gKy0gI3Jlc2V0LWNlbGxzIDogbXVzdCBjb250YWluIDEKPj4gKwo+PiAr
RXhhbXBsZToKPj4gK2RlMl9jbG9ja3M6IGNsb2NrQDAxMDAwMDAwIHsKPgo+IERyb3AgdGhlIGxl
YWRpbmcgMHMuIGR0YyBpbiBsaW51eC1uZXh0IHdpbGwgbm93IHdhcm4gb24gdGhpcyB3aXRoIFc9
MQo+IGNvbXBpbGUuIExvb2tzIGxpa2Ugc3VueGkgaGFzIGEgbG90IG9mIHRoZW0uIFBsZWFzZSBm
aXggc28gd2UgZG9uJ3Qga2VlcAo+IHJlcGVhdGluZyB0aGlzIHNhbWUgY29weS1uLXBhc3RlLgoK
VGhhbmtzIDstKQoKSSB3aWxsIHRyeSB0byBraWxsIHRoZW0gYWxsIDstKQoKPgo+PiArCWNvbXBh
dGlibGUgPSAiYWxsd2lubmVyLHN1bjUwaS1hNjQtZGUyLWNsayI7Cj4+ICsJcmVnID0gPDB4MDEw
MDAwMDAgMHgxMDAwMDA+Owo+PiArCWNsb2NrcyA9IDwmY2N1IENMS19ERT4sCj4+ICsJCSA8JmNj
dSBDTEtfQlVTX0RFPjsKPj4gKwljbG9jay1uYW1lcyA9ICJtb2QiLAo+PiArCQkgICAgICAiYnVz
IjsKPj4gKwlyZXNldHMgPSA8JmNjdSBSU1RfQlVTX0RFPjsKPj4gKwkjY2xvY2stY2VsbHMgPSA8
MT47Cj4+ICsJI3Jlc2V0LWNlbGxzID0gPDE+Owo+PiArfTsKPj4gLS0KPj4gMi4xMi4wCj4+Cgpf
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0t
a2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcK
aHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2Vy
bmVsCg==

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

* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
@ 2017-04-03 16:18       ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-03 16:18 UTC (permalink / raw)
  To: linux-arm-kernel



? 2017?04?03? 23:33, Rob Herring ??:
> On Thu, Mar 30, 2017 at 03:46:03AM +0800, Icenowy Zheng wrote:
>> From: Icenowy Zheng <icenowy@aosc.xyz>
>>
>> Allwinner "Display Engine 2.0" contains some clock controls in it.
>>
>> In order to add them as clock drivers, we need a device tree binding.
>> Add the binding here.
>>
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
>> ---
>> Changes in v3:
>> - Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.
>
> Why? You waste virtual memory space making this bigger than it needs to
> be. Not an issue so much for 64-bit.
>
>>
>>  .../devicetree/bindings/clock/sun8i-de2.txt        | 31 ++++++++++++++++++++++
>>  1 file changed, 31 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
>> new file mode 100644
>> index 000000000000..34cf79c05f13
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
>> @@ -0,0 +1,31 @@
>> +Allwinner Display Engine 2.0 Clock Control Binding
>> +--------------------------------------------------
>> +
>> +Required properties :
>> +- compatible: must contain one of the following compatibles:
>> +		- "allwinner,sun8i-a83t-de2-clk"
>> +		- "allwinner,sun50i-a64-de2-clk"
>> +		- "allwinner,sun50i-h5-de2-clk"
>> +
>> +- reg: Must contain the registers base address and length
>> +- clocks: phandle to the clocks feeding the display engine subsystem.
>> +	  Three are needed:
>> +  - "mod": the display engine module clock
>> +  - "bus": the bus clock for the whole display engine subsystem
>> +- clock-names: Must contain the clock names described just above
>> +- resets: phandle to the reset control for the display engine subsystem.
>> +- #clock-cells : must contain 1
>> +- #reset-cells : must contain 1
>> +
>> +Example:
>> +de2_clocks: clock at 01000000 {
>
> Drop the leading 0s. dtc in linux-next will now warn on this with W=1
> compile. Looks like sunxi has a lot of them. Please fix so we don't keep
> repeating this same copy-n-paste.

Thanks ;-)

I will try to kill them all ;-)

>
>> +	compatible = "allwinner,sun50i-a64-de2-clk";
>> +	reg = <0x01000000 0x100000>;
>> +	clocks = <&ccu CLK_DE>,
>> +		 <&ccu CLK_BUS_DE>;
>> +	clock-names = "mod",
>> +		      "bus";
>> +	resets = <&ccu RST_BUS_DE>;
>> +	#clock-cells = <1>;
>> +	#reset-cells = <1>;
>> +};
>> --
>> 2.12.0
>>

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
  2017-03-29 19:46   ` Icenowy Zheng
@ 2017-04-04 19:28     ` Sean Paul
  -1 siblings, 0 replies; 82+ messages in thread
From: Sean Paul @ 2017-04-04 19:28 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	devicetree, linux-kernel, dri-devel, linux-sunxi, linux-clk,
	linux-arm-kernel

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;
>  	}
>  
>  	return scrtc;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> index 230cb8f0d601..a4036ee44cf8 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>  
>  	struct sun4i_backend		*backend;
>  	struct sun4i_tcon		*tcon;
> -	struct sun4i_layer		**layers;
> +	void				**layers;
> +	const struct sunxi_layer_ops	*layer_ops;

I think you should probably take a different approach to abstract the layer
type. How about creating

struct sunxi_layer {
        struct drm_plane plane;
}

base and then subclassing that for sun4i and sun8i? By doing this you can avoid
the nasty casting and you can also get rid of the get_plane() hook and
layer_ops.

Sean



>  };
>  
>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> index f26bde5b9117..bc4a70d6968b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -16,7 +16,9 @@
>  #include <drm/drmP.h>
>  
>  #include "sun4i_backend.h"
> +#include "sun4i_crtc.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  
>  struct sun4i_plane_desc {
>  	       enum drm_plane_type     type;
> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
>  	},
>  };
>  
> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
> +{
> +	struct sun4i_layer *sun4i_layer = layer;
> +
> +	return &sun4i_layer->plane;
> +}
> +
> +static const struct sunxi_layer_ops layer_ops = {
> +	.get_plane = sun4i_layer_get_plane,
> +};
> +
>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  						struct sun4i_backend *backend,
>  						const struct sun4i_plane_desc *plane)
> @@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  }
>  
>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
> -				       struct sun4i_backend *backend)
> +				       struct sun4i_crtc *crtc)
>  {
>  	struct sun4i_layer **layers;
> +	struct sun4i_backend *backend = crtc->backend;
>  	int i;
>  
>  	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>  		layers[i] = layer;
>  	};
>  
> +	/* Assign layer ops to the CRTC */
> +	crtc->layer_ops = &layer_ops;
> +
>  	return layers;
>  }
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
> index 4be1f0919df2..425eea7b9e3b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>  }
>  
>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
> -				       struct sun4i_backend *backend);
> +				       struct sun4i_crtc *crtc);
>  
>  #endif /* _SUN4I_LAYER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
> new file mode 100644
> index 000000000000..d8838ec39299
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUNXI_LAYER_H_
> +#define _SUNXI_LAYER_H_
> +
> +struct sunxi_layer_ops {
> +	struct drm_plane *(*get_plane)(void *layer);
> +};
> +
> +#endif /* _SUNXI_LAYER_H_ */
> -- 
> 2.12.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Sean Paul, Software Engineer, Google / Chromium OS

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-04 19:28     ` Sean Paul
  0 siblings, 0 replies; 82+ messages in thread
From: Sean Paul @ 2017-04-04 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
> driver, we will finally have two types of layer.
> 
> Abstract the layer type to void * and a ops struct, which contains the
> only function used by crtc -- get the drm_plane struct of the layer.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> Refactored patch in v3.
> 
>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>  5 files changed, 49 insertions(+), 11 deletions(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> index 3c876c3a356a..33854ee7f636 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
> @@ -29,6 +29,7 @@
>  #include "sun4i_crtc.h"
>  #include "sun4i_drv.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  #include "sun4i_tcon.h"
>  
>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	scrtc->tcon = tcon;
>  
>  	/* Create our layers */
> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>  	if (IS_ERR(scrtc->layers)) {
>  		dev_err(drm->dev, "Couldn't create the planes\n");
>  		return NULL;
> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  
>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		switch (layer->plane.type) {
> +		switch (plane->type) {
>  		case DRM_PLANE_TYPE_PRIMARY:
> -			primary = &layer->plane;
> +			primary = plane;
>  			break;
>  		case DRM_PLANE_TYPE_CURSOR:
> -			cursor = &layer->plane;
> +			cursor = plane;
>  			break;
>  		default:
>  			break;
> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>  	/* Set possible_crtcs to this crtc for overlay planes */
>  	for (i = 0; scrtc->layers[i]; i++) {
>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
> -		struct sun4i_layer *layer = scrtc->layers[i];
> +		void *layer = scrtc->layers[i];
> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>  
> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
> -			layer->plane.possible_crtcs = possible_crtcs;
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			plane->possible_crtcs = possible_crtcs;
>  	}
>  
>  	return scrtc;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> index 230cb8f0d601..a4036ee44cf8 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>  
>  	struct sun4i_backend		*backend;
>  	struct sun4i_tcon		*tcon;
> -	struct sun4i_layer		**layers;
> +	void				**layers;
> +	const struct sunxi_layer_ops	*layer_ops;

I think you should probably take a different approach to abstract the layer
type. How about creating

struct sunxi_layer {
        struct drm_plane plane;
}

base and then subclassing that for sun4i and sun8i? By doing this you can avoid
the nasty casting and you can also get rid of the get_plane() hook and
layer_ops.

Sean



>  };
>  
>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
> index f26bde5b9117..bc4a70d6968b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
> @@ -16,7 +16,9 @@
>  #include <drm/drmP.h>
>  
>  #include "sun4i_backend.h"
> +#include "sun4i_crtc.h"
>  #include "sun4i_layer.h"
> +#include "sunxi_layer.h"
>  
>  struct sun4i_plane_desc {
>  	       enum drm_plane_type     type;
> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
>  	},
>  };
>  
> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
> +{
> +	struct sun4i_layer *sun4i_layer = layer;
> +
> +	return &sun4i_layer->plane;
> +}
> +
> +static const struct sunxi_layer_ops layer_ops = {
> +	.get_plane = sun4i_layer_get_plane,
> +};
> +
>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  						struct sun4i_backend *backend,
>  						const struct sun4i_plane_desc *plane)
> @@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>  }
>  
>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
> -				       struct sun4i_backend *backend)
> +				       struct sun4i_crtc *crtc)
>  {
>  	struct sun4i_layer **layers;
> +	struct sun4i_backend *backend = crtc->backend;
>  	int i;
>  
>  	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>  		layers[i] = layer;
>  	};
>  
> +	/* Assign layer ops to the CRTC */
> +	crtc->layer_ops = &layer_ops;
> +
>  	return layers;
>  }
> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
> index 4be1f0919df2..425eea7b9e3b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>  }
>  
>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
> -				       struct sun4i_backend *backend);
> +				       struct sun4i_crtc *crtc);
>  
>  #endif /* _SUN4I_LAYER_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
> new file mode 100644
> index 000000000000..d8838ec39299
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
> @@ -0,0 +1,17 @@
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SUNXI_LAYER_H_
> +#define _SUNXI_LAYER_H_
> +
> +struct sunxi_layer_ops {
> +	struct drm_plane *(*get_plane)(void *layer);
> +};
> +
> +#endif /* _SUNXI_LAYER_H_ */
> -- 
> 2.12.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Sean Paul, Software Engineer, Google / Chromium OS

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
  2017-04-04 19:28     ` Sean Paul
  (?)
@ 2017-04-04 19:53       ` Icenowy Zheng
  -1 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-04 19:53 UTC (permalink / raw)
  To: Sean Paul
  Cc: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r



在 2017年04月05日 03:28, Sean Paul 写道:
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>  	scrtc->tcon = tcon;
>>
>>  	/* Create our layers */
>> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>  	if (IS_ERR(scrtc->layers)) {
>>  		dev_err(drm->dev, "Couldn't create the planes\n");
>>  		return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>>  	for (i = 0; scrtc->layers[i]; i++) {
>> -		struct sun4i_layer *layer = scrtc->layers[i];
>> +		void *layer = scrtc->layers[i];
>> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -		switch (layer->plane.type) {
>> +		switch (plane->type) {
>>  		case DRM_PLANE_TYPE_PRIMARY:
>> -			primary = &layer->plane;
>> +			primary = plane;
>>  			break;
>>  		case DRM_PLANE_TYPE_CURSOR:
>> -			cursor = &layer->plane;
>> +			cursor = plane;
>>  			break;
>>  		default:
>>  			break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>  	/* Set possible_crtcs to this crtc for overlay planes */
>>  	for (i = 0; scrtc->layers[i]; i++) {
>>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -		struct sun4i_layer *layer = scrtc->layers[i];
>> +		void *layer = scrtc->layers[i];
>> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -			layer->plane.possible_crtcs = possible_crtcs;
>> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +			plane->possible_crtcs = possible_crtcs;
>>  	}
>>
>>  	return scrtc;
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> index 230cb8f0d601..a4036ee44cf8 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>
>>  	struct sun4i_backend		*backend;
>>  	struct sun4i_tcon		*tcon;
>> -	struct sun4i_layer		**layers;
>> +	void				**layers;
>> +	const struct sunxi_layer_ops	*layer_ops;
>
> I think you should probably take a different approach to abstract the layer
> type. How about creating
>
> struct sunxi_layer {
>         struct drm_plane plane;
> }
>
> base and then subclassing that for sun4i and sun8i? By doing this you can avoid
> the nasty casting and you can also get rid of the get_plane() hook and
> layer_ops.

For the situation that using ** things are easily to get weird.

>
> Sean
>
>
>
>>  };
>>
>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
>> index f26bde5b9117..bc4a70d6968b 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>> @@ -16,7 +16,9 @@
>>  #include <drm/drmP.h>
>>
>>  #include "sun4i_backend.h"
>> +#include "sun4i_crtc.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>
>>  struct sun4i_plane_desc {
>>  	       enum drm_plane_type     type;
>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
>>  	},
>>  };
>>
>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>> +{
>> +	struct sun4i_layer *sun4i_layer = layer;
>> +
>> +	return &sun4i_layer->plane;
>> +}
>> +
>> +static const struct sunxi_layer_ops layer_ops = {
>> +	.get_plane = sun4i_layer_get_plane,
>> +};
>> +
>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>  						struct sun4i_backend *backend,
>>  						const struct sun4i_plane_desc *plane)
>> @@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>  }
>>
>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>> -				       struct sun4i_backend *backend)
>> +				       struct sun4i_crtc *crtc)
>>  {
>>  	struct sun4i_layer **layers;
>> +	struct sun4i_backend *backend = crtc->backend;
>>  	int i;
>>
>>  	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>  		layers[i] = layer;
>>  	};
>>
>> +	/* Assign layer ops to the CRTC */
>> +	crtc->layer_ops = &layer_ops;
>> +
>>  	return layers;
>>  }
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
>> index 4be1f0919df2..425eea7b9e3b 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>  }
>>
>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>> -				       struct sun4i_backend *backend);
>> +				       struct sun4i_crtc *crtc);
>>
>>  #endif /* _SUN4I_LAYER_H_ */
>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
>> new file mode 100644
>> index 000000000000..d8838ec39299
>> --- /dev/null
>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>> @@ -0,0 +1,17 @@
>> +/*
>> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + */
>> +
>> +#ifndef _SUNXI_LAYER_H_
>> +#define _SUNXI_LAYER_H_
>> +
>> +struct sunxi_layer_ops {
>> +	struct drm_plane *(*get_plane)(void *layer);
>> +};
>> +
>> +#endif /* _SUNXI_LAYER_H_ */
>> --
>> 2.12.0
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

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

* Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-04 19:53       ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-04 19:53 UTC (permalink / raw)
  To: Sean Paul
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Chen-Yu Tsai, Rob Herring, Maxime Ripard, linux-clk,
	linux-arm-kernel

CgrlnKggMjAxN+W5tDA05pyIMDXml6UgMDM6MjgsIFNlYW4gUGF1bCDlhpnpgZM6Cj4gT24gVGh1
LCBNYXIgMzAsIDIwMTcgYXQgMDM6NDY6MDZBTSArMDgwMCwgSWNlbm93eSBaaGVuZyB3cm90ZToK
Pj4gQXMgd2UgYXJlIGdvaW5nIHRvIGFkZCBzdXBwb3J0IGZvciB0aGUgQWxsd2lubmVyIERFMiBN
aXhlciBpbiBzdW40aS1kcm0KPj4gZHJpdmVyLCB3ZSB3aWxsIGZpbmFsbHkgaGF2ZSB0d28gdHlw
ZXMgb2YgbGF5ZXIuCj4+Cj4+IEFic3RyYWN0IHRoZSBsYXllciB0eXBlIHRvIHZvaWQgKiBhbmQg
YSBvcHMgc3RydWN0LCB3aGljaCBjb250YWlucyB0aGUKPj4gb25seSBmdW5jdGlvbiB1c2VkIGJ5
IGNydGMgLS0gZ2V0IHRoZSBkcm1fcGxhbmUgc3RydWN0IG9mIHRoZSBsYXllci4KPj4KPj4gU2ln
bmVkLW9mZi1ieTogSWNlbm93eSBaaGVuZyA8aWNlbm93eUBhb3NjLmlvPgo+PiAtLS0KPj4gUmVm
YWN0b3JlZCBwYXRjaCBpbiB2My4KPj4KPj4gIGRyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9j
cnRjLmMgIHwgMTkgKysrKysrKysrKystLS0tLS0tLQo+PiAgZHJpdmVycy9ncHUvZHJtL3N1bjRp
L3N1bjRpX2NydGMuaCAgfCAgMyArKy0KPj4gIGRyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9s
YXllci5jIHwgMTkgKysrKysrKysrKysrKysrKysrLQo+PiAgZHJpdmVycy9ncHUvZHJtL3N1bjRp
L3N1bjRpX2xheWVyLmggfCAgMiArLQo+PiAgZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bnhpX2xh
eWVyLmggfCAxNyArKysrKysrKysrKysrKysrKwo+PiAgNSBmaWxlcyBjaGFuZ2VkLCA0OSBpbnNl
cnRpb25zKCspLCAxMSBkZWxldGlvbnMoLSkKPj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJz
L2dwdS9kcm0vc3VuNGkvc3VueGlfbGF5ZXIuaAo+Pgo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9n
cHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuYyBiL2RyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9j
cnRjLmMKPj4gaW5kZXggM2M4NzZjM2EzNTZhLi4zMzg1NGVlN2Y2MzYgMTAwNjQ0Cj4+IC0tLSBh
L2RyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9jcnRjLmMKPj4gKysrIGIvZHJpdmVycy9ncHUv
ZHJtL3N1bjRpL3N1bjRpX2NydGMuYwo+PiBAQCAtMjksNiArMjksNyBAQAo+PiAgI2luY2x1ZGUg
InN1bjRpX2NydGMuaCIKPj4gICNpbmNsdWRlICJzdW40aV9kcnYuaCIKPj4gICNpbmNsdWRlICJz
dW40aV9sYXllci5oIgo+PiArI2luY2x1ZGUgInN1bnhpX2xheWVyLmgiCj4+ICAjaW5jbHVkZSAi
c3VuNGlfdGNvbi5oIgo+Pgo+PiAgc3RhdGljIHZvaWQgc3VuNGlfY3J0Y19hdG9taWNfYmVnaW4o
c3RydWN0IGRybV9jcnRjICpjcnRjLAo+PiBAQCAtMTQ5LDcgKzE1MCw3IEBAIHN0cnVjdCBzdW40
aV9jcnRjICpzdW40aV9jcnRjX2luaXQoc3RydWN0IGRybV9kZXZpY2UgKmRybSwKPj4gIAlzY3J0
Yy0+dGNvbiA9IHRjb247Cj4+Cj4+ICAJLyogQ3JlYXRlIG91ciBsYXllcnMgKi8KPj4gLQlzY3J0
Yy0+bGF5ZXJzID0gc3VuNGlfbGF5ZXJzX2luaXQoZHJtLCBzY3J0Yy0+YmFja2VuZCk7Cj4+ICsJ
c2NydGMtPmxheWVycyA9ICh2b2lkICoqKXN1bjRpX2xheWVyc19pbml0KGRybSwgc2NydGMpOwo+
PiAgCWlmIChJU19FUlIoc2NydGMtPmxheWVycykpIHsKPj4gIAkJZGV2X2Vycihkcm0tPmRldiwg
IkNvdWxkbid0IGNyZWF0ZSB0aGUgcGxhbmVzXG4iKTsKPj4gIAkJcmV0dXJuIE5VTEw7Cj4+IEBA
IC0xNTcsMTQgKzE1OCwxNSBAQCBzdHJ1Y3Qgc3VuNGlfY3J0YyAqc3VuNGlfY3J0Y19pbml0KHN0
cnVjdCBkcm1fZGV2aWNlICpkcm0sCj4+Cj4+ICAJLyogZmluZCBwcmltYXJ5IGFuZCBjdXJzb3Ig
cGxhbmVzIGZvciBkcm1fY3J0Y19pbml0X3dpdGhfcGxhbmVzICovCj4+ICAJZm9yIChpID0gMDsg
c2NydGMtPmxheWVyc1tpXTsgaSsrKSB7Cj4+IC0JCXN0cnVjdCBzdW40aV9sYXllciAqbGF5ZXIg
PSBzY3J0Yy0+bGF5ZXJzW2ldOwo+PiArCQl2b2lkICpsYXllciA9IHNjcnRjLT5sYXllcnNbaV07
Cj4+ICsJCXN0cnVjdCBkcm1fcGxhbmUgKnBsYW5lID0gc2NydGMtPmxheWVyX29wcy0+Z2V0X3Bs
YW5lKGxheWVyKTsKPj4KPj4gLQkJc3dpdGNoIChsYXllci0+cGxhbmUudHlwZSkgewo+PiArCQlz
d2l0Y2ggKHBsYW5lLT50eXBlKSB7Cj4+ICAJCWNhc2UgRFJNX1BMQU5FX1RZUEVfUFJJTUFSWToK
Pj4gLQkJCXByaW1hcnkgPSAmbGF5ZXItPnBsYW5lOwo+PiArCQkJcHJpbWFyeSA9IHBsYW5lOwo+
PiAgCQkJYnJlYWs7Cj4+ICAJCWNhc2UgRFJNX1BMQU5FX1RZUEVfQ1VSU09SOgo+PiAtCQkJY3Vy
c29yID0gJmxheWVyLT5wbGFuZTsKPj4gKwkJCWN1cnNvciA9IHBsYW5lOwo+PiAgCQkJYnJlYWs7
Cj4+ICAJCWRlZmF1bHQ6Cj4+ICAJCQlicmVhazsKPj4gQEAgLTE5MCwxMCArMTkyLDExIEBAIHN0
cnVjdCBzdW40aV9jcnRjICpzdW40aV9jcnRjX2luaXQoc3RydWN0IGRybV9kZXZpY2UgKmRybSwK
Pj4gIAkvKiBTZXQgcG9zc2libGVfY3J0Y3MgdG8gdGhpcyBjcnRjIGZvciBvdmVybGF5IHBsYW5l
cyAqLwo+PiAgCWZvciAoaSA9IDA7IHNjcnRjLT5sYXllcnNbaV07IGkrKykgewo+PiAgCQl1aW50
MzJfdCBwb3NzaWJsZV9jcnRjcyA9IEJJVChkcm1fY3J0Y19pbmRleCgmc2NydGMtPmNydGMpKTsK
Pj4gLQkJc3RydWN0IHN1bjRpX2xheWVyICpsYXllciA9IHNjcnRjLT5sYXllcnNbaV07Cj4+ICsJ
CXZvaWQgKmxheWVyID0gc2NydGMtPmxheWVyc1tpXTsKPj4gKwkJc3RydWN0IGRybV9wbGFuZSAq
cGxhbmUgPSBzY3J0Yy0+bGF5ZXJfb3BzLT5nZXRfcGxhbmUobGF5ZXIpOwo+Pgo+PiAtCQlpZiAo
bGF5ZXItPnBsYW5lLnR5cGUgPT0gRFJNX1BMQU5FX1RZUEVfT1ZFUkxBWSkKPj4gLQkJCWxheWVy
LT5wbGFuZS5wb3NzaWJsZV9jcnRjcyA9IHBvc3NpYmxlX2NydGNzOwo+PiArCQlpZiAocGxhbmUt
PnR5cGUgPT0gRFJNX1BMQU5FX1RZUEVfT1ZFUkxBWSkKPj4gKwkJCXBsYW5lLT5wb3NzaWJsZV9j
cnRjcyA9IHBvc3NpYmxlX2NydGNzOwo+PiAgCX0KPj4KPj4gIAlyZXR1cm4gc2NydGM7Cj4+IGRp
ZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfY3J0Yy5oIGIvZHJpdmVycy9n
cHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuaAo+PiBpbmRleCAyMzBjYjhmMGQ2MDEuLmE0MDM2ZWU0
NGNmOCAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuaAo+
PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfY3J0Yy5oCj4+IEBAIC0xOSw3ICsx
OSw4IEBAIHN0cnVjdCBzdW40aV9jcnRjIHsKPj4KPj4gIAlzdHJ1Y3Qgc3VuNGlfYmFja2VuZAkJ
KmJhY2tlbmQ7Cj4+ICAJc3RydWN0IHN1bjRpX3Rjb24JCSp0Y29uOwo+PiAtCXN0cnVjdCBzdW40
aV9sYXllcgkJKipsYXllcnM7Cj4+ICsJdm9pZAkJCQkqKmxheWVyczsKPj4gKwljb25zdCBzdHJ1
Y3Qgc3VueGlfbGF5ZXJfb3BzCSpsYXllcl9vcHM7Cj4KPiBJIHRoaW5rIHlvdSBzaG91bGQgcHJv
YmFibHkgdGFrZSBhIGRpZmZlcmVudCBhcHByb2FjaCB0byBhYnN0cmFjdCB0aGUgbGF5ZXIKPiB0
eXBlLiBIb3cgYWJvdXQgY3JlYXRpbmcKPgo+IHN0cnVjdCBzdW54aV9sYXllciB7Cj4gICAgICAg
ICBzdHJ1Y3QgZHJtX3BsYW5lIHBsYW5lOwo+IH0KPgo+IGJhc2UgYW5kIHRoZW4gc3ViY2xhc3Np
bmcgdGhhdCBmb3Igc3VuNGkgYW5kIHN1bjhpPyBCeSBkb2luZyB0aGlzIHlvdSBjYW4gYXZvaWQK
PiB0aGUgbmFzdHkgY2FzdGluZyBhbmQgeW91IGNhbiBhbHNvIGdldCByaWQgb2YgdGhlIGdldF9w
bGFuZSgpIGhvb2sgYW5kCj4gbGF5ZXJfb3BzLgoKRm9yIHRoZSBzaXR1YXRpb24gdGhhdCB1c2lu
ZyAqKiB0aGluZ3MgYXJlIGVhc2lseSB0byBnZXQgd2VpcmQuCgo+Cj4gU2Vhbgo+Cj4KPgo+PiAg
fTsKPj4KPj4gIHN0YXRpYyBpbmxpbmUgc3RydWN0IHN1bjRpX2NydGMgKmRybV9jcnRjX3RvX3N1
bjRpX2NydGMoc3RydWN0IGRybV9jcnRjICpjcnRjKQo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9n
cHUvZHJtL3N1bjRpL3N1bjRpX2xheWVyLmMgYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlf
bGF5ZXIuYwo+PiBpbmRleCBmMjZiZGU1YjkxMTcuLmJjNGE3MGQ2OTY4YiAxMDA2NDQKPj4gLS0t
IGEvZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2xheWVyLmMKPj4gKysrIGIvZHJpdmVycy9n
cHUvZHJtL3N1bjRpL3N1bjRpX2xheWVyLmMKPj4gQEAgLTE2LDcgKzE2LDkgQEAKPj4gICNpbmNs
dWRlIDxkcm0vZHJtUC5oPgo+Pgo+PiAgI2luY2x1ZGUgInN1bjRpX2JhY2tlbmQuaCIKPj4gKyNp
bmNsdWRlICJzdW40aV9jcnRjLmgiCj4+ICAjaW5jbHVkZSAic3VuNGlfbGF5ZXIuaCIKPj4gKyNp
bmNsdWRlICJzdW54aV9sYXllci5oIgo+Pgo+PiAgc3RydWN0IHN1bjRpX3BsYW5lX2Rlc2Mgewo+
PiAgCSAgICAgICBlbnVtIGRybV9wbGFuZV90eXBlICAgICB0eXBlOwo+PiBAQCAtMTAwLDYgKzEw
MiwxNyBAQCBzdGF0aWMgY29uc3Qgc3RydWN0IHN1bjRpX3BsYW5lX2Rlc2Mgc3VuNGlfYmFja2Vu
ZF9wbGFuZXNbXSA9IHsKPj4gIAl9LAo+PiAgfTsKPj4KPj4gK3N0YXRpYyBzdHJ1Y3QgZHJtX3Bs
YW5lICpzdW40aV9sYXllcl9nZXRfcGxhbmUodm9pZCAqbGF5ZXIpCj4+ICt7Cj4+ICsJc3RydWN0
IHN1bjRpX2xheWVyICpzdW40aV9sYXllciA9IGxheWVyOwo+PiArCj4+ICsJcmV0dXJuICZzdW40
aV9sYXllci0+cGxhbmU7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3VueGlf
bGF5ZXJfb3BzIGxheWVyX29wcyA9IHsKPj4gKwkuZ2V0X3BsYW5lID0gc3VuNGlfbGF5ZXJfZ2V0
X3BsYW5lLAo+PiArfTsKPj4gKwo+PiAgc3RhdGljIHN0cnVjdCBzdW40aV9sYXllciAqc3VuNGlf
bGF5ZXJfaW5pdF9vbmUoc3RydWN0IGRybV9kZXZpY2UgKmRybSwKPj4gIAkJCQkJCXN0cnVjdCBz
dW40aV9iYWNrZW5kICpiYWNrZW5kLAo+PiAgCQkJCQkJY29uc3Qgc3RydWN0IHN1bjRpX3BsYW5l
X2Rlc2MgKnBsYW5lKQo+PiBAQCAtMTI5LDkgKzE0MiwxMCBAQCBzdGF0aWMgc3RydWN0IHN1bjRp
X2xheWVyICpzdW40aV9sYXllcl9pbml0X29uZShzdHJ1Y3QgZHJtX2RldmljZSAqZHJtLAo+PiAg
fQo+Pgo+PiAgc3RydWN0IHN1bjRpX2xheWVyICoqc3VuNGlfbGF5ZXJzX2luaXQoc3RydWN0IGRy
bV9kZXZpY2UgKmRybSwKPj4gLQkJCQkgICAgICAgc3RydWN0IHN1bjRpX2JhY2tlbmQgKmJhY2tl
bmQpCj4+ICsJCQkJICAgICAgIHN0cnVjdCBzdW40aV9jcnRjICpjcnRjKQo+PiAgewo+PiAgCXN0
cnVjdCBzdW40aV9sYXllciAqKmxheWVyczsKPj4gKwlzdHJ1Y3Qgc3VuNGlfYmFja2VuZCAqYmFj
a2VuZCA9IGNydGMtPmJhY2tlbmQ7Cj4+ICAJaW50IGk7Cj4+Cj4+ICAJbGF5ZXJzID0gZGV2bV9r
Y2FsbG9jKGRybS0+ZGV2LCBBUlJBWV9TSVpFKHN1bjRpX2JhY2tlbmRfcGxhbmVzKSArIDEsCj4+
IEBAIC0xODEsNSArMTk1LDggQEAgc3RydWN0IHN1bjRpX2xheWVyICoqc3VuNGlfbGF5ZXJzX2lu
aXQoc3RydWN0IGRybV9kZXZpY2UgKmRybSwKPj4gIAkJbGF5ZXJzW2ldID0gbGF5ZXI7Cj4+ICAJ
fTsKPj4KPj4gKwkvKiBBc3NpZ24gbGF5ZXIgb3BzIHRvIHRoZSBDUlRDICovCj4+ICsJY3J0Yy0+
bGF5ZXJfb3BzID0gJmxheWVyX29wczsKPj4gKwo+PiAgCXJldHVybiBsYXllcnM7Cj4+ICB9Cj4+
IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5ZXIuaCBiL2RyaXZl
cnMvZ3B1L2RybS9zdW40aS9zdW40aV9sYXllci5oCj4+IGluZGV4IDRiZTFmMDkxOWRmMi4uNDI1
ZWVhN2I5ZTNiIDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5
ZXIuaAo+PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5ZXIuaAo+PiBAQCAt
MjcsNiArMjcsNiBAQCBwbGFuZV90b19zdW40aV9sYXllcihzdHJ1Y3QgZHJtX3BsYW5lICpwbGFu
ZSkKPj4gIH0KPj4KPj4gIHN0cnVjdCBzdW40aV9sYXllciAqKnN1bjRpX2xheWVyc19pbml0KHN0
cnVjdCBkcm1fZGV2aWNlICpkcm0sCj4+IC0JCQkJICAgICAgIHN0cnVjdCBzdW40aV9iYWNrZW5k
ICpiYWNrZW5kKTsKPj4gKwkJCQkgICAgICAgc3RydWN0IHN1bjRpX2NydGMgKmNydGMpOwo+Pgo+
PiAgI2VuZGlmIC8qIF9TVU40SV9MQVlFUl9IXyAqLwo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9n
cHUvZHJtL3N1bjRpL3N1bnhpX2xheWVyLmggYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VueGlf
bGF5ZXIuaAo+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwMDAwMDAuLmQ4
ODM4ZWMzOTI5OQo+PiAtLS0gL2Rldi9udWxsCj4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9zdW40
aS9zdW54aV9sYXllci5oCj4+IEBAIC0wLDAgKzEsMTcgQEAKPj4gKy8qCj4+ICsgKiBDb3B5cmln
aHQgKEMpIDIwMTcgSWNlbm93eSBaaGVuZyA8aWNlbm93eUBhb3NjLnh5ej4KPj4gKyAqCj4+ICsg
KiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQg
YW5kL29yCj4+ICsgKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJh
bCBQdWJsaWMgTGljZW5zZSBhcwo+PiArICogcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJl
IEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIgb2YKPj4gKyAqIHRoZSBMaWNlbnNlLCBvciAo
YXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgo+PiArICovCj4+ICsKPj4gKyNpZm5k
ZWYgX1NVTlhJX0xBWUVSX0hfCj4+ICsjZGVmaW5lIF9TVU5YSV9MQVlFUl9IXwo+PiArCj4+ICtz
dHJ1Y3Qgc3VueGlfbGF5ZXJfb3BzIHsKPj4gKwlzdHJ1Y3QgZHJtX3BsYW5lICooKmdldF9wbGFu
ZSkodm9pZCAqbGF5ZXIpOwo+PiArfTsKPj4gKwo+PiArI2VuZGlmIC8qIF9TVU5YSV9MQVlFUl9I
XyAqLwo+PiAtLQo+PiAyLjEyLjAKPj4KPj4KPj4gX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18KPj4gbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKPj4g
bGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCj4+IGh0dHA6Ly9saXN0cy5pbmZy
YWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo+CgpfX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1h
aWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xp
c3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==

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

* [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-04 19:53       ` Icenowy Zheng
  0 siblings, 0 replies; 82+ messages in thread
From: Icenowy Zheng @ 2017-04-04 19:53 UTC (permalink / raw)
  To: linux-arm-kernel



? 2017?04?05? 03:28, Sean Paul ??:
> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>> driver, we will finally have two types of layer.
>>
>> Abstract the layer type to void * and a ops struct, which contains the
>> only function used by crtc -- get the drm_plane struct of the layer.
>>
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> ---
>> Refactored patch in v3.
>>
>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> index 3c876c3a356a..33854ee7f636 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>> @@ -29,6 +29,7 @@
>>  #include "sun4i_crtc.h"
>>  #include "sun4i_drv.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>  #include "sun4i_tcon.h"
>>
>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>  	scrtc->tcon = tcon;
>>
>>  	/* Create our layers */
>> -	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>> +	scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>  	if (IS_ERR(scrtc->layers)) {
>>  		dev_err(drm->dev, "Couldn't create the planes\n");
>>  		return NULL;
>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>
>>  	/* find primary and cursor planes for drm_crtc_init_with_planes */
>>  	for (i = 0; scrtc->layers[i]; i++) {
>> -		struct sun4i_layer *layer = scrtc->layers[i];
>> +		void *layer = scrtc->layers[i];
>> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -		switch (layer->plane.type) {
>> +		switch (plane->type) {
>>  		case DRM_PLANE_TYPE_PRIMARY:
>> -			primary = &layer->plane;
>> +			primary = plane;
>>  			break;
>>  		case DRM_PLANE_TYPE_CURSOR:
>> -			cursor = &layer->plane;
>> +			cursor = plane;
>>  			break;
>>  		default:
>>  			break;
>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
>>  	/* Set possible_crtcs to this crtc for overlay planes */
>>  	for (i = 0; scrtc->layers[i]; i++) {
>>  		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
>> -		struct sun4i_layer *layer = scrtc->layers[i];
>> +		void *layer = scrtc->layers[i];
>> +		struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
>>
>> -		if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>> -			layer->plane.possible_crtcs = possible_crtcs;
>> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>> +			plane->possible_crtcs = possible_crtcs;
>>  	}
>>
>>  	return scrtc;
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> index 230cb8f0d601..a4036ee44cf8 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>
>>  	struct sun4i_backend		*backend;
>>  	struct sun4i_tcon		*tcon;
>> -	struct sun4i_layer		**layers;
>> +	void				**layers;
>> +	const struct sunxi_layer_ops	*layer_ops;
>
> I think you should probably take a different approach to abstract the layer
> type. How about creating
>
> struct sunxi_layer {
>         struct drm_plane plane;
> }
>
> base and then subclassing that for sun4i and sun8i? By doing this you can avoid
> the nasty casting and you can also get rid of the get_plane() hook and
> layer_ops.

For the situation that using ** things are easily to get weird.

>
> Sean
>
>
>
>>  };
>>
>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
>> index f26bde5b9117..bc4a70d6968b 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>> @@ -16,7 +16,9 @@
>>  #include <drm/drmP.h>
>>
>>  #include "sun4i_backend.h"
>> +#include "sun4i_crtc.h"
>>  #include "sun4i_layer.h"
>> +#include "sunxi_layer.h"
>>
>>  struct sun4i_plane_desc {
>>  	       enum drm_plane_type     type;
>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
>>  	},
>>  };
>>
>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>> +{
>> +	struct sun4i_layer *sun4i_layer = layer;
>> +
>> +	return &sun4i_layer->plane;
>> +}
>> +
>> +static const struct sunxi_layer_ops layer_ops = {
>> +	.get_plane = sun4i_layer_get_plane,
>> +};
>> +
>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>  						struct sun4i_backend *backend,
>>  						const struct sun4i_plane_desc *plane)
>> @@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>  }
>>
>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>> -				       struct sun4i_backend *backend)
>> +				       struct sun4i_crtc *crtc)
>>  {
>>  	struct sun4i_layer **layers;
>> +	struct sun4i_backend *backend = crtc->backend;
>>  	int i;
>>
>>  	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>  		layers[i] = layer;
>>  	};
>>
>> +	/* Assign layer ops to the CRTC */
>> +	crtc->layer_ops = &layer_ops;
>> +
>>  	return layers;
>>  }
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
>> index 4be1f0919df2..425eea7b9e3b 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>  }
>>
>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>> -				       struct sun4i_backend *backend);
>> +				       struct sun4i_crtc *crtc);
>>
>>  #endif /* _SUN4I_LAYER_H_ */
>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
>> new file mode 100644
>> index 000000000000..d8838ec39299
>> --- /dev/null
>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>> @@ -0,0 +1,17 @@
>> +/*
>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + */
>> +
>> +#ifndef _SUNXI_LAYER_H_
>> +#define _SUNXI_LAYER_H_
>> +
>> +struct sunxi_layer_ops {
>> +	struct drm_plane *(*get_plane)(void *layer);
>> +};
>> +
>> +#endif /* _SUNXI_LAYER_H_ */
>> --
>> 2.12.0
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

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

* Re: [linux-sunxi] Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05  2:27         ` Chen-Yu Tsai
  0 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  2:27 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Sean Paul, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, devicetree, linux-kernel, dri-devel, linux-sunxi,
	linux-clk, linux-arm-kernel

On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy@aosc.io> wrote:
>
>
> 在 2017年04月05日 03:28, Sean Paul 写道:
>>
>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>
>>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>>> driver, we will finally have two types of layer.
>>>
>>> Abstract the layer type to void * and a ops struct, which contains the
>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>
>>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>> ---
>>> Refactored patch in v3.
>>>
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> index 3c876c3a356a..33854ee7f636 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> @@ -29,6 +29,7 @@
>>>  #include "sun4i_crtc.h"
>>>  #include "sun4i_drv.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>  #include "sun4i_tcon.h"
>>>
>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device
>>> *drm,
>>>         scrtc->tcon = tcon;
>>>
>>>         /* Create our layers */
>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>         if (IS_ERR(scrtc->layers)) {
>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>                 return NULL;
>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>
>>>         /* find primary and cursor planes for drm_crtc_init_with_planes
>>> */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               switch (layer->plane.type) {
>>> +               switch (plane->type) {
>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>> -                       primary = &layer->plane;
>>> +                       primary = plane;
>>>                         break;
>>>                 case DRM_PLANE_TYPE_CURSOR:
>>> -                       cursor = &layer->plane;
>>> +                       cursor = plane;
>>>                         break;
>>>                 default:
>>>                         break;
>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>                 uint32_t possible_crtcs =
>>> BIT(drm_crtc_index(&scrtc->crtc));
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>> -                       layer->plane.possible_crtcs = possible_crtcs;
>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>> +                       plane->possible_crtcs = possible_crtcs;
>>>         }
>>>
>>>         return scrtc;
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> index 230cb8f0d601..a4036ee44cf8 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>
>>>         struct sun4i_backend            *backend;
>>>         struct sun4i_tcon               *tcon;
>>> -       struct sun4i_layer              **layers;
>>> +       void                            **layers;
>>> +       const struct sunxi_layer_ops    *layer_ops;
>>
>>
>> I think you should probably take a different approach to abstract the
>> layer
>> type. How about creating
>>
>> struct sunxi_layer {
>>         struct drm_plane plane;
>> }
>>
>> base and then subclassing that for sun4i and sun8i? By doing this you can
>> avoid
>> the nasty casting and you can also get rid of the get_plane() hook and
>> layer_ops.
>
>
> For the situation that using ** things are easily to get weird.

That code could be reworked, by initializing the layers directly within
the crtc init code. If you look at rockchip's drm driver, you'll see
they do this. There is a good reason to do it this way, as you need
to first create the primary and cursor layers, pass them in when you
create the crtc, then initialize any additional layers with the
possible_crtcs bitmap.

In our driver we are currently initializing all layers, then going
back and filling in possible_crtcs for the extra layers.

And as Maxime and I mentioned in the other thread, we don't really
need to keep a reference to **layers.

Regards
ChenYu

>
>>
>> Sean
>>
>>
>>
>>>  };
>>>
>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc
>>> *crtc)
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> index f26bde5b9117..bc4a70d6968b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> @@ -16,7 +16,9 @@
>>>  #include <drm/drmP.h>
>>>
>>>  #include "sun4i_backend.h"
>>> +#include "sun4i_crtc.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>
>>>  struct sun4i_plane_desc {
>>>                enum drm_plane_type     type;
>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>> sun4i_backend_planes[] = {
>>>         },
>>>  };
>>>
>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>> +{
>>> +       struct sun4i_layer *sun4i_layer = layer;
>>> +
>>> +       return &sun4i_layer->plane;
>>> +}
>>> +
>>> +static const struct sunxi_layer_ops layer_ops = {
>>> +       .get_plane = sun4i_layer_get_plane,
>>> +};
>>> +
>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>>                                                 struct sun4i_backend
>>> *backend,
>>>                                                 const struct
>>> sun4i_plane_desc *plane)
>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend)
>>> +                                      struct sun4i_crtc *crtc)
>>>  {
>>>         struct sun4i_layer **layers;
>>> +       struct sun4i_backend *backend = crtc->backend;
>>>         int i;
>>>
>>>         layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes)
>>> + 1,
>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>> drm_device *drm,
>>>                 layers[i] = layer;
>>>         };
>>>
>>> +       /* Assign layer ops to the CRTC */
>>> +       crtc->layer_ops = &layer_ops;
>>> +
>>>         return layers;
>>>  }
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> index 4be1f0919df2..425eea7b9e3b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend);
>>> +                                      struct sun4i_crtc *crtc);
>>>
>>>  #endif /* _SUN4I_LAYER_H_ */
>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> new file mode 100644
>>> index 000000000000..d8838ec39299
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> @@ -0,0 +1,17 @@
>>> +/*
>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License as
>>> + * published by the Free Software Foundation; either version 2 of
>>> + * the License, or (at your option) any later version.
>>> + */
>>> +
>>> +#ifndef _SUNXI_LAYER_H_
>>> +#define _SUNXI_LAYER_H_
>>> +
>>> +struct sunxi_layer_ops {
>>> +       struct drm_plane *(*get_plane)(void *layer);
>>> +};
>>> +
>>> +#endif /* _SUNXI_LAYER_H_ */
>>> --
>>> 2.12.0
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05  2:27         ` Chen-Yu Tsai
  0 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  2:27 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Sean Paul, Rob Herring, Maxime Ripard, Chen-Yu Tsai,
	Jernej Skrabec, devicetree, linux-kernel, dri-devel, linux-sunxi,
	linux-clk, linux-arm-kernel

On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org> wrote:
>
>
> 在 2017年04月05日 03:28, Sean Paul 写道:
>>
>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>
>>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>>> driver, we will finally have two types of layer.
>>>
>>> Abstract the layer type to void * and a ops struct, which contains the
>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>
>>> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
>>> ---
>>> Refactored patch in v3.
>>>
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> index 3c876c3a356a..33854ee7f636 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> @@ -29,6 +29,7 @@
>>>  #include "sun4i_crtc.h"
>>>  #include "sun4i_drv.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>  #include "sun4i_tcon.h"
>>>
>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device
>>> *drm,
>>>         scrtc->tcon = tcon;
>>>
>>>         /* Create our layers */
>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>         if (IS_ERR(scrtc->layers)) {
>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>                 return NULL;
>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>
>>>         /* find primary and cursor planes for drm_crtc_init_with_planes
>>> */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               switch (layer->plane.type) {
>>> +               switch (plane->type) {
>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>> -                       primary = &layer->plane;
>>> +                       primary = plane;
>>>                         break;
>>>                 case DRM_PLANE_TYPE_CURSOR:
>>> -                       cursor = &layer->plane;
>>> +                       cursor = plane;
>>>                         break;
>>>                 default:
>>>                         break;
>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>                 uint32_t possible_crtcs =
>>> BIT(drm_crtc_index(&scrtc->crtc));
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>> -                       layer->plane.possible_crtcs = possible_crtcs;
>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>> +                       plane->possible_crtcs = possible_crtcs;
>>>         }
>>>
>>>         return scrtc;
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> index 230cb8f0d601..a4036ee44cf8 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>
>>>         struct sun4i_backend            *backend;
>>>         struct sun4i_tcon               *tcon;
>>> -       struct sun4i_layer              **layers;
>>> +       void                            **layers;
>>> +       const struct sunxi_layer_ops    *layer_ops;
>>
>>
>> I think you should probably take a different approach to abstract the
>> layer
>> type. How about creating
>>
>> struct sunxi_layer {
>>         struct drm_plane plane;
>> }
>>
>> base and then subclassing that for sun4i and sun8i? By doing this you can
>> avoid
>> the nasty casting and you can also get rid of the get_plane() hook and
>> layer_ops.
>
>
> For the situation that using ** things are easily to get weird.

That code could be reworked, by initializing the layers directly within
the crtc init code. If you look at rockchip's drm driver, you'll see
they do this. There is a good reason to do it this way, as you need
to first create the primary and cursor layers, pass them in when you
create the crtc, then initialize any additional layers with the
possible_crtcs bitmap.

In our driver we are currently initializing all layers, then going
back and filling in possible_crtcs for the extra layers.

And as Maxime and I mentioned in the other thread, we don't really
need to keep a reference to **layers.

Regards
ChenYu

>
>>
>> Sean
>>
>>
>>
>>>  };
>>>
>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc
>>> *crtc)
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> index f26bde5b9117..bc4a70d6968b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> @@ -16,7 +16,9 @@
>>>  #include <drm/drmP.h>
>>>
>>>  #include "sun4i_backend.h"
>>> +#include "sun4i_crtc.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>
>>>  struct sun4i_plane_desc {
>>>                enum drm_plane_type     type;
>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>> sun4i_backend_planes[] = {
>>>         },
>>>  };
>>>
>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>> +{
>>> +       struct sun4i_layer *sun4i_layer = layer;
>>> +
>>> +       return &sun4i_layer->plane;
>>> +}
>>> +
>>> +static const struct sunxi_layer_ops layer_ops = {
>>> +       .get_plane = sun4i_layer_get_plane,
>>> +};
>>> +
>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>>                                                 struct sun4i_backend
>>> *backend,
>>>                                                 const struct
>>> sun4i_plane_desc *plane)
>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend)
>>> +                                      struct sun4i_crtc *crtc)
>>>  {
>>>         struct sun4i_layer **layers;
>>> +       struct sun4i_backend *backend = crtc->backend;
>>>         int i;
>>>
>>>         layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes)
>>> + 1,
>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>> drm_device *drm,
>>>                 layers[i] = layer;
>>>         };
>>>
>>> +       /* Assign layer ops to the CRTC */
>>> +       crtc->layer_ops = &layer_ops;
>>> +
>>>         return layers;
>>>  }
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> index 4be1f0919df2..425eea7b9e3b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend);
>>> +                                      struct sun4i_crtc *crtc);
>>>
>>>  #endif /* _SUN4I_LAYER_H_ */
>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> new file mode 100644
>>> index 000000000000..d8838ec39299
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> @@ -0,0 +1,17 @@
>>> +/*
>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License as
>>> + * published by the Free Software Foundation; either version 2 of
>>> + * the License, or (at your option) any later version.
>>> + */
>>> +
>>> +#ifndef _SUNXI_LAYER_H_
>>> +#define _SUNXI_LAYER_H_
>>> +
>>> +struct sunxi_layer_ops {
>>> +       struct drm_plane *(*get_plane)(void *layer);
>>> +};
>>> +
>>> +#endif /* _SUNXI_LAYER_H_ */
>>> --
>>> 2.12.0
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

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

* [linux-sunxi] Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05  2:27         ` Chen-Yu Tsai
  0 siblings, 0 replies; 82+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  2:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy@aosc.io> wrote:
>
>
> ? 2017?04?05? 03:28, Sean Paul ??:
>>
>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>
>>> As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
>>> driver, we will finally have two types of layer.
>>>
>>> Abstract the layer type to void * and a ops struct, which contains the
>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>
>>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>> ---
>>> Refactored patch in v3.
>>>
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> index 3c876c3a356a..33854ee7f636 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>> @@ -29,6 +29,7 @@
>>>  #include "sun4i_crtc.h"
>>>  #include "sun4i_drv.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>  #include "sun4i_tcon.h"
>>>
>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device
>>> *drm,
>>>         scrtc->tcon = tcon;
>>>
>>>         /* Create our layers */
>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>         if (IS_ERR(scrtc->layers)) {
>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>                 return NULL;
>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>
>>>         /* find primary and cursor planes for drm_crtc_init_with_planes
>>> */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               switch (layer->plane.type) {
>>> +               switch (plane->type) {
>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>> -                       primary = &layer->plane;
>>> +                       primary = plane;
>>>                         break;
>>>                 case DRM_PLANE_TYPE_CURSOR:
>>> -                       cursor = &layer->plane;
>>> +                       cursor = plane;
>>>                         break;
>>>                 default:
>>>                         break;
>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>> drm_device *drm,
>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>                 uint32_t possible_crtcs =
>>> BIT(drm_crtc_index(&scrtc->crtc));
>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>> +               void *layer = scrtc->layers[i];
>>> +               struct drm_plane *plane =
>>> scrtc->layer_ops->get_plane(layer);
>>>
>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>> -                       layer->plane.possible_crtcs = possible_crtcs;
>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>> +                       plane->possible_crtcs = possible_crtcs;
>>>         }
>>>
>>>         return scrtc;
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> index 230cb8f0d601..a4036ee44cf8 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>
>>>         struct sun4i_backend            *backend;
>>>         struct sun4i_tcon               *tcon;
>>> -       struct sun4i_layer              **layers;
>>> +       void                            **layers;
>>> +       const struct sunxi_layer_ops    *layer_ops;
>>
>>
>> I think you should probably take a different approach to abstract the
>> layer
>> type. How about creating
>>
>> struct sunxi_layer {
>>         struct drm_plane plane;
>> }
>>
>> base and then subclassing that for sun4i and sun8i? By doing this you can
>> avoid
>> the nasty casting and you can also get rid of the get_plane() hook and
>> layer_ops.
>
>
> For the situation that using ** things are easily to get weird.

That code could be reworked, by initializing the layers directly within
the crtc init code. If you look at rockchip's drm driver, you'll see
they do this. There is a good reason to do it this way, as you need
to first create the primary and cursor layers, pass them in when you
create the crtc, then initialize any additional layers with the
possible_crtcs bitmap.

In our driver we are currently initializing all layers, then going
back and filling in possible_crtcs for the extra layers.

And as Maxime and I mentioned in the other thread, we don't really
need to keep a reference to **layers.

Regards
ChenYu

>
>>
>> Sean
>>
>>
>>
>>>  };
>>>
>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc
>>> *crtc)
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> index f26bde5b9117..bc4a70d6968b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>> @@ -16,7 +16,9 @@
>>>  #include <drm/drmP.h>
>>>
>>>  #include "sun4i_backend.h"
>>> +#include "sun4i_crtc.h"
>>>  #include "sun4i_layer.h"
>>> +#include "sunxi_layer.h"
>>>
>>>  struct sun4i_plane_desc {
>>>                enum drm_plane_type     type;
>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>> sun4i_backend_planes[] = {
>>>         },
>>>  };
>>>
>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>> +{
>>> +       struct sun4i_layer *sun4i_layer = layer;
>>> +
>>> +       return &sun4i_layer->plane;
>>> +}
>>> +
>>> +static const struct sunxi_layer_ops layer_ops = {
>>> +       .get_plane = sun4i_layer_get_plane,
>>> +};
>>> +
>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
>>>                                                 struct sun4i_backend
>>> *backend,
>>>                                                 const struct
>>> sun4i_plane_desc *plane)
>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend)
>>> +                                      struct sun4i_crtc *crtc)
>>>  {
>>>         struct sun4i_layer **layers;
>>> +       struct sun4i_backend *backend = crtc->backend;
>>>         int i;
>>>
>>>         layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes)
>>> + 1,
>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>> drm_device *drm,
>>>                 layers[i] = layer;
>>>         };
>>>
>>> +       /* Assign layer ops to the CRTC */
>>> +       crtc->layer_ops = &layer_ops;
>>> +
>>>         return layers;
>>>  }
>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> index 4be1f0919df2..425eea7b9e3b 100644
>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>  }
>>>
>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>> -                                      struct sun4i_backend *backend);
>>> +                                      struct sun4i_crtc *crtc);
>>>
>>>  #endif /* _SUN4I_LAYER_H_ */
>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> new file mode 100644
>>> index 000000000000..d8838ec39299
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>> @@ -0,0 +1,17 @@
>>> +/*
>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License as
>>> + * published by the Free Software Foundation; either version 2 of
>>> + * the License, or (at your option) any later version.
>>> + */
>>> +
>>> +#ifndef _SUNXI_LAYER_H_
>>> +#define _SUNXI_LAYER_H_
>>> +
>>> +struct sunxi_layer_ops {
>>> +       struct drm_plane *(*get_plane)(void *layer);
>>> +};
>>> +
>>> +#endif /* _SUNXI_LAYER_H_ */
>>> --
>>> 2.12.0
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to linux-sunxi+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05 17:14           ` icenowy-h8G6r0blFSE
  0 siblings, 0 replies; 82+ messages in thread
From: icenowy @ 2017-04-05 17:14 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Rob Herring, Sean Paul, Maxime Ripard, linux-clk,
	linux-arm-kernel

在 2017-04-05 10:27,Chen-Yu Tsai 写道:
> On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy@aosc.io> wrote:
>> 
>> 
>> 在 2017年04月05日 03:28, Sean Paul 写道:
>>> 
>>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>> 
>>>> As we are going to add support for the Allwinner DE2 Mixer in 
>>>> sun4i-drm
>>>> driver, we will finally have two types of layer.
>>>> 
>>>> Abstract the layer type to void * and a ops struct, which contains 
>>>> the
>>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>> 
>>>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>>> ---
>>>> Refactored patch in v3.
>>>> 
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> 
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> index 3c876c3a356a..33854ee7f636 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> @@ -29,6 +29,7 @@
>>>>  #include "sun4i_crtc.h"
>>>>  #include "sun4i_drv.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>>  #include "sun4i_tcon.h"
>>>> 
>>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct 
>>>> drm_device
>>>> *drm,
>>>>         scrtc->tcon = tcon;
>>>> 
>>>>         /* Create our layers */
>>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>>         if (IS_ERR(scrtc->layers)) {
>>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>>                 return NULL;
>>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>> 
>>>>         /* find primary and cursor planes for 
>>>> drm_crtc_init_with_planes
>>>> */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               switch (layer->plane.type) {
>>>> +               switch (plane->type) {
>>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>>> -                       primary = &layer->plane;
>>>> +                       primary = plane;
>>>>                         break;
>>>>                 case DRM_PLANE_TYPE_CURSOR:
>>>> -                       cursor = &layer->plane;
>>>> +                       cursor = plane;
>>>>                         break;
>>>>                 default:
>>>>                         break;
>>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>>                 uint32_t possible_crtcs =
>>>> BIT(drm_crtc_index(&scrtc->crtc));
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>>> -                       layer->plane.possible_crtcs = 
>>>> possible_crtcs;
>>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>>> +                       plane->possible_crtcs = possible_crtcs;
>>>>         }
>>>> 
>>>>         return scrtc;
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> index 230cb8f0d601..a4036ee44cf8 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>> 
>>>>         struct sun4i_backend            *backend;
>>>>         struct sun4i_tcon               *tcon;
>>>> -       struct sun4i_layer              **layers;
>>>> +       void                            **layers;
>>>> +       const struct sunxi_layer_ops    *layer_ops;
>>> 
>>> 
>>> I think you should probably take a different approach to abstract the
>>> layer
>>> type. How about creating
>>> 
>>> struct sunxi_layer {
>>>         struct drm_plane plane;
>>> }
>>> 
>>> base and then subclassing that for sun4i and sun8i? By doing this you 
>>> can
>>> avoid
>>> the nasty casting and you can also get rid of the get_plane() hook 
>>> and
>>> layer_ops.
>> 
>> 
>> For the situation that using ** things are easily to get weird.
> 
> That code could be reworked, by initializing the layers directly within
> the crtc init code. If you look at rockchip's drm driver, you'll see
> they do this. There is a good reason to do it this way, as you need
> to first create the primary and cursor layers, pass them in when you
> create the crtc, then initialize any additional layers with the
> possible_crtcs bitmap.

I feel that it's still more proper to offload plane creation code
to *_layers_init function, as:

1. We cannot assume the cursor layer's
existance. In fact currently no code in sun4i-drm (including this
patchset) create a cursor layer.

2. The format of planes heavily depend on the engine type (
sun4i-backend or sun8i-mixer).

3. We should create planes according to the type of engine.
Currently the *_layers_init function is part of engine code (See my
Makefile change).

4. If we do so we will have two codes for plane creating -- one for
primary in sun4i_crtc_init, another for overlays in *_layers_init.

> 
> In our driver we are currently initializing all layers, then going
> back and filling in possible_crtcs for the extra layers.
> 
> And as Maxime and I mentioned in the other thread, we don't really
> need to keep a reference to **layers.

It's correct, layers doesn't need to be kept.

And the struct sunxi_layer refactor also makes sense.

> 
> Regards
> ChenYu
> 
>> 
>>> 
>>> Sean
>>> 
>>> 
>>> 
>>>>  };
>>>> 
>>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct 
>>>> drm_crtc
>>>> *crtc)
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> index f26bde5b9117..bc4a70d6968b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> @@ -16,7 +16,9 @@
>>>>  #include <drm/drmP.h>
>>>> 
>>>>  #include "sun4i_backend.h"
>>>> +#include "sun4i_crtc.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>> 
>>>>  struct sun4i_plane_desc {
>>>>                enum drm_plane_type     type;
>>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>>> sun4i_backend_planes[] = {
>>>>         },
>>>>  };
>>>> 
>>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>>> +{
>>>> +       struct sun4i_layer *sun4i_layer = layer;
>>>> +
>>>> +       return &sun4i_layer->plane;
>>>> +}
>>>> +
>>>> +static const struct sunxi_layer_ops layer_ops = {
>>>> +       .get_plane = sun4i_layer_get_plane,
>>>> +};
>>>> +
>>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device 
>>>> *drm,
>>>>                                                 struct sun4i_backend
>>>> *backend,
>>>>                                                 const struct
>>>> sun4i_plane_desc *plane)
>>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend)
>>>> +                                      struct sun4i_crtc *crtc)
>>>>  {
>>>>         struct sun4i_layer **layers;
>>>> +       struct sun4i_backend *backend = crtc->backend;
>>>>         int i;
>>>> 
>>>>         layers = devm_kcalloc(drm->dev, 
>>>> ARRAY_SIZE(sun4i_backend_planes)
>>>> + 1,
>>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>>> drm_device *drm,
>>>>                 layers[i] = layer;
>>>>         };
>>>> 
>>>> +       /* Assign layer ops to the CRTC */
>>>> +       crtc->layer_ops = &layer_ops;
>>>> +
>>>>         return layers;
>>>>  }
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> index 4be1f0919df2..425eea7b9e3b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend);
>>>> +                                      struct sun4i_crtc *crtc);
>>>> 
>>>>  #endif /* _SUN4I_LAYER_H_ */
>>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> new file mode 100644
>>>> index 000000000000..d8838ec39299
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> @@ -0,0 +1,17 @@
>>>> +/*
>>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU General Public License as
>>>> + * published by the Free Software Foundation; either version 2 of
>>>> + * the License, or (at your option) any later version.
>>>> + */
>>>> +
>>>> +#ifndef _SUNXI_LAYER_H_
>>>> +#define _SUNXI_LAYER_H_
>>>> +
>>>> +struct sunxi_layer_ops {
>>>> +       struct drm_plane *(*get_plane)(void *layer);
>>>> +};
>>>> +
>>>> +#endif /* _SUNXI_LAYER_H_ */
>>>> --
>>>> 2.12.0
>>>> 
>>>> 
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel@lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>> 
>>> 
>> 
>> --
>> You received this message because you are subscribed to the Google 
>> Groups
>> "linux-sunxi" group.
>> To unsubscribe from this group and stop receiving emails from it, send 
>> an
>> email to linux-sunxi+unsubscribe@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
> 
> _______________________________________________
> 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] 82+ messages in thread

* Re: Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05 17:14           ` icenowy-h8G6r0blFSE
  0 siblings, 0 replies; 82+ messages in thread
From: icenowy-h8G6r0blFSE @ 2017-04-05 17:14 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: devicetree, Jernej Skrabec, linux-sunxi, linux-kernel, dri-devel,
	Rob Herring, Sean Paul, Maxime Ripard, linux-clk,
	linux-arm-kernel

在 2017-04-05 10:27,Chen-Yu Tsai 写道:
> On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org> wrote:
>> 
>> 
>> 在 2017年04月05日 03:28, Sean Paul 写道:
>>> 
>>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>> 
>>>> As we are going to add support for the Allwinner DE2 Mixer in 
>>>> sun4i-drm
>>>> driver, we will finally have two types of layer.
>>>> 
>>>> Abstract the layer type to void * and a ops struct, which contains 
>>>> the
>>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>> 
>>>> Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
>>>> ---
>>>> Refactored patch in v3.
>>>> 
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> 
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> index 3c876c3a356a..33854ee7f636 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> @@ -29,6 +29,7 @@
>>>>  #include "sun4i_crtc.h"
>>>>  #include "sun4i_drv.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>>  #include "sun4i_tcon.h"
>>>> 
>>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct 
>>>> drm_device
>>>> *drm,
>>>>         scrtc->tcon = tcon;
>>>> 
>>>>         /* Create our layers */
>>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>>         if (IS_ERR(scrtc->layers)) {
>>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>>                 return NULL;
>>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>> 
>>>>         /* find primary and cursor planes for 
>>>> drm_crtc_init_with_planes
>>>> */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               switch (layer->plane.type) {
>>>> +               switch (plane->type) {
>>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>>> -                       primary = &layer->plane;
>>>> +                       primary = plane;
>>>>                         break;
>>>>                 case DRM_PLANE_TYPE_CURSOR:
>>>> -                       cursor = &layer->plane;
>>>> +                       cursor = plane;
>>>>                         break;
>>>>                 default:
>>>>                         break;
>>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>>                 uint32_t possible_crtcs =
>>>> BIT(drm_crtc_index(&scrtc->crtc));
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>>> -                       layer->plane.possible_crtcs = 
>>>> possible_crtcs;
>>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>>> +                       plane->possible_crtcs = possible_crtcs;
>>>>         }
>>>> 
>>>>         return scrtc;
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> index 230cb8f0d601..a4036ee44cf8 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>> 
>>>>         struct sun4i_backend            *backend;
>>>>         struct sun4i_tcon               *tcon;
>>>> -       struct sun4i_layer              **layers;
>>>> +       void                            **layers;
>>>> +       const struct sunxi_layer_ops    *layer_ops;
>>> 
>>> 
>>> I think you should probably take a different approach to abstract the
>>> layer
>>> type. How about creating
>>> 
>>> struct sunxi_layer {
>>>         struct drm_plane plane;
>>> }
>>> 
>>> base and then subclassing that for sun4i and sun8i? By doing this you 
>>> can
>>> avoid
>>> the nasty casting and you can also get rid of the get_plane() hook 
>>> and
>>> layer_ops.
>> 
>> 
>> For the situation that using ** things are easily to get weird.
> 
> That code could be reworked, by initializing the layers directly within
> the crtc init code. If you look at rockchip's drm driver, you'll see
> they do this. There is a good reason to do it this way, as you need
> to first create the primary and cursor layers, pass them in when you
> create the crtc, then initialize any additional layers with the
> possible_crtcs bitmap.

I feel that it's still more proper to offload plane creation code
to *_layers_init function, as:

1. We cannot assume the cursor layer's
existance. In fact currently no code in sun4i-drm (including this
patchset) create a cursor layer.

2. The format of planes heavily depend on the engine type (
sun4i-backend or sun8i-mixer).

3. We should create planes according to the type of engine.
Currently the *_layers_init function is part of engine code (See my
Makefile change).

4. If we do so we will have two codes for plane creating -- one for
primary in sun4i_crtc_init, another for overlays in *_layers_init.

> 
> In our driver we are currently initializing all layers, then going
> back and filling in possible_crtcs for the extra layers.
> 
> And as Maxime and I mentioned in the other thread, we don't really
> need to keep a reference to **layers.

It's correct, layers doesn't need to be kept.

And the struct sunxi_layer refactor also makes sense.

> 
> Regards
> ChenYu
> 
>> 
>>> 
>>> Sean
>>> 
>>> 
>>> 
>>>>  };
>>>> 
>>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct 
>>>> drm_crtc
>>>> *crtc)
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> index f26bde5b9117..bc4a70d6968b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> @@ -16,7 +16,9 @@
>>>>  #include <drm/drmP.h>
>>>> 
>>>>  #include "sun4i_backend.h"
>>>> +#include "sun4i_crtc.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>> 
>>>>  struct sun4i_plane_desc {
>>>>                enum drm_plane_type     type;
>>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>>> sun4i_backend_planes[] = {
>>>>         },
>>>>  };
>>>> 
>>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>>> +{
>>>> +       struct sun4i_layer *sun4i_layer = layer;
>>>> +
>>>> +       return &sun4i_layer->plane;
>>>> +}
>>>> +
>>>> +static const struct sunxi_layer_ops layer_ops = {
>>>> +       .get_plane = sun4i_layer_get_plane,
>>>> +};
>>>> +
>>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device 
>>>> *drm,
>>>>                                                 struct sun4i_backend
>>>> *backend,
>>>>                                                 const struct
>>>> sun4i_plane_desc *plane)
>>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend)
>>>> +                                      struct sun4i_crtc *crtc)
>>>>  {
>>>>         struct sun4i_layer **layers;
>>>> +       struct sun4i_backend *backend = crtc->backend;
>>>>         int i;
>>>> 
>>>>         layers = devm_kcalloc(drm->dev, 
>>>> ARRAY_SIZE(sun4i_backend_planes)
>>>> + 1,
>>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>>> drm_device *drm,
>>>>                 layers[i] = layer;
>>>>         };
>>>> 
>>>> +       /* Assign layer ops to the CRTC */
>>>> +       crtc->layer_ops = &layer_ops;
>>>> +
>>>>         return layers;
>>>>  }
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> index 4be1f0919df2..425eea7b9e3b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend);
>>>> +                                      struct sun4i_crtc *crtc);
>>>> 
>>>>  #endif /* _SUN4I_LAYER_H_ */
>>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> new file mode 100644
>>>> index 000000000000..d8838ec39299
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> @@ -0,0 +1,17 @@
>>>> +/*
>>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU General Public License as
>>>> + * published by the Free Software Foundation; either version 2 of
>>>> + * the License, or (at your option) any later version.
>>>> + */
>>>> +
>>>> +#ifndef _SUNXI_LAYER_H_
>>>> +#define _SUNXI_LAYER_H_
>>>> +
>>>> +struct sunxi_layer_ops {
>>>> +       struct drm_plane *(*get_plane)(void *layer);
>>>> +};
>>>> +
>>>> +#endif /* _SUNXI_LAYER_H_ */
>>>> --
>>>> 2.12.0
>>>> 
>>>> 
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>> 
>>> 
>> 
>> --
>> You received this message because you are subscribed to the Google 
>> Groups
>> "linux-sunxi" group.
>> To unsubscribe from this group and stop receiving emails from it, send 
>> an
>> email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
>> For more options, visit https://groups.google.com/d/optout.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05 17:14           ` icenowy-h8G6r0blFSE
  0 siblings, 0 replies; 82+ messages in thread
From: icenowy @ 2017-04-05 17:14 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: devicetree, Jernej Skrabec, linux-kernel, dri-devel, linux-sunxi,
	Rob Herring, Sean Paul, Maxime Ripard, linux-clk,
	linux-arm-kernel

5ZyoIDIwMTctMDQtMDUgMTA6MjfvvIxDaGVuLVl1IFRzYWkg5YaZ6YGT77yaCj4gT24gV2VkLCBB
cHIgNSwgMjAxNyBhdCAzOjUzIEFNLCBJY2Vub3d5IFpoZW5nIDxpY2Vub3d5QGFvc2MuaW8+IHdy
b3RlOgo+PiAKPj4gCj4+IOWcqCAyMDE35bm0MDTmnIgwNeaXpSAwMzoyOCwgU2VhbiBQYXVsIOWG
memBkzoKPj4+IAo+Pj4gT24gVGh1LCBNYXIgMzAsIDIwMTcgYXQgMDM6NDY6MDZBTSArMDgwMCwg
SWNlbm93eSBaaGVuZyB3cm90ZToKPj4+PiAKPj4+PiBBcyB3ZSBhcmUgZ29pbmcgdG8gYWRkIHN1
cHBvcnQgZm9yIHRoZSBBbGx3aW5uZXIgREUyIE1peGVyIGluIAo+Pj4+IHN1bjRpLWRybQo+Pj4+
IGRyaXZlciwgd2Ugd2lsbCBmaW5hbGx5IGhhdmUgdHdvIHR5cGVzIG9mIGxheWVyLgo+Pj4+IAo+
Pj4+IEFic3RyYWN0IHRoZSBsYXllciB0eXBlIHRvIHZvaWQgKiBhbmQgYSBvcHMgc3RydWN0LCB3
aGljaCBjb250YWlucyAKPj4+PiB0aGUKPj4+PiBvbmx5IGZ1bmN0aW9uIHVzZWQgYnkgY3J0YyAt
LSBnZXQgdGhlIGRybV9wbGFuZSBzdHJ1Y3Qgb2YgdGhlIGxheWVyLgo+Pj4+IAo+Pj4+IFNpZ25l
ZC1vZmYtYnk6IEljZW5vd3kgWmhlbmcgPGljZW5vd3lAYW9zYy5pbz4KPj4+PiAtLS0KPj4+PiBS
ZWZhY3RvcmVkIHBhdGNoIGluIHYzLgo+Pj4+IAo+Pj4+ICBkcml2ZXJzL2dwdS9kcm0vc3VuNGkv
c3VuNGlfY3J0Yy5jICB8IDE5ICsrKysrKysrKysrLS0tLS0tLS0KPj4+PiAgZHJpdmVycy9ncHUv
ZHJtL3N1bjRpL3N1bjRpX2NydGMuaCAgfCAgMyArKy0KPj4+PiAgZHJpdmVycy9ncHUvZHJtL3N1
bjRpL3N1bjRpX2xheWVyLmMgfCAxOSArKysrKysrKysrKysrKysrKystCj4+Pj4gIGRyaXZlcnMv
Z3B1L2RybS9zdW40aS9zdW40aV9sYXllci5oIHwgIDIgKy0KPj4+PiAgZHJpdmVycy9ncHUvZHJt
L3N1bjRpL3N1bnhpX2xheWVyLmggfCAxNyArKysrKysrKysrKysrKysrKwo+Pj4+ICA1IGZpbGVz
IGNoYW5nZWQsIDQ5IGluc2VydGlvbnMoKyksIDExIGRlbGV0aW9ucygtKQo+Pj4+ICBjcmVhdGUg
bW9kZSAxMDA2NDQgZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bnhpX2xheWVyLmgKPj4+PiAKPj4+
PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuYwo+Pj4+IGIv
ZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuYwo+Pj4+IGluZGV4IDNjODc2YzNhMzU2
YS4uMzM4NTRlZTdmNjM2IDEwMDY0NAo+Pj4+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9zdW40aS9z
dW40aV9jcnRjLmMKPj4+PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfY3J0Yy5j
Cj4+Pj4gQEAgLTI5LDYgKzI5LDcgQEAKPj4+PiAgI2luY2x1ZGUgInN1bjRpX2NydGMuaCIKPj4+
PiAgI2luY2x1ZGUgInN1bjRpX2Rydi5oIgo+Pj4+ICAjaW5jbHVkZSAic3VuNGlfbGF5ZXIuaCIK
Pj4+PiArI2luY2x1ZGUgInN1bnhpX2xheWVyLmgiCj4+Pj4gICNpbmNsdWRlICJzdW40aV90Y29u
LmgiCj4+Pj4gCj4+Pj4gIHN0YXRpYyB2b2lkIHN1bjRpX2NydGNfYXRvbWljX2JlZ2luKHN0cnVj
dCBkcm1fY3J0YyAqY3J0YywKPj4+PiBAQCAtMTQ5LDcgKzE1MCw3IEBAIHN0cnVjdCBzdW40aV9j
cnRjICpzdW40aV9jcnRjX2luaXQoc3RydWN0IAo+Pj4+IGRybV9kZXZpY2UKPj4+PiAqZHJtLAo+
Pj4+ICAgICAgICAgc2NydGMtPnRjb24gPSB0Y29uOwo+Pj4+IAo+Pj4+ICAgICAgICAgLyogQ3Jl
YXRlIG91ciBsYXllcnMgKi8KPj4+PiAtICAgICAgIHNjcnRjLT5sYXllcnMgPSBzdW40aV9sYXll
cnNfaW5pdChkcm0sIHNjcnRjLT5iYWNrZW5kKTsKPj4+PiArICAgICAgIHNjcnRjLT5sYXllcnMg
PSAodm9pZCAqKilzdW40aV9sYXllcnNfaW5pdChkcm0sIHNjcnRjKTsKPj4+PiAgICAgICAgIGlm
IChJU19FUlIoc2NydGMtPmxheWVycykpIHsKPj4+PiAgICAgICAgICAgICAgICAgZGV2X2Vycihk
cm0tPmRldiwgIkNvdWxkbid0IGNyZWF0ZSB0aGUgcGxhbmVzXG4iKTsKPj4+PiAgICAgICAgICAg
ICAgICAgcmV0dXJuIE5VTEw7Cj4+Pj4gQEAgLTE1NywxNCArMTU4LDE1IEBAIHN0cnVjdCBzdW40
aV9jcnRjICpzdW40aV9jcnRjX2luaXQoc3RydWN0Cj4+Pj4gZHJtX2RldmljZSAqZHJtLAo+Pj4+
IAo+Pj4+ICAgICAgICAgLyogZmluZCBwcmltYXJ5IGFuZCBjdXJzb3IgcGxhbmVzIGZvciAKPj4+
PiBkcm1fY3J0Y19pbml0X3dpdGhfcGxhbmVzCj4+Pj4gKi8KPj4+PiAgICAgICAgIGZvciAoaSA9
IDA7IHNjcnRjLT5sYXllcnNbaV07IGkrKykgewo+Pj4+IC0gICAgICAgICAgICAgICBzdHJ1Y3Qg
c3VuNGlfbGF5ZXIgKmxheWVyID0gc2NydGMtPmxheWVyc1tpXTsKPj4+PiArICAgICAgICAgICAg
ICAgdm9pZCAqbGF5ZXIgPSBzY3J0Yy0+bGF5ZXJzW2ldOwo+Pj4+ICsgICAgICAgICAgICAgICBz
dHJ1Y3QgZHJtX3BsYW5lICpwbGFuZSA9Cj4+Pj4gc2NydGMtPmxheWVyX29wcy0+Z2V0X3BsYW5l
KGxheWVyKTsKPj4+PiAKPj4+PiAtICAgICAgICAgICAgICAgc3dpdGNoIChsYXllci0+cGxhbmUu
dHlwZSkgewo+Pj4+ICsgICAgICAgICAgICAgICBzd2l0Y2ggKHBsYW5lLT50eXBlKSB7Cj4+Pj4g
ICAgICAgICAgICAgICAgIGNhc2UgRFJNX1BMQU5FX1RZUEVfUFJJTUFSWToKPj4+PiAtICAgICAg
ICAgICAgICAgICAgICAgICBwcmltYXJ5ID0gJmxheWVyLT5wbGFuZTsKPj4+PiArICAgICAgICAg
ICAgICAgICAgICAgICBwcmltYXJ5ID0gcGxhbmU7Cj4+Pj4gICAgICAgICAgICAgICAgICAgICAg
ICAgYnJlYWs7Cj4+Pj4gICAgICAgICAgICAgICAgIGNhc2UgRFJNX1BMQU5FX1RZUEVfQ1VSU09S
Ogo+Pj4+IC0gICAgICAgICAgICAgICAgICAgICAgIGN1cnNvciA9ICZsYXllci0+cGxhbmU7Cj4+
Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgY3Vyc29yID0gcGxhbmU7Cj4+Pj4gICAgICAgICAg
ICAgICAgICAgICAgICAgYnJlYWs7Cj4+Pj4gICAgICAgICAgICAgICAgIGRlZmF1bHQ6Cj4+Pj4g
ICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4+Pj4gQEAgLTE5MCwxMCArMTkyLDExIEBA
IHN0cnVjdCBzdW40aV9jcnRjICpzdW40aV9jcnRjX2luaXQoc3RydWN0Cj4+Pj4gZHJtX2Rldmlj
ZSAqZHJtLAo+Pj4+ICAgICAgICAgLyogU2V0IHBvc3NpYmxlX2NydGNzIHRvIHRoaXMgY3J0YyBm
b3Igb3ZlcmxheSBwbGFuZXMgKi8KPj4+PiAgICAgICAgIGZvciAoaSA9IDA7IHNjcnRjLT5sYXll
cnNbaV07IGkrKykgewo+Pj4+ICAgICAgICAgICAgICAgICB1aW50MzJfdCBwb3NzaWJsZV9jcnRj
cyA9Cj4+Pj4gQklUKGRybV9jcnRjX2luZGV4KCZzY3J0Yy0+Y3J0YykpOwo+Pj4+IC0gICAgICAg
ICAgICAgICBzdHJ1Y3Qgc3VuNGlfbGF5ZXIgKmxheWVyID0gc2NydGMtPmxheWVyc1tpXTsKPj4+
PiArICAgICAgICAgICAgICAgdm9pZCAqbGF5ZXIgPSBzY3J0Yy0+bGF5ZXJzW2ldOwo+Pj4+ICsg
ICAgICAgICAgICAgICBzdHJ1Y3QgZHJtX3BsYW5lICpwbGFuZSA9Cj4+Pj4gc2NydGMtPmxheWVy
X29wcy0+Z2V0X3BsYW5lKGxheWVyKTsKPj4+PiAKPj4+PiAtICAgICAgICAgICAgICAgaWYgKGxh
eWVyLT5wbGFuZS50eXBlID09IERSTV9QTEFORV9UWVBFX09WRVJMQVkpCj4+Pj4gLSAgICAgICAg
ICAgICAgICAgICAgICAgbGF5ZXItPnBsYW5lLnBvc3NpYmxlX2NydGNzID0gCj4+Pj4gcG9zc2li
bGVfY3J0Y3M7Cj4+Pj4gKyAgICAgICAgICAgICAgIGlmIChwbGFuZS0+dHlwZSA9PSBEUk1fUExB
TkVfVFlQRV9PVkVSTEFZKQo+Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgIHBsYW5lLT5wb3Nz
aWJsZV9jcnRjcyA9IHBvc3NpYmxlX2NydGNzOwo+Pj4+ICAgICAgICAgfQo+Pj4+IAo+Pj4+ICAg
ICAgICAgcmV0dXJuIHNjcnRjOwo+Pj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vc3Vu
NGkvc3VuNGlfY3J0Yy5oCj4+Pj4gYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfY3J0Yy5o
Cj4+Pj4gaW5kZXggMjMwY2I4ZjBkNjAxLi5hNDAzNmVlNDRjZjggMTAwNjQ0Cj4+Pj4gLS0tIGEv
ZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2NydGMuaAo+Pj4+ICsrKyBiL2RyaXZlcnMvZ3B1
L2RybS9zdW40aS9zdW40aV9jcnRjLmgKPj4+PiBAQCAtMTksNyArMTksOCBAQCBzdHJ1Y3Qgc3Vu
NGlfY3J0YyB7Cj4+Pj4gCj4+Pj4gICAgICAgICBzdHJ1Y3Qgc3VuNGlfYmFja2VuZCAgICAgICAg
ICAgICpiYWNrZW5kOwo+Pj4+ICAgICAgICAgc3RydWN0IHN1bjRpX3Rjb24gICAgICAgICAgICAg
ICAqdGNvbjsKPj4+PiAtICAgICAgIHN0cnVjdCBzdW40aV9sYXllciAgICAgICAgICAgICAgKips
YXllcnM7Cj4+Pj4gKyAgICAgICB2b2lkICAgICAgICAgICAgICAgICAgICAgICAgICAgICoqbGF5
ZXJzOwo+Pj4+ICsgICAgICAgY29uc3Qgc3RydWN0IHN1bnhpX2xheWVyX29wcyAgICAqbGF5ZXJf
b3BzOwo+Pj4gCj4+PiAKPj4+IEkgdGhpbmsgeW91IHNob3VsZCBwcm9iYWJseSB0YWtlIGEgZGlm
ZmVyZW50IGFwcHJvYWNoIHRvIGFic3RyYWN0IHRoZQo+Pj4gbGF5ZXIKPj4+IHR5cGUuIEhvdyBh
Ym91dCBjcmVhdGluZwo+Pj4gCj4+PiBzdHJ1Y3Qgc3VueGlfbGF5ZXIgewo+Pj4gICAgICAgICBz
dHJ1Y3QgZHJtX3BsYW5lIHBsYW5lOwo+Pj4gfQo+Pj4gCj4+PiBiYXNlIGFuZCB0aGVuIHN1YmNs
YXNzaW5nIHRoYXQgZm9yIHN1bjRpIGFuZCBzdW44aT8gQnkgZG9pbmcgdGhpcyB5b3UgCj4+PiBj
YW4KPj4+IGF2b2lkCj4+PiB0aGUgbmFzdHkgY2FzdGluZyBhbmQgeW91IGNhbiBhbHNvIGdldCBy
aWQgb2YgdGhlIGdldF9wbGFuZSgpIGhvb2sgCj4+PiBhbmQKPj4+IGxheWVyX29wcy4KPj4gCj4+
IAo+PiBGb3IgdGhlIHNpdHVhdGlvbiB0aGF0IHVzaW5nICoqIHRoaW5ncyBhcmUgZWFzaWx5IHRv
IGdldCB3ZWlyZC4KPiAKPiBUaGF0IGNvZGUgY291bGQgYmUgcmV3b3JrZWQsIGJ5IGluaXRpYWxp
emluZyB0aGUgbGF5ZXJzIGRpcmVjdGx5IHdpdGhpbgo+IHRoZSBjcnRjIGluaXQgY29kZS4gSWYg
eW91IGxvb2sgYXQgcm9ja2NoaXAncyBkcm0gZHJpdmVyLCB5b3UnbGwgc2VlCj4gdGhleSBkbyB0
aGlzLiBUaGVyZSBpcyBhIGdvb2QgcmVhc29uIHRvIGRvIGl0IHRoaXMgd2F5LCBhcyB5b3UgbmVl
ZAo+IHRvIGZpcnN0IGNyZWF0ZSB0aGUgcHJpbWFyeSBhbmQgY3Vyc29yIGxheWVycywgcGFzcyB0
aGVtIGluIHdoZW4geW91Cj4gY3JlYXRlIHRoZSBjcnRjLCB0aGVuIGluaXRpYWxpemUgYW55IGFk
ZGl0aW9uYWwgbGF5ZXJzIHdpdGggdGhlCj4gcG9zc2libGVfY3J0Y3MgYml0bWFwLgoKSSBmZWVs
IHRoYXQgaXQncyBzdGlsbCBtb3JlIHByb3BlciB0byBvZmZsb2FkIHBsYW5lIGNyZWF0aW9uIGNv
ZGUKdG8gKl9sYXllcnNfaW5pdCBmdW5jdGlvbiwgYXM6CgoxLiBXZSBjYW5ub3QgYXNzdW1lIHRo
ZSBjdXJzb3IgbGF5ZXIncwpleGlzdGFuY2UuIEluIGZhY3QgY3VycmVudGx5IG5vIGNvZGUgaW4g
c3VuNGktZHJtIChpbmNsdWRpbmcgdGhpcwpwYXRjaHNldCkgY3JlYXRlIGEgY3Vyc29yIGxheWVy
LgoKMi4gVGhlIGZvcm1hdCBvZiBwbGFuZXMgaGVhdmlseSBkZXBlbmQgb24gdGhlIGVuZ2luZSB0
eXBlICgKc3VuNGktYmFja2VuZCBvciBzdW44aS1taXhlcikuCgozLiBXZSBzaG91bGQgY3JlYXRl
IHBsYW5lcyBhY2NvcmRpbmcgdG8gdGhlIHR5cGUgb2YgZW5naW5lLgpDdXJyZW50bHkgdGhlICpf
bGF5ZXJzX2luaXQgZnVuY3Rpb24gaXMgcGFydCBvZiBlbmdpbmUgY29kZSAoU2VlIG15Ck1ha2Vm
aWxlIGNoYW5nZSkuCgo0LiBJZiB3ZSBkbyBzbyB3ZSB3aWxsIGhhdmUgdHdvIGNvZGVzIGZvciBw
bGFuZSBjcmVhdGluZyAtLSBvbmUgZm9yCnByaW1hcnkgaW4gc3VuNGlfY3J0Y19pbml0LCBhbm90
aGVyIGZvciBvdmVybGF5cyBpbiAqX2xheWVyc19pbml0LgoKPiAKPiBJbiBvdXIgZHJpdmVyIHdl
IGFyZSBjdXJyZW50bHkgaW5pdGlhbGl6aW5nIGFsbCBsYXllcnMsIHRoZW4gZ29pbmcKPiBiYWNr
IGFuZCBmaWxsaW5nIGluIHBvc3NpYmxlX2NydGNzIGZvciB0aGUgZXh0cmEgbGF5ZXJzLgo+IAo+
IEFuZCBhcyBNYXhpbWUgYW5kIEkgbWVudGlvbmVkIGluIHRoZSBvdGhlciB0aHJlYWQsIHdlIGRv
bid0IHJlYWxseQo+IG5lZWQgdG8ga2VlcCBhIHJlZmVyZW5jZSB0byAqKmxheWVycy4KCkl0J3Mg
Y29ycmVjdCwgbGF5ZXJzIGRvZXNuJ3QgbmVlZCB0byBiZSBrZXB0LgoKQW5kIHRoZSBzdHJ1Y3Qg
c3VueGlfbGF5ZXIgcmVmYWN0b3IgYWxzbyBtYWtlcyBzZW5zZS4KCj4gCj4gUmVnYXJkcwo+IENo
ZW5ZdQo+IAo+PiAKPj4+IAo+Pj4gU2Vhbgo+Pj4gCj4+PiAKPj4+IAo+Pj4+ICB9Owo+Pj4+IAo+
Pj4+ICBzdGF0aWMgaW5saW5lIHN0cnVjdCBzdW40aV9jcnRjICpkcm1fY3J0Y190b19zdW40aV9j
cnRjKHN0cnVjdCAKPj4+PiBkcm1fY3J0Ywo+Pj4+ICpjcnRjKQo+Pj4+IGRpZmYgLS1naXQgYS9k
cml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5ZXIuYwo+Pj4+IGIvZHJpdmVycy9ncHUvZHJt
L3N1bjRpL3N1bjRpX2xheWVyLmMKPj4+PiBpbmRleCBmMjZiZGU1YjkxMTcuLmJjNGE3MGQ2OTY4
YiAxMDA2NDQKPj4+PiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5ZXIuYwo+
Pj4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9sYXllci5jCj4+Pj4gQEAgLTE2
LDcgKzE2LDkgQEAKPj4+PiAgI2luY2x1ZGUgPGRybS9kcm1QLmg+Cj4+Pj4gCj4+Pj4gICNpbmNs
dWRlICJzdW40aV9iYWNrZW5kLmgiCj4+Pj4gKyNpbmNsdWRlICJzdW40aV9jcnRjLmgiCj4+Pj4g
ICNpbmNsdWRlICJzdW40aV9sYXllci5oIgo+Pj4+ICsjaW5jbHVkZSAic3VueGlfbGF5ZXIuaCIK
Pj4+PiAKPj4+PiAgc3RydWN0IHN1bjRpX3BsYW5lX2Rlc2Mgewo+Pj4+ICAgICAgICAgICAgICAg
IGVudW0gZHJtX3BsYW5lX3R5cGUgICAgIHR5cGU7Cj4+Pj4gQEAgLTEwMCw2ICsxMDIsMTcgQEAg
c3RhdGljIGNvbnN0IHN0cnVjdCBzdW40aV9wbGFuZV9kZXNjCj4+Pj4gc3VuNGlfYmFja2VuZF9w
bGFuZXNbXSA9IHsKPj4+PiAgICAgICAgIH0sCj4+Pj4gIH07Cj4+Pj4gCj4+Pj4gK3N0YXRpYyBz
dHJ1Y3QgZHJtX3BsYW5lICpzdW40aV9sYXllcl9nZXRfcGxhbmUodm9pZCAqbGF5ZXIpCj4+Pj4g
K3sKPj4+PiArICAgICAgIHN0cnVjdCBzdW40aV9sYXllciAqc3VuNGlfbGF5ZXIgPSBsYXllcjsK
Pj4+PiArCj4+Pj4gKyAgICAgICByZXR1cm4gJnN1bjRpX2xheWVyLT5wbGFuZTsKPj4+PiArfQo+
Pj4+ICsKPj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBzdW54aV9sYXllcl9vcHMgbGF5ZXJfb3Bz
ID0gewo+Pj4+ICsgICAgICAgLmdldF9wbGFuZSA9IHN1bjRpX2xheWVyX2dldF9wbGFuZSwKPj4+
PiArfTsKPj4+PiArCj4+Pj4gIHN0YXRpYyBzdHJ1Y3Qgc3VuNGlfbGF5ZXIgKnN1bjRpX2xheWVy
X2luaXRfb25lKHN0cnVjdCBkcm1fZGV2aWNlIAo+Pj4+ICpkcm0sCj4+Pj4gICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHN1bjRpX2JhY2tlbmQK
Pj4+PiAqYmFja2VuZCwKPj4+PiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICBjb25zdCBzdHJ1Y3QKPj4+PiBzdW40aV9wbGFuZV9kZXNjICpwbGFuZSkKPj4+
PiBAQCAtMTI5LDkgKzE0MiwxMCBAQCBzdGF0aWMgc3RydWN0IHN1bjRpX2xheWVyCj4+Pj4gKnN1
bjRpX2xheWVyX2luaXRfb25lKHN0cnVjdCBkcm1fZGV2aWNlICpkcm0sCj4+Pj4gIH0KPj4+PiAK
Pj4+PiAgc3RydWN0IHN1bjRpX2xheWVyICoqc3VuNGlfbGF5ZXJzX2luaXQoc3RydWN0IGRybV9k
ZXZpY2UgKmRybSwKPj4+PiAtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBz
dHJ1Y3Qgc3VuNGlfYmFja2VuZCAKPj4+PiAqYmFja2VuZCkKPj4+PiArICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgc3VuNGlfY3J0YyAqY3J0YykKPj4+PiAgewo+
Pj4+ICAgICAgICAgc3RydWN0IHN1bjRpX2xheWVyICoqbGF5ZXJzOwo+Pj4+ICsgICAgICAgc3Ry
dWN0IHN1bjRpX2JhY2tlbmQgKmJhY2tlbmQgPSBjcnRjLT5iYWNrZW5kOwo+Pj4+ICAgICAgICAg
aW50IGk7Cj4+Pj4gCj4+Pj4gICAgICAgICBsYXllcnMgPSBkZXZtX2tjYWxsb2MoZHJtLT5kZXYs
IAo+Pj4+IEFSUkFZX1NJWkUoc3VuNGlfYmFja2VuZF9wbGFuZXMpCj4+Pj4gKyAxLAo+Pj4+IEBA
IC0xODEsNSArMTk1LDggQEAgc3RydWN0IHN1bjRpX2xheWVyICoqc3VuNGlfbGF5ZXJzX2luaXQo
c3RydWN0Cj4+Pj4gZHJtX2RldmljZSAqZHJtLAo+Pj4+ICAgICAgICAgICAgICAgICBsYXllcnNb
aV0gPSBsYXllcjsKPj4+PiAgICAgICAgIH07Cj4+Pj4gCj4+Pj4gKyAgICAgICAvKiBBc3NpZ24g
bGF5ZXIgb3BzIHRvIHRoZSBDUlRDICovCj4+Pj4gKyAgICAgICBjcnRjLT5sYXllcl9vcHMgPSAm
bGF5ZXJfb3BzOwo+Pj4+ICsKPj4+PiAgICAgICAgIHJldHVybiBsYXllcnM7Cj4+Pj4gIH0KPj4+
PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bjRpX2xheWVyLmgKPj4+PiBi
L2RyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW40aV9sYXllci5oCj4+Pj4gaW5kZXggNGJlMWYwOTE5
ZGYyLi40MjVlZWE3YjllM2IgMTAwNjQ0Cj4+Pj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3N1bjRp
L3N1bjRpX2xheWVyLmgKPj4+PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VuNGlfbGF5
ZXIuaAo+Pj4+IEBAIC0yNyw2ICsyNyw2IEBAIHBsYW5lX3RvX3N1bjRpX2xheWVyKHN0cnVjdCBk
cm1fcGxhbmUgKnBsYW5lKQo+Pj4+ICB9Cj4+Pj4gCj4+Pj4gIHN0cnVjdCBzdW40aV9sYXllciAq
KnN1bjRpX2xheWVyc19pbml0KHN0cnVjdCBkcm1fZGV2aWNlICpkcm0sCj4+Pj4gLSAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHN1bjRpX2JhY2tlbmQgCj4+Pj4g
KmJhY2tlbmQpOwo+Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0
cnVjdCBzdW40aV9jcnRjICpjcnRjKTsKPj4+PiAKPj4+PiAgI2VuZGlmIC8qIF9TVU40SV9MQVlF
Ul9IXyAqLwo+Pj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vc3VuNGkvc3VueGlfbGF5
ZXIuaAo+Pj4+IGIvZHJpdmVycy9ncHUvZHJtL3N1bjRpL3N1bnhpX2xheWVyLmgKPj4+PiBuZXcg
ZmlsZSBtb2RlIDEwMDY0NAo+Pj4+IGluZGV4IDAwMDAwMDAwMDAwMC4uZDg4MzhlYzM5Mjk5Cj4+
Pj4gLS0tIC9kZXYvbnVsbAo+Pj4+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9zdW40aS9zdW54aV9s
YXllci5oCj4+Pj4gQEAgLTAsMCArMSwxNyBAQAo+Pj4+ICsvKgo+Pj4+ICsgKiBDb3B5cmlnaHQg
KEMpIDIwMTcgSWNlbm93eSBaaGVuZyA8aWNlbm93eUBhb3NjLnh5ej4KPj4+PiArICoKPj4+PiAr
ICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0
IGFuZC9vcgo+Pj4+ICsgKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2Vu
ZXJhbCBQdWJsaWMgTGljZW5zZSBhcwo+Pj4+ICsgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29m
dHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiBvZgo+Pj4+ICsgKiB0aGUgTGljZW5z
ZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KPj4+PiArICovCj4+Pj4g
Kwo+Pj4+ICsjaWZuZGVmIF9TVU5YSV9MQVlFUl9IXwo+Pj4+ICsjZGVmaW5lIF9TVU5YSV9MQVlF
Ul9IXwo+Pj4+ICsKPj4+PiArc3RydWN0IHN1bnhpX2xheWVyX29wcyB7Cj4+Pj4gKyAgICAgICBz
dHJ1Y3QgZHJtX3BsYW5lICooKmdldF9wbGFuZSkodm9pZCAqbGF5ZXIpOwo+Pj4+ICt9Owo+Pj4+
ICsKPj4+PiArI2VuZGlmIC8qIF9TVU5YSV9MQVlFUl9IXyAqLwo+Pj4+IC0tCj4+Pj4gMi4xMi4w
Cj4+Pj4gCj4+Pj4gCj4+Pj4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX18KPj4+PiBsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdAo+Pj4+IGxpbnV4LWFy
bS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwo+Pj4+IGh0dHA6Ly9saXN0cy5pbmZyYWRlYWQu
b3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo+Pj4gCj4+PiAKPj4gCj4+IC0t
Cj4+IFlvdSByZWNlaXZlZCB0aGlzIG1lc3NhZ2UgYmVjYXVzZSB5b3UgYXJlIHN1YnNjcmliZWQg
dG8gdGhlIEdvb2dsZSAKPj4gR3JvdXBzCj4+ICJsaW51eC1zdW54aSIgZ3JvdXAuCj4+IFRvIHVu
c3Vic2NyaWJlIGZyb20gdGhpcyBncm91cCBhbmQgc3RvcCByZWNlaXZpbmcgZW1haWxzIGZyb20g
aXQsIHNlbmQgCj4+IGFuCj4+IGVtYWlsIHRvIGxpbnV4LXN1bnhpK3Vuc3Vic2NyaWJlQGdvb2ds
ZWdyb3Vwcy5jb20uCj4+IEZvciBtb3JlIG9wdGlvbnMsIHZpc2l0IGh0dHBzOi8vZ3JvdXBzLmdv
b2dsZS5jb20vZC9vcHRvdXQuCj4gCj4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX18KPiBsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdAo+IGxpbnV4LWFy
bS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwo+IGh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3Jn
L21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAoKX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QK
bGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRl
YWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=

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

* [linux-sunxi] Re: [PATCH v3 04/11] drm/sun4i: abstract the layer type
@ 2017-04-05 17:14           ` icenowy-h8G6r0blFSE
  0 siblings, 0 replies; 82+ messages in thread
From: icenowy at aosc.io @ 2017-04-05 17:14 UTC (permalink / raw)
  To: linux-arm-kernel

? 2017-04-05 10:27?Chen-Yu Tsai ???
> On Wed, Apr 5, 2017 at 3:53 AM, Icenowy Zheng <icenowy@aosc.io> wrote:
>> 
>> 
>> ? 2017?04?05? 03:28, Sean Paul ??:
>>> 
>>> On Thu, Mar 30, 2017 at 03:46:06AM +0800, Icenowy Zheng wrote:
>>>> 
>>>> As we are going to add support for the Allwinner DE2 Mixer in 
>>>> sun4i-drm
>>>> driver, we will finally have two types of layer.
>>>> 
>>>> Abstract the layer type to void * and a ops struct, which contains 
>>>> the
>>>> only function used by crtc -- get the drm_plane struct of the layer.
>>>> 
>>>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>>> ---
>>>> Refactored patch in v3.
>>>> 
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.c  | 19 +++++++++++--------
>>>>  drivers/gpu/drm/sun4i/sun4i_crtc.h  |  3 ++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
>>>>  drivers/gpu/drm/sun4i/sun4i_layer.h |  2 +-
>>>>  drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
>>>>  5 files changed, 49 insertions(+), 11 deletions(-)
>>>>  create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> 
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> index 3c876c3a356a..33854ee7f636 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
>>>> @@ -29,6 +29,7 @@
>>>>  #include "sun4i_crtc.h"
>>>>  #include "sun4i_drv.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>>  #include "sun4i_tcon.h"
>>>> 
>>>>  static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
>>>> @@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct 
>>>> drm_device
>>>> *drm,
>>>>         scrtc->tcon = tcon;
>>>> 
>>>>         /* Create our layers */
>>>> -       scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
>>>> +       scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
>>>>         if (IS_ERR(scrtc->layers)) {
>>>>                 dev_err(drm->dev, "Couldn't create the planes\n");
>>>>                 return NULL;
>>>> @@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>> 
>>>>         /* find primary and cursor planes for 
>>>> drm_crtc_init_with_planes
>>>> */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               switch (layer->plane.type) {
>>>> +               switch (plane->type) {
>>>>                 case DRM_PLANE_TYPE_PRIMARY:
>>>> -                       primary = &layer->plane;
>>>> +                       primary = plane;
>>>>                         break;
>>>>                 case DRM_PLANE_TYPE_CURSOR:
>>>> -                       cursor = &layer->plane;
>>>> +                       cursor = plane;
>>>>                         break;
>>>>                 default:
>>>>                         break;
>>>> @@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct
>>>> drm_device *drm,
>>>>         /* Set possible_crtcs to this crtc for overlay planes */
>>>>         for (i = 0; scrtc->layers[i]; i++) {
>>>>                 uint32_t possible_crtcs =
>>>> BIT(drm_crtc_index(&scrtc->crtc));
>>>> -               struct sun4i_layer *layer = scrtc->layers[i];
>>>> +               void *layer = scrtc->layers[i];
>>>> +               struct drm_plane *plane =
>>>> scrtc->layer_ops->get_plane(layer);
>>>> 
>>>> -               if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
>>>> -                       layer->plane.possible_crtcs = 
>>>> possible_crtcs;
>>>> +               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
>>>> +                       plane->possible_crtcs = possible_crtcs;
>>>>         }
>>>> 
>>>>         return scrtc;
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> index 230cb8f0d601..a4036ee44cf8 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
>>>> @@ -19,7 +19,8 @@ struct sun4i_crtc {
>>>> 
>>>>         struct sun4i_backend            *backend;
>>>>         struct sun4i_tcon               *tcon;
>>>> -       struct sun4i_layer              **layers;
>>>> +       void                            **layers;
>>>> +       const struct sunxi_layer_ops    *layer_ops;
>>> 
>>> 
>>> I think you should probably take a different approach to abstract the
>>> layer
>>> type. How about creating
>>> 
>>> struct sunxi_layer {
>>>         struct drm_plane plane;
>>> }
>>> 
>>> base and then subclassing that for sun4i and sun8i? By doing this you 
>>> can
>>> avoid
>>> the nasty casting and you can also get rid of the get_plane() hook 
>>> and
>>> layer_ops.
>> 
>> 
>> For the situation that using ** things are easily to get weird.
> 
> That code could be reworked, by initializing the layers directly within
> the crtc init code. If you look at rockchip's drm driver, you'll see
> they do this. There is a good reason to do it this way, as you need
> to first create the primary and cursor layers, pass them in when you
> create the crtc, then initialize any additional layers with the
> possible_crtcs bitmap.

I feel that it's still more proper to offload plane creation code
to *_layers_init function, as:

1. We cannot assume the cursor layer's
existance. In fact currently no code in sun4i-drm (including this
patchset) create a cursor layer.

2. The format of planes heavily depend on the engine type (
sun4i-backend or sun8i-mixer).

3. We should create planes according to the type of engine.
Currently the *_layers_init function is part of engine code (See my
Makefile change).

4. If we do so we will have two codes for plane creating -- one for
primary in sun4i_crtc_init, another for overlays in *_layers_init.

> 
> In our driver we are currently initializing all layers, then going
> back and filling in possible_crtcs for the extra layers.
> 
> And as Maxime and I mentioned in the other thread, we don't really
> need to keep a reference to **layers.

It's correct, layers doesn't need to be kept.

And the struct sunxi_layer refactor also makes sense.

> 
> Regards
> ChenYu
> 
>> 
>>> 
>>> Sean
>>> 
>>> 
>>> 
>>>>  };
>>>> 
>>>>  static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct 
>>>> drm_crtc
>>>> *crtc)
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> index f26bde5b9117..bc4a70d6968b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
>>>> @@ -16,7 +16,9 @@
>>>>  #include <drm/drmP.h>
>>>> 
>>>>  #include "sun4i_backend.h"
>>>> +#include "sun4i_crtc.h"
>>>>  #include "sun4i_layer.h"
>>>> +#include "sunxi_layer.h"
>>>> 
>>>>  struct sun4i_plane_desc {
>>>>                enum drm_plane_type     type;
>>>> @@ -100,6 +102,17 @@ static const struct sun4i_plane_desc
>>>> sun4i_backend_planes[] = {
>>>>         },
>>>>  };
>>>> 
>>>> +static struct drm_plane *sun4i_layer_get_plane(void *layer)
>>>> +{
>>>> +       struct sun4i_layer *sun4i_layer = layer;
>>>> +
>>>> +       return &sun4i_layer->plane;
>>>> +}
>>>> +
>>>> +static const struct sunxi_layer_ops layer_ops = {
>>>> +       .get_plane = sun4i_layer_get_plane,
>>>> +};
>>>> +
>>>>  static struct sun4i_layer *sun4i_layer_init_one(struct drm_device 
>>>> *drm,
>>>>                                                 struct sun4i_backend
>>>> *backend,
>>>>                                                 const struct
>>>> sun4i_plane_desc *plane)
>>>> @@ -129,9 +142,10 @@ static struct sun4i_layer
>>>> *sun4i_layer_init_one(struct drm_device *drm,
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend)
>>>> +                                      struct sun4i_crtc *crtc)
>>>>  {
>>>>         struct sun4i_layer **layers;
>>>> +       struct sun4i_backend *backend = crtc->backend;
>>>>         int i;
>>>> 
>>>>         layers = devm_kcalloc(drm->dev, 
>>>> ARRAY_SIZE(sun4i_backend_planes)
>>>> + 1,
>>>> @@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct
>>>> drm_device *drm,
>>>>                 layers[i] = layer;
>>>>         };
>>>> 
>>>> +       /* Assign layer ops to the CRTC */
>>>> +       crtc->layer_ops = &layer_ops;
>>>> +
>>>>         return layers;
>>>>  }
>>>> diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> index 4be1f0919df2..425eea7b9e3b 100644
>>>> --- a/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> +++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
>>>> @@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
>>>>  }
>>>> 
>>>>  struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
>>>> -                                      struct sun4i_backend 
>>>> *backend);
>>>> +                                      struct sun4i_crtc *crtc);
>>>> 
>>>>  #endif /* _SUN4I_LAYER_H_ */
>>>> diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> new file mode 100644
>>>> index 000000000000..d8838ec39299
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
>>>> @@ -0,0 +1,17 @@
>>>> +/*
>>>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU General Public License as
>>>> + * published by the Free Software Foundation; either version 2 of
>>>> + * the License, or (at your option) any later version.
>>>> + */
>>>> +
>>>> +#ifndef _SUNXI_LAYER_H_
>>>> +#define _SUNXI_LAYER_H_
>>>> +
>>>> +struct sunxi_layer_ops {
>>>> +       struct drm_plane *(*get_plane)(void *layer);
>>>> +};
>>>> +
>>>> +#endif /* _SUNXI_LAYER_H_ */
>>>> --
>>>> 2.12.0
>>>> 
>>>> 
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel at lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>> 
>>> 
>> 
>> --
>> You received this message because you are subscribed to the Google 
>> Groups
>> "linux-sunxi" group.
>> To unsubscribe from this group and stop receiving emails from it, send 
>> an
>> email to linux-sunxi+unsubscribe at googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2017-04-05 17:15 UTC | newest]

Thread overview: 82+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-29 19:46 [PATCH v3 00/11] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng
2017-03-29 19:46 ` Icenowy Zheng
2017-03-29 19:46 ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-04-03 15:33   ` Rob Herring
2017-04-03 15:33     ` Rob Herring
2017-04-03 15:33     ` Rob Herring
2017-04-03 15:33     ` Rob Herring
2017-04-03 16:18     ` Icenowy Zheng
2017-04-03 16:18       ` Icenowy Zheng
2017-04-03 16:18       ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 02/11] clk: sunxi-ng: add support for " Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-04-03  8:00   ` Maxime Ripard
2017-04-03  8:00     ` Maxime Ripard
2017-04-03  8:00     ` Maxime Ripard
2017-04-03  8:00     ` Maxime Ripard
2017-03-29 19:46 ` [PATCH v3 04/11] drm/sun4i: abstract the layer type Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-04-03  8:14   ` Maxime Ripard
2017-04-03  8:14     ` Maxime Ripard
2017-04-03  8:14     ` Maxime Ripard
2017-04-03  8:14     ` Maxime Ripard
2017-04-03 10:51     ` Chen-Yu Tsai
2017-04-03 10:51       ` Chen-Yu Tsai
2017-04-03 10:51       ` Chen-Yu Tsai
2017-04-04 19:28   ` Sean Paul
2017-04-04 19:28     ` Sean Paul
2017-04-04 19:53     ` Icenowy Zheng
2017-04-04 19:53       ` Icenowy Zheng
2017-04-04 19:53       ` Icenowy Zheng
2017-04-05  2:27       ` [linux-sunxi] " Chen-Yu Tsai
2017-04-05  2:27         ` Chen-Yu Tsai
2017-04-05  2:27         ` Chen-Yu Tsai
2017-04-05 17:14         ` [linux-sunxi] " icenowy
2017-04-05 17:14           ` icenowy at aosc.io
2017-04-05 17:14           ` icenowy
2017-04-05 17:14           ` icenowy-h8G6r0blFSE
2017-03-29 19:46 ` [PATCH v3 05/11] drm/sun4i: abstract a mixer type Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-04-03  8:24   ` Maxime Ripard
2017-04-03  8:24     ` Maxime Ripard
2017-04-03  8:24     ` Maxime Ripard
2017-03-29 19:46 ` [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 22:33   ` [linux-sunxi] " Jernej Škrabec
2017-03-29 22:33     ` Jernej Škrabec
2017-03-29 22:33     ` Jernej Škrabec
2017-03-29 19:46 ` [PATCH v3 07/11] drm/sun4i: Add compatible string for V3s display engine Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of " Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46 ` [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng
2017-03-29 19:46   ` Icenowy Zheng

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.