Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1641155 > unrolled thread

[PATCH v7 00/13] Initial Allwinner Display Engine 2.0 Support

Started byIcenowy Zheng <icenowy@aosc.io>
First post2017-05-14 18:40 +0200
Last post2017-05-16 14:20 +0200
Articles 9 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v7 00/13] Initial Allwinner Display Engine 2.0 Support Icenowy Zheng <icenowy@aosc.io> - 2017-05-14 18:40 +0200
    [PATCH v7 04/13] drm/sun4i: return only planes for layers created Icenowy Zheng <icenowy@aosc.io> - 2017-05-14 18:40 +0200
      Re: [PATCH v7 04/13] drm/sun4i: return only planes for layers created Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-05-15 11:30 +0200
    [PATCH v7 10/13] drm/sun4i: tcon: add support for V3s TCON Icenowy Zheng <icenowy@aosc.io> - 2017-05-14 18:40 +0200
    [PATCH v7 12/13] ARM: sun8i: v3s: add pinmux for LCD pins of V3s SoC Icenowy Zheng <icenowy@aosc.io> - 2017-05-14 18:40 +0200
    [PATCH v7 05/13] drm/sun4i: abstract a engine type Icenowy Zheng <icenowy@aosc.io> - 2017-05-14 18:40 +0200
      Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-05-15 11:30 +0200
        Re: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type Icenowy Zheng <icenowy@aosc.io> - 2017-05-15 11:40 +0200
          Re: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine  type Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-05-16 14:20 +0200

#1641155 — [PATCH v7 00/13] Initial Allwinner Display Engine 2.0 Support

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-14 18:40 +0200
Subject[PATCH v7 00/13] Initial Allwinner Display Engine 2.0 Support
Message-ID<tH4IN-3Wa-3@gated-at.bofh.it>
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, 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. (For TVE
I have some code that made it working; for HDMI there is a driver by
Jernej Skrabec which is based on the dw-hdmi common code.)

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 (13):
  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: return only planes for layers created
  drm/sun4i: abstract a engine type
  drm/sun4i: add a dedicated module for sun4i-backend and sun4i-layer
  drm/sun4i: add a Kconfig option for sun4i-backend
  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: sun8i: v3s: add device nodes for DE2 display pipeline
  ARM: sun8i: v3s: add pinmux for LCD pins of V3s SoC
  [DO NOT MERGE] ARM: sun8i: v3s: enable LCD panel of Lichee Pi Zero

 .../devicetree/bindings/clock/sun8i-de2.txt        |  31 ++
 .../bindings/display/sunxi/sun4i-drm.txt           |  26 +-
 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               | 260 +++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-de2.h               |  28 ++
 drivers/gpu/drm/sun4i/Kconfig                      |  20 +
 drivers/gpu/drm/sun4i/Makefile                     |   9 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c              |  72 ++--
 drivers/gpu/drm/sun4i/sun4i_backend.h              |  17 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.c                 |  32 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.h                 |   5 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c                  |   6 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h                  |   2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c                |  21 +-
 drivers/gpu/drm/sun4i/sun4i_layer.h                |   6 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c                 |  43 ++-
 drivers/gpu/drm/sun4i/sun4i_tv.c                   |   9 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c                | 134 +++++++
 drivers/gpu/drm/sun4i/sun8i_layer.h                |  36 ++
 drivers/gpu/drm/sun4i/sun8i_mixer.c                | 412 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h                | 137 +++++++
 drivers/gpu/drm/sun4i/sunxi_engine.h               | 111 ++++++
 include/dt-bindings/clock/sun8i-de2.h              |  18 +
 include/dt-bindings/reset/sun8i-de2.h              |  14 +
 27 files changed, 1485 insertions(+), 102 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_engine.h
 create mode 100644 include/dt-bindings/clock/sun8i-de2.h
 create mode 100644 include/dt-bindings/reset/sun8i-de2.h

-- 
2.12.2

[toc] | [next] | [standalone]


#1641156 — [PATCH v7 04/13] drm/sun4i: return only planes for layers created

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-14 18:40 +0200
Subject[PATCH v7 04/13] drm/sun4i: return only planes for layers created
Message-ID<tH4IO-3Wa-29@gated-at.bofh.it>
In reply to#1641155
As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layers.

Each layer is bound to a drm_plane that is CRTC-specific, so we create
them when initializing CRTC (calling sun4i_layers_init, which will be
generalized in next patch). The drm_plane's will be used when creating
CRTC, but the CRTC initialization code do not care other properties of
the layer, so we let the sun4i_layers_init function return drm_plane's
only.

As we have no need to trace the layers after the CRTC is properly
created, we drop the layers pointer in sun4i_crtc struct.

Doing this uncouples the CRTC code from the type of layer (the
sun4i_layers_init function name is still hardcoded and will be changed
in the next patch), so that we can finally gain support for the
mixer in DE2, which has different layers.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c  | 23 ++++++++++++-----------
 drivers/gpu/drm/sun4i/sun4i_crtc.h  |  1 -
 drivers/gpu/drm/sun4i/sun4i_layer.c | 18 ++++++++++--------
 drivers/gpu/drm/sun4i/sun4i_layer.h |  4 ++--
 4 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..708b3543d4e9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -139,6 +139,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
+	struct drm_plane **planes;
 	struct drm_plane *primary = NULL, *cursor = NULL;
 	int ret, i;
 
@@ -149,22 +150,22 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
-	if (IS_ERR(scrtc->layers)) {
+	planes = sun4i_layers_init(drm, scrtc);
+	if (IS_ERR(planes)) {
 		dev_err(drm->dev, "Couldn't create the planes\n");
 		return NULL;
 	}
 
 	/* 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];
+	for (i = 0; planes[i]; i++) {
+		struct drm_plane *plane = planes[i];
 
-		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;
@@ -188,12 +189,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
 						   1);
 
 	/* Set possible_crtcs to this crtc for overlay planes */
-	for (i = 0; scrtc->layers[i]; i++) {
+	for (i = 0; planes[i]; i++) {
 		uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
-		struct sun4i_layer *layer = scrtc->layers[i];
+		struct drm_plane *plane = planes[i];
 
-		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..4dae3508424a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,6 @@ struct sun4i_crtc {
 
 	struct sun4i_backend		*backend;
 	struct sun4i_tcon		*tcon;
-	struct sun4i_layer		**layers;
 };
 
 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..e1f03e1cc0ac 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,6 +16,7 @@
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
+#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
 
 struct sun4i_plane_desc {
@@ -128,15 +129,16 @@ 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_backend *backend)
+struct drm_plane **sun4i_layers_init(struct drm_device *drm,
+				     struct sun4i_crtc *crtc)
 {
-	struct sun4i_layer **layers;
+	struct drm_plane **planes;
+	struct sun4i_backend *backend = crtc->backend;
 	int i;
 
-	layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
-			      sizeof(*layers), GFP_KERNEL);
-	if (!layers)
+	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
+			      sizeof(*planes), GFP_KERNEL);
+	if (!planes)
 		return ERR_PTR(-ENOMEM);
 
 	/*
@@ -178,8 +180,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
 				   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
 
 		layer->id = i;
-		layers[i] = layer;
+		planes[i] = &layer->plane;
 	};
 
-	return layers;
+	return planes;
 }
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..5ea5c994d6ea 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -26,7 +26,7 @@ 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_backend *backend);
+struct drm_plane **sun4i_layers_init(struct drm_device *drm,
+				     struct sun4i_crtc *crtc);
 
 #endif /* _SUN4I_LAYER_H_ */
-- 
2.12.2

[toc] | [prev] | [next] | [standalone]


#1641480 — Re: [PATCH v7 04/13] drm/sun4i: return only planes for layers created

FromMaxime Ripard <maxime.ripard@free-electrons.com>
Date2017-05-15 11:30 +0200
SubjectRe: [PATCH v7 04/13] drm/sun4i: return only planes for layers created
Message-ID<tHkuf-6eH-45@gated-at.bofh.it>
In reply to#1641156

[Multipart message — attachments visible in raw view] — view raw

On Mon, May 15, 2017 at 12:30:36AM +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 layers.
> 
> Each layer is bound to a drm_plane that is CRTC-specific, so we create
> them when initializing CRTC (calling sun4i_layers_init, which will be
> generalized in next patch). The drm_plane's will be used when creating
> CRTC, but the CRTC initialization code do not care other properties of
> the layer, so we let the sun4i_layers_init function return drm_plane's
> only.
> 
> As we have no need to trace the layers after the CRTC is properly
> created, we drop the layers pointer in sun4i_crtc struct.
> 
> Doing this uncouples the CRTC code from the type of layer (the
> sun4i_layers_init function name is still hardcoded and will be changed
> in the next patch), so that we can finally gain support for the
> mixer in DE2, which has different layers.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

Applied, thanks!
Maxime

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

[toc] | [prev] | [next] | [standalone]


#1641157 — [PATCH v7 10/13] drm/sun4i: tcon: add support for V3s TCON

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-14 18:40 +0200
Subject[PATCH v7 10/13] drm/sun4i: tcon: add support for V3s TCON
Message-ID<tH4IO-3Wa-31@gated-at.bofh.it>
In reply to#1641155
Allwinner V3s SoC features a TCON without channel 1.

Add support for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v7:
- Added Chen-Yu's Reviewed-by.

 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 4a979d17ddaa..1dd1948025d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -178,7 +178,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 288275802f92..add349f5e012 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -601,11 +601,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.2

[toc] | [prev] | [next] | [standalone]


#1641158 — [PATCH v7 12/13] ARM: sun8i: v3s: add pinmux for LCD pins of V3s SoC

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-14 18:40 +0200
Subject[PATCH v7 12/13] ARM: sun8i: v3s: add pinmux for LCD pins of V3s SoC
Message-ID<tH4IO-3Wa-33@gated-at.bofh.it>
In reply to#1641155
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.io>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v7:
- Dropped the trailing "@0" in rgb666 pinmux node name.
- Added Chen-Yu's ACK.

 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 b71b35734515..a7026517ed99 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 {
+				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.2

[toc] | [prev] | [next] | [standalone]


#1641159 — [PATCH v7 05/13] drm/sun4i: abstract a engine type

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-14 18:40 +0200
Subject[PATCH v7 05/13] drm/sun4i: abstract a engine type
Message-ID<tH4IP-3Wa-39@gated-at.bofh.it>
In reply to#1641155
As we are going to add support for the Allwinner DE2 engine in sun4i-drm
driver, we will finally have two types of display engines -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, and is part of the "Display Engine" called by
Allwinner, so I choose to call them both "engine" here.

Abstract the engine type to a new struct with an ops struct, which contains
functions that should be called outside the engine-specified code (in
TCON, CRTC or TV Encoder code).

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v7:
- Mention "Display Engine" for the name "engine".
- Fixed some small issues found by Chen-Yu and added his ACK.
Changes in v6:
- Rebased on wens's multi-pipeline patchset.
- Split out Makefile changes.
Changes in v5:
- Really made a sunxi_engine struct type, and moved ops pointer
  into it.
- Added checked ops wrappers.
- Changed the second parameter of layers_init from crtc to engine.
Changes in v4:
- Comments to tag the color correction functions as optional.
- Check before calling the optional functions.
- Change layers_init to satisfy new PATCH v4 04/11.

 drivers/gpu/drm/sun4i/sun4i_backend.c |  68 ++++++++++++---------
 drivers/gpu/drm/sun4i/sun4i_backend.h |  17 +++---
 drivers/gpu/drm/sun4i/sun4i_crtc.c    |  11 ++--
 drivers/gpu/drm/sun4i/sun4i_crtc.h    |   4 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c     |   2 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h     |   2 +-
 drivers/gpu/drm/sun4i/sun4i_layer.c   |   9 ++-
 drivers/gpu/drm/sun4i/sun4i_layer.h   |   4 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c    |  38 ++++++------
 drivers/gpu/drm/sun4i/sun4i_tv.c      |   9 ++-
 drivers/gpu/drm/sun4i/sunxi_engine.h  | 111 ++++++++++++++++++++++++++++++++++
 11 files changed, 199 insertions(+), 76 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sunxi_engine.h

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index e53107418add..611cdcb9c182 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -25,6 +25,8 @@
 
 #include "sun4i_backend.h"
 #include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_engine.h"
 
 static const u32 sunxi_rgb2yuv_coef[12] = {
 	0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -32,41 +34,38 @@ 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(struct sunxi_engine *engine)
 {
 	int i;
 
 	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
 
 	/* Set color correction */
-	regmap_write(backend->regs, SUN4I_BACKEND_OCCTL_REG,
+	regmap_write(engine->regs, SUN4I_BACKEND_OCCTL_REG,
 		     SUN4I_BACKEND_OCCTL_ENABLE);
 
 	for (i = 0; i < 12; i++)
-		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
+		regmap_write(engine->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(struct sunxi_engine *engine)
 {
 	DRM_DEBUG_DRIVER("Disabling color correction\n");
 
 	/* Disable color correction */
-	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
+	regmap_update_bits(engine->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(struct sunxi_engine *engine)
 {
 	DRM_DEBUG_DRIVER("Committing changes\n");
 
-	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
+	regmap_write(engine->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)
@@ -81,7 +80,7 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 	else
 		val = 0;
 
-	regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+	regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
 			   SUN4I_BACKEND_MODCTL_LAY_EN(layer), val);
 }
 EXPORT_SYMBOL(sun4i_backend_layer_enable);
@@ -144,27 +143,28 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
 	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(backend->regs, SUN4I_BACKEND_DISSIZE_REG,
+		regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG,
 			     SUN4I_BACKEND_DISSIZE(state->crtc_w,
 						   state->crtc_h));
 	}
 
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
-	regmap_write(backend->regs, SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
+	regmap_write(backend->engine.regs,
+		     SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
 		     fb->pitches[0] * 8);
 
 	/* Set height and width */
 	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
 			 state->crtc_w, state->crtc_h);
-	regmap_write(backend->regs, SUN4I_BACKEND_LAYSIZE_REG(layer),
+	regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYSIZE_REG(layer),
 		     SUN4I_BACKEND_LAYSIZE(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(backend->regs, SUN4I_BACKEND_LAYCOOR_REG(layer),
+	regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYCOOR_REG(layer),
 		     SUN4I_BACKEND_LAYCOOR(state->crtc_x,
 					   state->crtc_y));
 
@@ -185,7 +185,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
 		interlaced = plane->state->crtc->state->adjusted_mode.flags
 			& DRM_MODE_FLAG_INTERLACE;
 
-	regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+	regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
 			   SUN4I_BACKEND_MODCTL_ITLMOD_EN,
 			   interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0);
 
@@ -199,7 +199,8 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
 		return ret;
 	}
 
-	regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG1(layer),
+	regmap_update_bits(backend->engine.regs,
+			   SUN4I_BACKEND_ATTCTL_REG1(layer),
 			   SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val);
 
 	return 0;
@@ -232,13 +233,14 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
 	/* Write the 32 lower bits of the address (in bits) */
 	lo_paddr = paddr << 3;
 	DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr);
-	regmap_write(backend->regs, SUN4I_BACKEND_LAYFB_L32ADD_REG(layer),
+	regmap_write(backend->engine.regs,
+		     SUN4I_BACKEND_LAYFB_L32ADD_REG(layer),
 		     lo_paddr);
 
 	/* And the upper bits */
 	hi_paddr = paddr >> 29;
 	DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr);
-	regmap_update_bits(backend->regs, SUN4I_BACKEND_LAYFB_H4ADD_REG,
+	regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG,
 			   SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer),
 			   SUN4I_BACKEND_LAYFB_H4ADD(layer, hi_paddr));
 
@@ -330,6 +332,13 @@ static int sun4i_backend_of_get_id(struct device_node *node)
 	return ret;
 }
 
+static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
+	.commit				= sun4i_backend_commit,
+	.layers_init			= sun4i_layers_init,
+	.apply_color_correction		= sun4i_backend_apply_color_correction,
+	.disable_color_correction	= sun4i_backend_disable_color_correction,
+};
+
 static struct regmap_config sun4i_backend_regmap_config = {
 	.reg_bits	= 32,
 	.val_bits	= 32,
@@ -353,7 +362,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 		return -ENOMEM;
 	dev_set_drvdata(dev, backend);
 
-	backend->node = dev->of_node;
+	backend->engine.node = dev->of_node;
+	backend->engine.ops = &sun4i_backend_engine_ops;
 	backend->id = sun4i_backend_of_get_id(dev->of_node);
 	if (backend->id < 0)
 		return backend->id;
@@ -363,11 +373,11 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 	if (IS_ERR(regs))
 		return PTR_ERR(regs);
 
-	backend->regs = devm_regmap_init_mmio(dev, regs,
-					      &sun4i_backend_regmap_config);
-	if (IS_ERR(backend->regs)) {
+	backend->engine.regs = devm_regmap_init_mmio(dev, regs,
+						     &sun4i_backend_regmap_config);
+	if (IS_ERR(backend->engine.regs)) {
 		dev_err(dev, "Couldn't create the backend regmap\n");
-		return PTR_ERR(backend->regs);
+		return PTR_ERR(backend->engine.regs);
 	}
 
 	backend->reset = devm_reset_control_get(dev, NULL);
@@ -415,18 +425,18 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
 		}
 	}
 
-	list_add_tail(&backend->list, &drv->backend_list);
+	list_add_tail(&backend->engine.list, &drv->engine_list);
 
 	/* Reset the registers */
 	for (i = 0x800; i < 0x1000; i += 4)
-		regmap_write(backend->regs, i, 0);
+		regmap_write(backend->engine.regs, i, 0);
 
 	/* Disable registers autoloading */
-	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
+	regmap_write(backend->engine.regs, SUN4I_BACKEND_REGBUFFCTL_REG,
 		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS);
 
 	/* Enable the backend */
-	regmap_write(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+	regmap_write(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG,
 		     SUN4I_BACKEND_MODCTL_DEBE_EN |
 		     SUN4I_BACKEND_MODCTL_START_CTL);
 
@@ -448,7 +458,7 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
 {
 	struct sun4i_backend *backend = dev_get_drvdata(dev);
 
-	list_del(&backend->list);
+	list_del(&backend->engine.list);
 
 	if (of_device_is_compatible(dev->of_node,
 				    "allwinner,sun8i-a33-display-backend"))
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 6327a2985fe6..b022a37e8e5b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -19,6 +19,8 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
+#include "sunxi_engine.h"
+
 #define SUN4I_BACKEND_MODCTL_REG		0x800
 #define SUN4I_BACKEND_MODCTL_LINE_SEL			BIT(29)
 #define SUN4I_BACKEND_MODCTL_ITLMOD_EN			BIT(28)
@@ -141,8 +143,7 @@
 #define SUN4I_BACKEND_PIPE_OFF(p)		(0x5000 + (0x400 * (p)))
 
 struct sun4i_backend {
-	struct device_node	*node;
-	struct regmap		*regs;
+	struct sunxi_engine	engine;
 
 	struct reset_control	*reset;
 
@@ -154,15 +155,13 @@ struct sun4i_backend {
 	struct reset_control	*sat_reset;
 
 	int			id;
-
-	/* Backend list management */
-	struct list_head	list;
 };
 
-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);
+static inline struct sun4i_backend *
+engine_to_sun4i_backend(struct sunxi_engine *engine)
+{
+	return container_of(engine, struct sun4i_backend, engine);
+}
 
 void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 				int layer, bool enable);
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 708b3543d4e9..f8c70439d1e2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,10 +25,9 @@
 
 #include <video/videomode.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
-#include "sun4i_layer.h"
+#include "sunxi_engine.h"
 #include "sun4i_tcon.h"
 
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -56,7 +55,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	DRM_DEBUG_DRIVER("Committing plane changes\n");
 
-	sun4i_backend_commit(scrtc->backend);
+	sunxi_engine_commit(scrtc->engine);
 
 	if (event) {
 		crtc->state->event = NULL;
@@ -135,7 +134,7 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
 };
 
 struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+				   struct sunxi_engine *engine,
 				   struct sun4i_tcon *tcon)
 {
 	struct sun4i_crtc *scrtc;
@@ -146,11 +145,11 @@ 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->engine = engine;
 	scrtc->tcon = tcon;
 
 	/* Create our layers */
-	planes = sun4i_layers_init(drm, scrtc);
+	planes = sunxi_engine_layers_init(drm, engine);
 	if (IS_ERR(planes)) {
 		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 4dae3508424a..bf0ce36eb518 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,7 @@ struct sun4i_crtc {
 	struct drm_crtc			crtc;
 	struct drm_pending_vblank_event	*event;
 
-	struct sun4i_backend		*backend;
+	struct sunxi_engine		*engine;
 	struct sun4i_tcon		*tcon;
 };
 
@@ -27,7 +27,7 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
 }
 
 struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
-				   struct sun4i_backend *backend,
+				   struct sunxi_engine *engine,
 				   struct sun4i_tcon *tcon);
 
 #endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index c52f7a9eb045..35cad9cb44c5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -91,7 +91,7 @@ static int sun4i_drv_bind(struct device *dev)
 		goto free_drm;
 	}
 	drm->dev_private = drv;
-	INIT_LIST_HEAD(&drv->backend_list);
+	INIT_LIST_HEAD(&drv->engine_list);
 	INIT_LIST_HEAD(&drv->tcon_list);
 
 	ret = of_reserved_mem_device_init(dev);
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 250c29017ef5..a960c89270cc 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -18,7 +18,7 @@
 #include <linux/regmap.h>
 
 struct sun4i_drv {
-	struct list_head	backend_list;
+	struct list_head	engine_list;
 	struct list_head	tcon_list;
 
 	struct drm_fbdev_cma	*fbdev;
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index e1f03e1cc0ac..ead4f9d4c1ee 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -11,13 +11,12 @@
  */
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drmP.h>
 
 #include "sun4i_backend.h"
-#include "sun4i_crtc.h"
 #include "sun4i_layer.h"
+#include "sunxi_engine.h"
 
 struct sun4i_plane_desc {
 	       enum drm_plane_type     type;
@@ -130,10 +129,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
 }
 
 struct drm_plane **sun4i_layers_init(struct drm_device *drm,
-				     struct sun4i_crtc *crtc)
+				     struct sunxi_engine *engine)
 {
 	struct drm_plane **planes;
-	struct sun4i_backend *backend = crtc->backend;
+	struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
 	int i;
 
 	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -175,7 +174,7 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
 
 		DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
 				 i ? "overlay" : "primary", plane->pipe);
-		regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
+		regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
 				   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
 				   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 5ea5c994d6ea..4e84f438b346 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 sunxi_engine;
+
 struct sun4i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
@@ -27,6 +29,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
 }
 
 struct drm_plane **sun4i_layers_init(struct drm_device *drm,
-				     struct sun4i_crtc *crtc);
+				     struct sunxi_engine *engine);
 
 #endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 8b6aaa60037d..288275802f92 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -25,12 +25,12 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
-#include "sun4i_backend.h"
 #include "sun4i_crtc.h"
 #include "sun4i_dotclock.h"
 #include "sun4i_drv.h"
 #include "sun4i_rgb.h"
 #include "sun4i_tcon.h"
+#include "sunxi_engine.h"
 
 void sun4i_tcon_disable(struct sun4i_tcon *tcon)
 {
@@ -419,12 +419,16 @@ static int sun4i_tcon_init_regmap(struct device *dev,
  * means maintaining a large list of them. Or, since the backend is
  * registered and binded before the TCON, we can just go through the
  * list of registered backends and compare the device node.
+ *
+ * As the structures now store engines instead of backends, here this
+ * function in fact searches the corresponding engine, and the ID is
+ * requested via the get_id function of the engine.
  */
-static struct sun4i_backend *sun4i_tcon_find_backend(struct sun4i_drv *drv,
-						     struct device_node *node)
+static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
+						   struct device_node *node)
 {
 	struct device_node *port, *ep, *remote;
-	struct sun4i_backend *backend;
+	struct sunxi_engine *engine;
 
 	port = of_graph_get_port_by_id(node, 0);
 	if (!port)
@@ -435,21 +439,21 @@ static struct sun4i_backend *sun4i_tcon_find_backend(struct sun4i_drv *drv,
 		if (!remote)
 			continue;
 
-		/* does this node match any registered backends? */
-		list_for_each_entry(backend, &drv->backend_list, list) {
-			if (remote == backend->node) {
+		/* does this node match any registered engines? */
+		list_for_each_entry(engine, &drv->engine_list, list) {
+			if (remote == engine->node) {
 				of_node_put(remote);
 				of_node_put(port);
-				return backend;
+				return engine;
 			}
 		}
 
 		/* keep looking through upstream ports */
-		backend = sun4i_tcon_find_backend(drv, remote);
-		if (!IS_ERR(backend)) {
+		engine = sun4i_tcon_find_engine(drv, remote);
+		if (!IS_ERR(engine)) {
 			of_node_put(remote);
 			of_node_put(port);
-			return backend;
+			return engine;
 		}
 	}
 
@@ -461,13 +465,13 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = data;
 	struct sun4i_drv *drv = drm->dev_private;
-	struct sun4i_backend *backend;
+	struct sunxi_engine *engine;
 	struct sun4i_tcon *tcon;
 	int ret;
 
-	backend = sun4i_tcon_find_backend(drv, dev->of_node);
-	if (IS_ERR(backend)) {
-		dev_err(dev, "Couldn't find matching backend\n");
+	engine = sun4i_tcon_find_engine(drv, dev->of_node);
+	if (IS_ERR(engine)) {
+		dev_err(dev, "Couldn't find matching engine\n");
 		return -EPROBE_DEFER;
 	}
 
@@ -477,7 +481,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	dev_set_drvdata(dev, tcon);
 	tcon->drm = drm;
 	tcon->dev = dev;
-	tcon->id = backend->id;
+	tcon->id = sunxi_engine_get_id(engine);
 	tcon->quirks = of_device_get_match_data(dev);
 
 	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
@@ -520,7 +524,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 		goto err_free_dotclock;
 	}
 
-	tcon->crtc = sun4i_crtc_init(drm, backend, tcon);
+	tcon->crtc = sun4i_crtc_init(drm, engine, 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 542da220818b..a9cad00d4ee8 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_engine.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,8 @@ 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);
+
+	sunxi_engine_disable_color_correction(crtc->engine);
 }
 
 static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +370,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);
+	sunxi_engine_apply_color_correction(crtc->engine);
 
 	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
 			   SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
new file mode 100644
index 000000000000..9d3eabd8020d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * 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_ENGINE_H_
+#define _SUNXI_ENGINE_H_
+
+struct drm_plane;
+struct drm_device;
+
+struct sunxi_engine;
+
+struct sunxi_engine_ops {
+	void (*commit)(struct sunxi_engine *engine);
+	struct drm_plane **(*layers_init)(struct drm_device *drm,
+					  struct sunxi_engine *engine);
+
+	void (*apply_color_correction)(struct sunxi_engine *engine);
+	void (*disable_color_correction)(struct sunxi_engine *engine);
+	int (*get_id)(struct sunxi_engine *engine);
+};
+
+/**
+ * struct sunxi_engine - the common parts of an engine for sun4i-drm driver
+ * @ops:	the operations of the engine
+ * @regs:	the regmap of the engine
+ */
+struct sunxi_engine {
+	const struct sunxi_engine_ops	*ops;
+
+	struct device_node		*node;
+	struct regmap			*regs;
+
+	/* Engine list management */
+	struct list_head		list;
+};
+
+/**
+ * sunxi_engine_commit() - commit all changes of the engine
+ * @engine:	pointer to the engine
+ */
+static inline void
+sunxi_engine_commit(struct sunxi_engine *engine)
+{
+	if (engine->ops && engine->ops->commit)
+		engine->ops->commit(engine);
+}
+
+/**
+ * sunxi_engine_layers_init() - Create planes (layers) for the engine
+ * @drm:	pointer to the drm_device for which planes will be created
+ * @engine:	pointer to the engine
+ */
+static inline struct drm_plane **
+sunxi_engine_layers_init(struct drm_device *drm, struct sunxi_engine *engine)
+{
+	if (engine->ops && engine->ops->layers_init)
+		return engine->ops->layers_init(drm, engine);
+	return ERR_PTR(-ENOSYS);
+}
+
+/**
+ * sunxi_engine_apply_color_correction - Apply the RGB2YUV color correction
+ * @engine:	pointer to the engine
+ *
+ * This functionality is optional for an engine, however, if the engine is
+ * intended to be used with TV Encoder, the output will be incorrect
+ * without the color correction, due to TV Encoder expects the engine to
+ * output directly YUV signal.
+ */
+static inline void
+sunxi_engine_apply_color_correction(struct sunxi_engine *engine)
+{
+	if (engine->ops && engine->ops->apply_color_correction)
+		engine->ops->apply_color_correction(engine);
+}
+
+/**
+ * sunxi_engine_disable_color_correction - Disable the color space correction
+ * @engine:	pointer to the engine
+ *
+ * This function is paired with apply_color_correction().
+ */
+static inline void
+sunxi_engine_disable_color_correction(struct sunxi_engine *engine)
+{
+	if (engine->ops && engine->ops->disable_color_correction)
+		engine->ops->disable_color_correction(engine);
+}
+
+/**
+ * sunxi_engine_get_id - Get the ID of the engine.
+ * @engine:	pointer to the engine
+ *
+ * If the ID is not necessary, just do not implement it in sunxi_engine_ops,
+ * and a default -1 will be returned.
+ */
+static inline int
+sunxi_engine_get_id(struct sunxi_engine *engine)
+{
+	if (engine->ops && engine->ops->get_id)
+		return engine->ops->get_id(engine);
+
+	return -1;
+}
+#endif /* _SUNXI_ENGINE_H_ */
-- 
2.12.2

[toc] | [prev] | [next] | [standalone]


#1641478 — Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type

FromMaxime Ripard <maxime.ripard@free-electrons.com>
Date2017-05-15 11:30 +0200
SubjectRe: [PATCH v7 05/13] drm/sun4i: abstract a engine type
Message-ID<tHkuf-6eH-41@gated-at.bofh.it>
In reply to#1641159

[Multipart message — attachments visible in raw view] — view raw

On Mon, May 15, 2017 at 12:30:37AM +0800, Icenowy Zheng wrote:
> As we are going to add support for the Allwinner DE2 engine in sun4i-drm
> driver, we will finally have two types of display engines -- the DE1
> backend and the DE2 mixer. They both do some display blending and feed
> graphics data to TCON, and is part of the "Display Engine" called by
> Allwinner, so I choose to call them both "engine" here.
> 
> Abstract the engine type to a new struct with an ops struct, which contains
> functions that should be called outside the engine-specified code (in
> TCON, CRTC or TV Encoder code).
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v7:
> - Mention "Display Engine" for the name "engine".
> - Fixed some small issues found by Chen-Yu and added his ACK.
> Changes in v6:
> - Rebased on wens's multi-pipeline patchset.
> - Split out Makefile changes.

You also added a get_id callback here...

> +static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
> +	.commit				= sun4i_backend_commit,
> +	.layers_init			= sun4i_layers_init,
> +	.apply_color_correction		= sun4i_backend_apply_color_correction,
> +	.disable_color_correction	= sun4i_backend_disable_color_correction,
> +};
> +

... that you don't populate ...

> @@ -477,7 +481,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  	dev_set_drvdata(dev, tcon);
>  	tcon->drm = drm;
>  	tcon->dev = dev;
> -	tcon->id = backend->id;
> +	tcon->id = sunxi_engine_get_id(engine);

... that you call to fill the TCON ID ...

> +/**
> + * sunxi_engine_get_id - Get the ID of the engine.
> + * @engine:	pointer to the engine
> + *
> + * If the ID is not necessary, just do not implement it in sunxi_engine_ops,
> + * and a default -1 will be returned.
> + */
> +static inline int
> +sunxi_engine_get_id(struct sunxi_engine *engine)
> +{
> +	if (engine->ops && engine->ops->get_id)
> +		return engine->ops->get_id(engine);
> +
> +	return -1;

... and will return -1 if not populated, which essentially means that
instead of having 0 or 1, we're now having -1 as our id.

This is a regression, and I'm even wondering if we can't just store
the ID in the sunxi_engine structure. Is anything preventing us to do
that, instead of using a callback?

Maxime

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

[toc] | [prev] | [next] | [standalone]


#1641488 — Re: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type

FromIcenowy Zheng <icenowy@aosc.io>
Date2017-05-15 11:40 +0200
SubjectRe: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type
Message-ID<tHkDT-6ia-11@gated-at.bofh.it>
In reply to#1641478

于 2017年5月15日 GMT+08:00 下午5:20:01, Maxime Ripard <maxime.ripard@free-electrons.com> 写到:
>On Mon, May 15, 2017 at 12:30:37AM +0800, Icenowy Zheng wrote:
>> As we are going to add support for the Allwinner DE2 engine in
>sun4i-drm
>> driver, we will finally have two types of display engines -- the DE1
>> backend and the DE2 mixer. They both do some display blending and
>feed
>> graphics data to TCON, and is part of the "Display Engine" called by
>> Allwinner, so I choose to call them both "engine" here.
>> 
>> Abstract the engine type to a new struct with an ops struct, which
>contains
>> functions that should be called outside the engine-specified code (in
>> TCON, CRTC or TV Encoder code).
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> Changes in v7:
>> - Mention "Display Engine" for the name "engine".
>> - Fixed some small issues found by Chen-Yu and added his ACK.
>> Changes in v6:
>> - Rebased on wens's multi-pipeline patchset.
>> - Split out Makefile changes.
>
>You also added a get_id callback here...
>
>> +static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
>> +	.commit				= sun4i_backend_commit,
>> +	.layers_init			= sun4i_layers_init,
>> +	.apply_color_correction		= sun4i_backend_apply_color_correction,
>> +	.disable_color_correction	= sun4i_backend_disable_color_correction,
>> +};
>> +
>
>... that you don't populate ...
>
>> @@ -477,7 +481,7 @@ static int sun4i_tcon_bind(struct device *dev,
>struct device *master,
>>  	dev_set_drvdata(dev, tcon);
>>  	tcon->drm = drm;
>>  	tcon->dev = dev;
>> -	tcon->id = backend->id;
>> +	tcon->id = sunxi_engine_get_id(engine);
>
>... that you call to fill the TCON ID ...
>
>> +/**
>> + * sunxi_engine_get_id - Get the ID of the engine.
>> + * @engine:	pointer to the engine
>> + *
>> + * If the ID is not necessary, just do not implement it in
>sunxi_engine_ops,
>> + * and a default -1 will be returned.
>> + */
>> +static inline int
>> +sunxi_engine_get_id(struct sunxi_engine *engine)
>> +{
>> +	if (engine->ops && engine->ops->get_id)
>> +		return engine->ops->get_id(engine);
>> +
>> +	return -1;
>
>... and will return -1 if not populated, which essentially means that
>instead of having 0 or 1, we're now having -1 as our id.
>
>This is a regression, and I'm even wondering if we can't just store
>the ID in the sunxi_engine structure. Is anything preventing us to do
>that, instead of using a callback?

Some engines (de2 mixer) doesn't use the ID. But 0 is a valid ID here.

If we just store it in sunxi_engine, it should be assigned -1 for de2 mixer.
Is this applicable?

If it's okay I will do so.

>
>Maxime

[toc] | [prev] | [next] | [standalone]


#1642486 — Re: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type

FromMaxime Ripard <maxime.ripard@free-electrons.com>
Date2017-05-16 14:20 +0200
SubjectRe: [linux-sunxi] Re: [PATCH v7 05/13] drm/sun4i: abstract a engine type
Message-ID<tHJCi-5vb-37@gated-at.bofh.it>
In reply to#1641488

[Multipart message — attachments visible in raw view] — view raw

On Mon, May 15, 2017 at 05:35:02PM +0800, Icenowy Zheng wrote:
> 
> 
> 于 2017年5月15日 GMT+08:00 下午5:20:01, Maxime Ripard <maxime.ripard@free-electrons.com> 写到:
> >On Mon, May 15, 2017 at 12:30:37AM +0800, Icenowy Zheng wrote:
> >> As we are going to add support for the Allwinner DE2 engine in
> >sun4i-drm
> >> driver, we will finally have two types of display engines -- the DE1
> >> backend and the DE2 mixer. They both do some display blending and
> >feed
> >> graphics data to TCON, and is part of the "Display Engine" called by
> >> Allwinner, so I choose to call them both "engine" here.
> >> 
> >> Abstract the engine type to a new struct with an ops struct, which
> >contains
> >> functions that should be called outside the engine-specified code (in
> >> TCON, CRTC or TV Encoder code).
> >> 
> >> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> >> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> >> ---
> >> Changes in v7:
> >> - Mention "Display Engine" for the name "engine".
> >> - Fixed some small issues found by Chen-Yu and added his ACK.
> >> Changes in v6:
> >> - Rebased on wens's multi-pipeline patchset.
> >> - Split out Makefile changes.
> >
> >You also added a get_id callback here...
> >
> >> +static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
> >> +	.commit				= sun4i_backend_commit,
> >> +	.layers_init			= sun4i_layers_init,
> >> +	.apply_color_correction		= sun4i_backend_apply_color_correction,
> >> +	.disable_color_correction	= sun4i_backend_disable_color_correction,
> >> +};
> >> +
> >
> >... that you don't populate ...
> >
> >> @@ -477,7 +481,7 @@ static int sun4i_tcon_bind(struct device *dev,
> >struct device *master,
> >>  	dev_set_drvdata(dev, tcon);
> >>  	tcon->drm = drm;
> >>  	tcon->dev = dev;
> >> -	tcon->id = backend->id;
> >> +	tcon->id = sunxi_engine_get_id(engine);
> >
> >... that you call to fill the TCON ID ...
> >
> >> +/**
> >> + * sunxi_engine_get_id - Get the ID of the engine.
> >> + * @engine:	pointer to the engine
> >> + *
> >> + * If the ID is not necessary, just do not implement it in
> >sunxi_engine_ops,
> >> + * and a default -1 will be returned.
> >> + */
> >> +static inline int
> >> +sunxi_engine_get_id(struct sunxi_engine *engine)
> >> +{
> >> +	if (engine->ops && engine->ops->get_id)
> >> +		return engine->ops->get_id(engine);
> >> +
> >> +	return -1;
> >
> >... and will return -1 if not populated, which essentially means that
> >instead of having 0 or 1, we're now having -1 as our id.
> >
> >This is a regression, and I'm even wondering if we can't just store
> >the ID in the sunxi_engine structure. Is anything preventing us to do
> >that, instead of using a callback?
> 
> Some engines (de2 mixer) doesn't use the ID. But 0 is a valid ID here.

Surely it will at some point.

> If we just store it in sunxi_engine, it should be assigned -1 for de2 mixer.
> Is this applicable?
> 
> If it's okay I will do so.

Yes, it sounds reasonable.

Maxime

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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web