linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/27] Improve DE2 support
@ 2017-12-01  6:05 Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 01/27] drm/sun4i: Fix format mask in DE2 driver Jernej Skrabec
                   ` (27 more replies)
  0 siblings, 28 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Current DE2 driver is very basic and uses a lot of magic constants since
there is no documentation and knowledge about it was limited at the time.

With studying BSP source code, deeper knowledge was gained which allows
to improve mainline driver considerably.

At the beginning of this series, some code refactoring is done as well
as adding some checks (patches 1-15).

Further patches add multi-plane support with HW scaling and all possible
RGB formats (patches 16-21).

At last, support for YUV formats is added (patches 22-26).

At the end, I included patch which puts lowest plane before second lowest.
This should help testing VI planes when mixer has configuration 1 VI plane
and 1 or more UI planes (most SoCs except V3s).

This code was developed on H3, but it should work on every SoC if correct
configuration structure is provided.

H3 code can be found here:
https://github.com/jernejsk/linux-1/commits/de2_impr_for_next

Best regards,
Jernej

Changes from v1:
- Split two patches to multiple smaller ones and better explain why those
changes are needed and added fixes tag where appropriate.
- channel parameters represents HW better (layer id -> channel, overlay)
- add kerneldoc to configuration structure
- nicer code style in atomic_check functions
- changed WARN() to DRM_WARN() in csc code
- split common scaler file to separate ui and vi scaler files
- move channel specific code out of mixer code to sun8i_ui_layer.c and
sun8i_vi_layer.c
- defined macros for min and max supported scaler factor for each type
of scaler

Jernej Skrabec (27):
  drm/sun4i: Fix format mask in DE2 driver
  drm/sun4i: Rename DE2 RGB format macros
  drm/sun4i: Remove setting alpha mode in DE2 driver
  drm/sun4i: Fix debug message in DE2
  drm/sun4i: Remove setting default values in DE2 driver
  drm/sun4i: Explain color macro in DE2 driver
  drm/sun4i: Set blending mode for all channels (DE2)
  drm/sun4i: Rename some macros in DE2 driver
  drm/sun4i: Rework enabling plane in DE2 driver
  drm/sun4i: Start using layer id in DE2 driver
  drm/sun4i: Add constraints checking to DE2 driver
  drm/sun4i: Use values calculated by atomic check
  drm/sun4i: Move line width setting in DE2
  drm/sun4i: Move channel size related code in DE2
  drm/sun4i: Move interlace related code in DE2
  drm/sun4i: Add multi plane support to DE2 driver
  drm/sun4i: Add support for all HW supported DE2 RGB formats
  drm/sun4i: Reorganize UI layer code in DE2
  drm/sun4i: Add support for DE2 VI planes
  drm/sun4i: Add scaler configuration to DE2 mixers
  drm/sun4i: Add support for HW scaling to DE2
  drm/sun4i: Add CCSC property to DE2 configuration
  drm/sun4i: Add DE2 CSC library
  drm/sun4i: Add DE2 definitions for YUV formats
  drm/sun4i: Expand DE2 scaler lib with YUV support
  drm/sun4i: Wire in DE2 YUV support
  [DO NOT MERGE]drm/sun4i: Change zpos of bottom VI plane

 drivers/gpu/drm/sun4i/Makefile          |   4 +-
 drivers/gpu/drm/sun4i/sun8i_csc.c       |  93 +++
 drivers/gpu/drm/sun4i/sun8i_csc.h       |  36 ++
 drivers/gpu/drm/sun4i/sun8i_layer.c     | 134 -----
 drivers/gpu/drm/sun4i/sun8i_layer.h     |  36 --
 drivers/gpu/drm/sun4i/sun8i_mixer.c     | 496 +++++++++-------
 drivers/gpu/drm/sun4i/sun8i_mixer.h     | 123 ++--
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c  | 351 ++++++++++++
 drivers/gpu/drm/sun4i/sun8i_ui_layer.h  |  63 +++
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 172 ++++++
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h |  49 ++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c  | 389 +++++++++++++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h  |  51 ++
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 971 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h |  58 ++
 15 files changed, 2595 insertions(+), 431 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_csc.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_csc.h
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h

-- 
2.15.1

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

* [PATCH v2 01/27] drm/sun4i: Fix format mask in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 02/27] drm/sun4i: Rename DE2 RGB format macros Jernej Skrabec
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Format mask is one bit too short. Fix it.

Fixes: 9d75b8c0b999 (drm/sun4i: add support for Allwinner DE2 mixers)

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 4785ac090b8c..c142fbb8661e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -80,7 +80,7 @@
 
 #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_FBFMT_MASK	GENMASK(12, 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)
-- 
2.15.1

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

* [PATCH v2 02/27] drm/sun4i: Rename DE2 RGB format macros
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 01/27] drm/sun4i: Fix format mask in DE2 driver Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 03/27] drm/sun4i: Remove setting alpha mode in DE2 driver Jernej Skrabec
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Current RGB formats macros are actually not specific to UI planes.
Rename it to something more universal and introduce shift macro.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 7 ++++---
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 8 +++++---
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index cb193c5f1686..b9c48c60131f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -71,15 +71,15 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 {
 	switch (format) {
 	case DRM_FORMAT_ARGB8888:
-		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888;
+		*mode = SUN8I_MIXER_FBFMT_ARGB8888;
 		break;
 
 	case DRM_FORMAT_XRGB8888:
-		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+		*mode = SUN8I_MIXER_FBFMT_XRGB8888;
 		break;
 
 	case DRM_FORMAT_RGB888:
-		*mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+		*mode = SUN8I_MIXER_FBFMT_RGB888;
 		break;
 
 	default:
@@ -173,6 +173,7 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 		return ret;
 	}
 
+	val <<= SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index c142fbb8661e..82c3416fbf3a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -81,13 +81,15 @@
 #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(12, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET	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)
 
+#define SUN8I_MIXER_FBFMT_ARGB8888	0
+#define SUN8I_MIXER_FBFMT_XRGB8888	4
+#define SUN8I_MIXER_FBFMT_RGB888	8
+
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
  * be used to disable these sub-engines.
-- 
2.15.1

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

* [PATCH v2 03/27] drm/sun4i: Remove setting alpha mode in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 01/27] drm/sun4i: Fix format mask in DE2 driver Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 02/27] drm/sun4i: Rename DE2 RGB format macros Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 04/27] drm/sun4i: Fix debug message in DE2 Jernej Skrabec
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Current code sets alpha mode to global alpha mode and global alpha
value to 0xff which is totaly opaque. That is not needed for two
reasons:

- only one plane is active and thus it can be blended only with
background, which is black,
- it will hinder proper blending when more than one plane is supported

Default mode (0) considers pixel alpha value or 0xff if pixel has
no alpha information. Global alpha value is ignored in this case.

Because of that, just remove the code.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 10 ----------
 drivers/gpu/drm/sun4i/sun8i_mixer.h |  2 --
 2 files changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index b9c48c60131f..d3dee6131209 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -54,16 +54,6 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 	regmap_update_bits(mixer->engine.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->engine.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->engine.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);
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 82c3416fbf3a..a7fe013c1d4a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -83,8 +83,6 @@
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK	GENMASK(12, 8)
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET	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_ALPHA_DEF	(0xff << 24)
 
 #define SUN8I_MIXER_FBFMT_ARGB8888	0
 #define SUN8I_MIXER_FBFMT_XRGB8888	4
-- 
2.15.1

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

* [PATCH v2 04/27] drm/sun4i: Fix debug message in DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (2 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 03/27] drm/sun4i: Remove setting alpha mode in DE2 driver Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 05/27] drm/sun4i: Remove setting default values in DE2 driver Jernej Skrabec
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Debug message would print "Enabling" even when disabling plane.

Fix it.

Fixes: 9d75b8c0b999 (drm/sun4i: add support for Allwinner DE2 mixers)

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index d3dee6131209..b947ee2e4fe4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -44,7 +44,8 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 	/* 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);
+	DRM_DEBUG_DRIVER("%sabling layer %d in channel %d\n",
+			 enable ? "En" : "Dis", layer, chan);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
-- 
2.15.1

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

* [PATCH v2 05/27] drm/sun4i: Remove setting default values in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (3 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 04/27] drm/sun4i: Fix debug message in DE2 Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 06/27] drm/sun4i: Explain color macro " Jernej Skrabec
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Premultiply and color key control registers are already set to zero by
initialization code few lines above. Furthermore, it seems that
colorkeying doesn't really work. It's not used in BSP driver and
experiments with it all failed.

Just remove the code.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 4 ----
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index b947ee2e4fe4..f4a7fa0ba7ad 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -320,14 +320,10 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
 		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
-		     SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
 		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
 		     SUN8I_MIXER_BLEND_MODE_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_CK_CTL,
-		     SUN8I_MIXER_BLEND_CK_CTL_DEF);
 
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index a7fe013c1d4a..db005a4bca43 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -48,10 +48,8 @@
 /* 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)
 
-- 
2.15.1

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

* [PATCH v2 06/27] drm/sun4i: Explain color macro in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (4 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 05/27] drm/sun4i: Remove setting default values in DE2 driver Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 07/27] drm/sun4i: Set blending mode for all channels (DE2) Jernej Skrabec
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Color attribute have same format troughout the whole driver.

Rename macro, add comment with simple explanation and remove redundant
definitions.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 8 +++++---
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 4 ++--
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index f4a7fa0ba7ad..5144e6d0ac56 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -317,17 +317,19 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
 		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);
 
+	/* Set background color to black */
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
+		     SUN8I_MIXER_BLEND_COLOR_BLACK);
+
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
 		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
-		     SUN8I_MIXER_BLEND_BKCOLOR_DEF);
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
 		     SUN8I_MIXER_BLEND_MODE_DEF);
 
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
 	/* Select the first UI channel */
 	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index db005a4bca43..9b50733298b8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -45,10 +45,10 @@
 #define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
 #define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
 
+/* colors are always in AARRGGBB format */
+#define SUN8I_MIXER_BLEND_COLOR_BLACK		0xff000000
 /* 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_BKCOLOR_DEF		0xff000000
 #define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
 
 #define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
-- 
2.15.1

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

* [PATCH v2 07/27] drm/sun4i: Set blending mode for all channels (DE2)
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (5 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 06/27] drm/sun4i: Explain color macro " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 08/27] drm/sun4i: Rename some macros in DE2 driver Jernej Skrabec
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

BSP driver always sets blend mode for all channels, no matter if they
are really used or not. Do the same here.

The exact meaning of the value is not exactly known, but BSP driver
mentions "SRC OVER" and by digging through code some more info can be
found.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 5144e6d0ac56..23659ce1cf27 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -239,6 +239,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	struct sun8i_mixer *mixer;
 	struct resource *res;
 	void __iomem *regs;
+	int plane_cnt;
 	int i, ret;
 
 	/*
@@ -324,8 +325,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	/* Initialize blender */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
 		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(0),
-		     SUN8I_MIXER_BLEND_MODE_DEF);
 
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
@@ -337,6 +336,11 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
 		     mixer->cfg->vi_num);
 
+	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
+	for (i = 0; i < plane_cnt; i++)
+		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i),
+			     SUN8I_MIXER_BLEND_MODE_DEF);
+
 	return 0;
 
 err_disable_bus_clk:
-- 
2.15.1

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

* [PATCH v2 08/27] drm/sun4i: Rename some macros in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (6 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 07/27] drm/sun4i: Set blending mode for all channels (DE2) Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 09/27] drm/sun4i: Rework enabling plane " Jernej Skrabec
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Now that some knowledge of DE2 is gained, rename or add some macros to
make code more readable.

Max channel macro is removed, since it is not used and it is not clear
if it has right value. Structures in BSP driver shows possibility of 5
channels maximum although there is no SoC with such configuration.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c |  5 +++--
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 13 ++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 23659ce1cf27..c7d4ccd605e0 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -323,8 +323,9 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
 	/* Initialize blender */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
-		     SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+		     SUN8I_MIXER_BLEND_PIPE_CTL_EN(0) |
+		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
 
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 9b50733298b8..76f0b2bd91e2 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -16,8 +16,6 @@
 
 #include "sunxi_engine.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))
 
@@ -26,14 +24,14 @@
 #define SUN8I_MIXER_GLOBAL_DBUFF		0x8
 #define SUN8I_MIXER_GLOBAL_SIZE			0xc
 
-#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		0x1
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN		BIT(0)
 
-#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		0x1
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE		BIT(0)
 
-#define SUN8I_MIXER_BLEND_FCOLOR_CTL		0x1000
+#define SUN8I_MIXER_BLEND_PIPE_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_ATTR_COORD(x)		(0x1004 + 0x10 * (x) + 0x8)
 #define SUN8I_MIXER_BLEND_ROUTE			0x1080
 #define SUN8I_MIXER_BLEND_PREMULTIPLY		0x1084
 #define SUN8I_MIXER_BLEND_BKCOLOR		0x1088
@@ -45,10 +43,11 @@
 #define SUN8I_MIXER_BLEND_CK_MIN(x)		(0x10e0 + 0x04 * (x))
 #define SUN8I_MIXER_BLEND_OUTCTL		0x10fc
 
+#define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe)	BIT(8 + pipe)
+#define SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(pipe)	BIT(pipe)
 /* colors are always in AARRGGBB format */
 #define SUN8I_MIXER_BLEND_COLOR_BLACK		0xff000000
 /* The following numbers are some still unknown magic numbers */
-#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF	0x00000101
 #define SUN8I_MIXER_BLEND_MODE_DEF		0x03010301
 
 #define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED	BIT(1)
-- 
2.15.1

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

* [PATCH v2 09/27] drm/sun4i: Rework enabling plane in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (7 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 08/27] drm/sun4i: Rename some macros in DE2 driver Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 10/27] drm/sun4i: Start using layer id " Jernej Skrabec
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

If we want to support multiple planes in the future, code which enables
pipe has to be moved to appropriate place and it must depend on channel
id instead of being hardcoded.

Side effect of that rework is definition of default Z position. For now,
put first channel at the bottom, second above it and so on.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index c7d4ccd605e0..015943c0ed5a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -55,6 +55,15 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	if (enable)
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(chan);
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_BLEND_PIPE_CTL,
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(chan), val);
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
@@ -98,7 +107,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating blender size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_BLEND_ATTR_INSIZE(0),
+			     SUN8I_MIXER_BLEND_ATTR_INSIZE(chan),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
@@ -322,20 +331,17 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR,
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
-	/* Initialize blender */
+	/*
+	 * Set fill color of bottom plane to black. Generally not needed
+	 * except when VI plane is at bottom (zpos = 0) and enabled.
+	 */
 	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL,
-		     SUN8I_MIXER_BLEND_PIPE_CTL_EN(0) |
 		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
-
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
-	/* Select the first UI channel */
-	DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
-			 mixer->cfg->vi_num);
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE,
-		     mixer->cfg->vi_num);
+	/* Fixed zpos for now */
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43210);
 
 	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
 	for (i = 0; i < plane_cnt; i++)
-- 
2.15.1

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

* [PATCH v2 10/27] drm/sun4i: Start using layer id in DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (8 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 09/27] drm/sun4i: Rework enabling plane " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 11/27] drm/sun4i: Add constraints checking to " Jernej Skrabec
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Till now, plane selection was hardcoded to first overlay in first UI
channel and layer parameter is unused.

Rename and add parameters to layer functions so they would represent HW
more accurately and start using then.

It turns out that overlays don't fit well in current DRM design, because
they can't be blended together or scaled independetly when they are set
to same channel. Because of that, always use only first overlay in each
channel.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_layer.c | 18 ++++++++-----
 drivers/gpu/drm/sun4i/sun8i_layer.h |  3 ++-
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 50 ++++++++++++++++---------------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 16 ++++++------
 4 files changed, 43 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
index 23810ff72684..5aa6e2c9728e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -32,7 +32,8 @@ static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
 	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
 	struct sun8i_mixer *mixer = layer->mixer;
 
-	sun8i_mixer_layer_enable(mixer, layer->id, false);
+	sun8i_mixer_layer_enable(mixer, layer->channel,
+				 layer->overlay, false);
 }
 
 static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
@@ -41,10 +42,14 @@ static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
 	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);
+	sun8i_mixer_update_layer_coord(mixer, layer->channel,
+				       layer->overlay, plane);
+	sun8i_mixer_update_layer_formats(mixer, layer->channel,
+					 layer->overlay, plane);
+	sun8i_mixer_update_layer_buffer(mixer, layer->channel,
+					layer->overlay, plane);
+	sun8i_mixer_layer_enable(mixer, layer->channel,
+				 layer->overlay, true);
 }
 
 static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
@@ -126,7 +131,8 @@ struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 			return ERR_CAST(layer);
 		};
 
-		layer->id = i;
+		layer->channel = mixer->cfg->vi_num + i;
+		layer->overlay = 0;
 		planes[i] = &layer->plane;
 	};
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
index e5eccd27cff0..d246e0dd3d48 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -22,7 +22,8 @@ struct sun8i_layer {
 	struct drm_plane	plane;
 	struct sun4i_drv	*drv;
 	struct sun8i_mixer	*mixer;
-	int			id;
+	int			channel;
+	int			overlay;
 };
 
 static inline struct sun8i_layer *
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 015943c0ed5a..2bf7ba1e5ba7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -37,15 +37,13 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
-				int layer, bool enable)
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, int channel,
+			      int overlay, bool enable)
 {
 	u32 val;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 
-	DRM_DEBUG_DRIVER("%sabling layer %d in channel %d\n",
-			 enable ? "En" : "Dis", layer, chan);
+	DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
+			 enable ? "En" : "Dis", channel, overlay);
 
 	if (enable)
 		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
@@ -53,17 +51,17 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	if (enable)
-		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(chan);
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
 	else
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_BLEND_PIPE_CTL,
-			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(chan), val);
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
 }
 
 static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
@@ -89,15 +87,13 @@ static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
 	return 0;
 }
 
-int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
-				     int layer, struct drm_plane *plane)
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
+				   int overlay, 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;
 
-	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
@@ -107,7 +103,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating blender size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_BLEND_ATTR_INSIZE(chan),
+			     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
@@ -115,7 +111,7 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 					      state->crtc_h));
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
 			     SUN8I_MIXER_SIZE(state->crtc_w,
 					      state->crtc_h));
 	}
@@ -123,35 +119,33 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
 	/* Set the line width */
 	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
 		     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->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
 		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
 
 	return 0;
 }
 
-int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
-				       int layer, struct drm_plane *plane)
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
+				     int overlay, 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)
@@ -175,21 +169,19 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
 
 	val <<= SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
 	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
 
 	return 0;
 }
 
-int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
-				      int layer, struct drm_plane *plane)
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
+				    int overlay, 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;
-	/* Currently the first UI channel is used */
-	int chan = mixer->cfg->vi_num;
 	int bpp;
 
 	/* Get the physical address of the buffer in memory */
@@ -221,7 +213,7 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(channel, overlay),
 		     lower_32_bits(paddr));
 
 	return 0;
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 76f0b2bd91e2..70113c9ea2d1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -123,12 +123,12 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-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);
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, int channel,
+			      int overlay, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
+				   int overlay, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
+				     int overlay, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
+				    int overlay, struct drm_plane *plane);
 #endif /* _SUN8I_MIXER_H_ */
-- 
2.15.1

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

* [PATCH v2 11/27] drm/sun4i: Add constraints checking to DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (9 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 10/27] drm/sun4i: Start using layer id " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 12/27] drm/sun4i: Use values calculated by atomic check Jernej Skrabec
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Since current DE2 driver doesn't know how to scale yet, add atomic check
function which checks that.

Nice side effect of that function is that populates clipped coordinates
and checks visibility of the plane. That data will be used in the
future.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_layer.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
index 5aa6e2c9728e..40e6b83aef3b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -13,7 +13,9 @@
  * the License, or (at your option) any later version.
  */
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drmP.h>
 
@@ -26,6 +28,31 @@ struct sun8i_plane_desc {
 	       uint32_t                nformats;
 };
 
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+	return drm_plane_helper_check_state(state, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    true, true);
+}
+
 static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
 					       struct drm_plane_state *old_state)
 {
@@ -53,6 +80,7 @@ static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
 }
 
 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,
 };
-- 
2.15.1

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

* [PATCH v2 12/27] drm/sun4i: Use values calculated by atomic check
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (10 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 11/27] drm/sun4i: Add constraints checking to " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 13/27] drm/sun4i: Move line width setting in DE2 Jernej Skrabec
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Now that we have properly clipped coordinates in plane state structure,
use them.

This also fixes bug where source x and y were adjusted for negative
value, but width and height weren't. It wasn't discovered because
primary plane usually doesn't have negative coordinates.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_layer.c |  6 +++++
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 52 ++++++++++++++++---------------------
 2 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
index 40e6b83aef3b..1eced63f365d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -69,6 +69,12 @@ static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
 	struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
 	struct sun8i_mixer *mixer = layer->mixer;
 
+	if (!plane->state->visible) {
+		sun8i_mixer_layer_enable(mixer, layer->channel,
+					 layer->overlay, false);
+		return;
+	}
+
 	sun8i_mixer_update_layer_coord(mixer, layer->channel,
 				       layer->overlay, plane);
 	sun8i_mixer_update_layer_formats(mixer, layer->channel,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 2bf7ba1e5ba7..37fcc5ed18c5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -92,28 +92,34 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 {
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
+	u32 width, height, size;
 
 	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
 
+	/*
+	 * Same source and destination width and height are guaranteed
+	 * by atomic check function.
+	 */
+	width = drm_rect_width(&state->dst);
+	height = drm_rect_height(&state->dst);
+	size = SUN8I_MIXER_SIZE(width, height);
+
 	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->engine.regs, SUN8I_MIXER_GLOBAL_SIZE,
-			     SUN8I_MIXER_SIZE(state->crtc_w,
-					      state->crtc_h));
+				 width, height);
+		regmap_write(mixer->engine.regs,
+			     SUN8I_MIXER_GLOBAL_SIZE,
+			     size);
 		DRM_DEBUG_DRIVER("Updating blender size\n");
 		regmap_write(mixer->engine.regs,
 			     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
-			     SUN8I_MIXER_SIZE(state->crtc_w,
-					      state->crtc_h));
+			     size);
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
-			     SUN8I_MIXER_SIZE(state->crtc_w,
-					      state->crtc_h));
+			     size);
 		DRM_DEBUG_DRIVER("Updating channel size\n");
 		regmap_write(mixer->engine.regs,
 			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
-			     SUN8I_MIXER_SIZE(state->crtc_w,
-					      state->crtc_h));
+			     size);
 	}
 
 	/* Set the line width */
@@ -123,18 +129,17 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 		     fb->pitches[0]);
 
 	/* Set height and width */
-	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
-			 state->crtc_w, state->crtc_h);
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
-		     SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+		     size);
 
 	/* Set base coordinates */
 	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
-			 state->crtc_x, state->crtc_y);
+			 state->dst.x1, state->dst.y1);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
-		     SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
 
 	return 0;
 }
@@ -194,21 +199,8 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
 	paddr = gem->paddr + fb->offsets[0];
 
 	/* Fixup framebuffer address for src coordinates */
-	paddr += (state->src_x >> 16) * bpp;
-	paddr += (state->src_y >> 16) * fb->pitches[0];
-
-	/*
-	 * The hardware cannot correctly deal with negative crtc
-	 * coordinates, the display is cropped to the requested size,
-	 * but the display content is not moved.
-	 * Manually move the display content by fixup the framebuffer
-	 * address when crtc_x or crtc_y is negative, like what we
-	 * have did for src_x and src_y.
-	 */
-	if (state->crtc_x < 0)
-		paddr += -state->crtc_x * bpp;
-	if (state->crtc_y < 0)
-		paddr += -state->crtc_y * fb->pitches[0];
+	paddr += (state->src.x1 >> 16) * bpp;
+	paddr += (state->src.y1 >> 16) * fb->pitches[0];
 
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
-- 
2.15.1

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

* [PATCH v2 13/27] drm/sun4i: Move line width setting in DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (11 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 12/27] drm/sun4i: Use values calculated by atomic check Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 14/27] drm/sun4i: Move channel size related code " Jernej Skrabec
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Line width is a property of a framebuffer and it belongs to
sun8i_mixer_update_layer_buffer(). This will became even more obvious
when support for multi-plane formats will be added.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 37fcc5ed18c5..9635c30651d6 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -91,7 +91,6 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 				   int overlay, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
-	struct drm_framebuffer *fb = state->fb;
 	u32 width, height, size;
 
 	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
@@ -122,12 +121,6 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 			     size);
 	}
 
-	/* Set the line width */
-	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
-		     fb->pitches[0]);
-
 	/* Set height and width */
 	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
 	regmap_write(mixer->engine.regs,
@@ -202,6 +195,12 @@ int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
 	paddr += (state->src.x1 >> 16) * bpp;
 	paddr += (state->src.y1 >> 16) * fb->pitches[0];
 
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
+		     fb->pitches[0]);
+
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
 	regmap_write(mixer->engine.regs,
-- 
2.15.1

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

* [PATCH v2 14/27] drm/sun4i: Move channel size related code in DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (12 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 13/27] drm/sun4i: Move line width setting in DE2 Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 15/27] drm/sun4i: Move interlace " Jernej Skrabec
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Channel size should be set every time plane is changed, not only when
primary plane changes. Current code works only because only one
(primary) plane is supported at the moment.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 9635c30651d6..00c0cc6440e2 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -109,16 +109,8 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 		regmap_write(mixer->engine.regs,
 			     SUN8I_MIXER_GLOBAL_SIZE,
 			     size);
-		DRM_DEBUG_DRIVER("Updating blender size\n");
-		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
-			     size);
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
 			     size);
-		DRM_DEBUG_DRIVER("Updating channel size\n");
-		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
-			     size);
 	}
 
 	/* Set height and width */
@@ -126,6 +118,9 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
 		     size);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
+		     size);
 
 	/* Set base coordinates */
 	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
@@ -133,6 +128,9 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+		     size);
 
 	return 0;
 }
-- 
2.15.1

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

* [PATCH v2 15/27] drm/sun4i: Move interlace related code in DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (13 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 14/27] drm/sun4i: Move channel size related code " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 16/27] drm/sun4i: Add multi plane support to DE2 driver Jernej Skrabec
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

There is no point having code which sets interlace mode of mixer in
channel related function. Interlace mode will only change when CRTC
state will change, so let's move it to the block which is executed only
when primary plane state is changed.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 00c0cc6440e2..f35a08dc260b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -104,6 +104,9 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 	size = SUN8I_MIXER_SIZE(width, height);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		bool interlaced = false;
+		u32 val;
+
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
 				 width, height);
 		regmap_write(mixer->engine.regs,
@@ -111,6 +114,23 @@ int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 			     size);
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
 			     size);
+
+		if (state->crtc)
+			interlaced = state->crtc->state->adjusted_mode.flags
+				& DRM_MODE_FLAG_INTERLACE;
+
+		if (interlaced)
+			val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
+		else
+			val = 0;
+
+		regmap_update_bits(mixer->engine.regs,
+				   SUN8I_MIXER_BLEND_OUTCTL,
+				   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+				   val);
+
+		DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+				 interlaced ? "on" : "off");
 	}
 
 	/* Set height and width */
@@ -140,22 +160,9 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
 {
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
-	bool interlaced = false;
 	u32 val;
 	int ret;
 
-	if (plane->state->crtc)
-		interlaced = plane->state->crtc->state->adjusted_mode.flags
-			& DRM_MODE_FLAG_INTERLACE;
-
-	regmap_update_bits(mixer->engine.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) {
-- 
2.15.1

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

* [PATCH v2 16/27] drm/sun4i: Add multi plane support to DE2 driver
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (14 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 15/27] drm/sun4i: Move interlace " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 17/27] drm/sun4i: Add support for all HW supported DE2 RGB formats Jernej Skrabec
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Support for multiple UI planes can now be easily enabled just by adding
more planes with different index.

For now, add immutable zpos property.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_layer.c | 38 +++++++++++++++++--------------------
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
index 1eced63f365d..65d6eb7d5cbf 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -22,12 +22,6 @@
 #include "sun8i_layer.h"
 #include "sun8i_mixer.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)
 {
@@ -106,35 +100,38 @@ static const uint32_t sun8i_mixer_layer_formats[] = {
 	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 sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
 						struct sun8i_mixer *mixer,
-						const struct sun8i_plane_desc *plane)
+						int index)
 {
 	struct sun8i_layer *layer;
+	enum drm_plane_type type;
 	int ret;
 
 	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
 	if (!layer)
 		return ERR_PTR(-ENOMEM);
 
+	type = index == 0 ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+
 	/* possible crtcs are set later */
 	ret = drm_universal_plane_init(drm, &layer->plane, 0,
 				       &sun8i_mixer_layer_funcs,
-				       plane->formats, plane->nformats,
-				       NULL, plane->type, NULL);
+				       sun8i_mixer_layer_formats,
+				       ARRAY_SIZE(sun8i_mixer_layer_formats),
+				       NULL, type, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
 		return ERR_PTR(ret);
 	}
 
+	/* fixed zpos for now */
+	ret = drm_plane_create_zpos_immutable_property(&layer->plane, index);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't add zpos property\n");
+		return ERR_PTR(ret);
+	}
+
 	drm_plane_helper_add(&layer->plane,
 			     &sun8i_mixer_layer_helper_funcs);
 	layer->mixer = mixer;
@@ -149,16 +146,15 @@ struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
 	int i;
 
-	planes = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+	planes = devm_kcalloc(drm->dev, mixer->cfg->ui_num + 1,
 			      sizeof(*planes), GFP_KERNEL);
 	if (!planes)
 		return ERR_PTR(-ENOMEM);
 
-	for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
-		const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+	for (i = 0; i < mixer->cfg->ui_num; i++) {
 		struct sun8i_layer *layer;
 
-		layer = sun8i_layer_init_one(drm, mixer, plane);
+		layer = sun8i_layer_init_one(drm, mixer, i);
 		if (IS_ERR(layer)) {
 			dev_err(drm->dev, "Couldn't initialize %s plane\n",
 				i ? "overlay" : "primary");
-- 
2.15.1

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

* [PATCH v2 17/27] drm/sun4i: Add support for all HW supported DE2 RGB formats
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (15 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 16/27] drm/sun4i: Add multi plane support to DE2 driver Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 18/27] drm/sun4i: Reorganize UI layer code in DE2 Jernej Skrabec
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Currently only a few RGB formats are supported by the DE2 driver. Add
support for all formats supported by the HW.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_layer.c |  19 ++++-
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 134 ++++++++++++++++++++++++++++--------
 drivers/gpu/drm/sun4i/sun8i_mixer.h |  17 +++++
 3 files changed, 139 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
index 65d6eb7d5cbf..cdeda083c60e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -95,8 +95,25 @@ static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
 };
 
 static const uint32_t sun8i_mixer_layer_formats[] = {
-	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_ABGR4444,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_BGRA5551,
+	DRM_FORMAT_BGRA4444,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_RGBA5551,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index f35a08dc260b..d49eed97b452 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -29,6 +29,105 @@
 #include "sun8i_layer.h"
 #include "sunxi_engine.h"
 
+struct de2_fmt_info {
+	u32 drm_fmt;
+	u32 de2_fmt;
+};
+
+static const struct de2_fmt_info de2_formats[] = {
+	{
+		.drm_fmt = DRM_FORMAT_ARGB8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ABGR8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGBA8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGRA8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_XRGB8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_XRGB8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_XBGR8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_XBGR8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGBX8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBX8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGRX8888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRX8888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGB888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGR888,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGR888,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGB565,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGB565,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGR565,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGR565,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ARGB4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ABGR4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGBA4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGRA4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ARGB1555,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ABGR1555,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGBA5551,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGRA5551,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
+	},
+};
+
+static const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(de2_formats); ++i)
+		if (de2_formats[i].drm_fmt == format)
+			return &de2_formats[i];
+
+	return NULL;
+}
+
 static void sun8i_mixer_commit(struct sunxi_engine *engine)
 {
 	DRM_DEBUG_DRIVER("Committing changes\n");
@@ -64,29 +163,6 @@ void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, int channel,
 			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
 }
 
-static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
-					     u32 format, u32 *mode)
-{
-	switch (format) {
-	case DRM_FORMAT_ARGB8888:
-		*mode = SUN8I_MIXER_FBFMT_ARGB8888;
-		break;
-
-	case DRM_FORMAT_XRGB8888:
-		*mode = SUN8I_MIXER_FBFMT_XRGB8888;
-		break;
-
-	case DRM_FORMAT_RGB888:
-		*mode = SUN8I_MIXER_FBFMT_RGB888;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
 				   int overlay, struct drm_plane *plane)
 {
@@ -159,18 +235,16 @@ int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
 				     int overlay, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
-	struct drm_framebuffer *fb = state->fb;
+	const struct de2_fmt_info *fmt_info;
 	u32 val;
-	int ret;
 
-	ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
-						&val);
-	if (ret) {
+	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
+	if (!fmt_info) {
 		DRM_DEBUG_DRIVER("Invalid format\n");
-		return ret;
+		return -EINVAL;
 	}
 
-	val <<= SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
+	val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 70113c9ea2d1..e23525b9cf6d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -82,8 +82,25 @@
 #define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
 
 #define SUN8I_MIXER_FBFMT_ARGB8888	0
+#define SUN8I_MIXER_FBFMT_ABGR8888	1
+#define SUN8I_MIXER_FBFMT_RGBA8888	2
+#define SUN8I_MIXER_FBFMT_BGRA8888	3
 #define SUN8I_MIXER_FBFMT_XRGB8888	4
+#define SUN8I_MIXER_FBFMT_XBGR8888	5
+#define SUN8I_MIXER_FBFMT_RGBX8888	6
+#define SUN8I_MIXER_FBFMT_BGRX8888	7
 #define SUN8I_MIXER_FBFMT_RGB888	8
+#define SUN8I_MIXER_FBFMT_BGR888	9
+#define SUN8I_MIXER_FBFMT_RGB565	10
+#define SUN8I_MIXER_FBFMT_BGR565	11
+#define SUN8I_MIXER_FBFMT_ARGB4444	12
+#define SUN8I_MIXER_FBFMT_ABGR4444	13
+#define SUN8I_MIXER_FBFMT_RGBA4444	14
+#define SUN8I_MIXER_FBFMT_BGRA4444	15
+#define SUN8I_MIXER_FBFMT_ARGB1555	16
+#define SUN8I_MIXER_FBFMT_ABGR1555	17
+#define SUN8I_MIXER_FBFMT_RGBA5551	18
+#define SUN8I_MIXER_FBFMT_BGRA5551	19
 
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
-- 
2.15.1

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

* [PATCH v2 18/27] drm/sun4i: Reorganize UI layer code in DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (16 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 17/27] drm/sun4i: Add support for all HW supported DE2 RGB formats Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 19/27] drm/sun4i: Add support for DE2 VI planes Jernej Skrabec
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Till now, DE2 driver supported only UI planes. Before we add support for
VI planes, lets split out UI layer specific code from common parts. This
commit does the following:
- renames sun8i_layer.c to sun8i_ui_layer.c
- moves UI channel specific code to sun8i_ui_layer.c
- moves common code from sun8i_layer.c to sun8i_mixer.c
- renames function and structure names so it is apparent where they
belong to

No functional change is made.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/Makefile         |   2 +-
 drivers/gpu/drm/sun4i/sun8i_layer.c    | 187 --------------------
 drivers/gpu/drm/sun4i/sun8i_layer.h    |  37 ----
 drivers/gpu/drm/sun4i/sun8i_mixer.c    | 174 +++---------------
 drivers/gpu/drm/sun4i/sun8i_mixer.h    |  43 +----
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 314 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_ui_layer.h |  63 +++++++
 7 files changed, 406 insertions(+), 414 deletions(-)
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
 delete mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_layer.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 0c2f8c7facae..0a839674cd1d 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
 sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
 sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun8i-mixer-y			+= sun8i_mixer.o sun8i_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
deleted file mode 100644
index cdeda083c60e..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * 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.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drmP.h>
-
-#include "sun8i_layer.h"
-#include "sun8i_mixer.h"
-
-static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
-					  struct drm_plane_state *state)
-{
-	struct drm_crtc *crtc = state->crtc;
-	struct drm_crtc_state *crtc_state;
-	struct drm_rect clip;
-
-	if (!crtc)
-		return 0;
-
-	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
-	if (WARN_ON(!crtc_state))
-		return -EINVAL;
-
-	clip.x1 = 0;
-	clip.y1 = 0;
-	clip.x2 = crtc_state->adjusted_mode.hdisplay;
-	clip.y2 = crtc_state->adjusted_mode.vdisplay;
-
-	return drm_plane_helper_check_state(state, &clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    true, true);
-}
-
-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->channel,
-				 layer->overlay, 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;
-
-	if (!plane->state->visible) {
-		sun8i_mixer_layer_enable(mixer, layer->channel,
-					 layer->overlay, false);
-		return;
-	}
-
-	sun8i_mixer_update_layer_coord(mixer, layer->channel,
-				       layer->overlay, plane);
-	sun8i_mixer_update_layer_formats(mixer, layer->channel,
-					 layer->overlay, plane);
-	sun8i_mixer_update_layer_buffer(mixer, layer->channel,
-					layer->overlay, plane);
-	sun8i_mixer_layer_enable(mixer, layer->channel,
-				 layer->overlay, 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_ABGR1555,
-	DRM_FORMAT_ABGR4444,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_ARGB1555,
-	DRM_FORMAT_ARGB4444,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_BGR565,
-	DRM_FORMAT_BGR888,
-	DRM_FORMAT_BGRA5551,
-	DRM_FORMAT_BGRA4444,
-	DRM_FORMAT_BGRA8888,
-	DRM_FORMAT_BGRX8888,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_RGB888,
-	DRM_FORMAT_RGBA4444,
-	DRM_FORMAT_RGBA5551,
-	DRM_FORMAT_RGBA8888,
-	DRM_FORMAT_RGBX8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB8888,
-};
-
-static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
-						struct sun8i_mixer *mixer,
-						int index)
-{
-	struct sun8i_layer *layer;
-	enum drm_plane_type type;
-	int ret;
-
-	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
-	if (!layer)
-		return ERR_PTR(-ENOMEM);
-
-	type = index == 0 ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
-
-	/* possible crtcs are set later */
-	ret = drm_universal_plane_init(drm, &layer->plane, 0,
-				       &sun8i_mixer_layer_funcs,
-				       sun8i_mixer_layer_formats,
-				       ARRAY_SIZE(sun8i_mixer_layer_formats),
-				       NULL, type, NULL);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't initialize layer\n");
-		return ERR_PTR(ret);
-	}
-
-	/* fixed zpos for now */
-	ret = drm_plane_create_zpos_immutable_property(&layer->plane, index);
-	if (ret) {
-		dev_err(drm->dev, "Couldn't add zpos property\n");
-		return ERR_PTR(ret);
-	}
-
-	drm_plane_helper_add(&layer->plane,
-			     &sun8i_mixer_layer_helper_funcs);
-	layer->mixer = mixer;
-
-	return layer;
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine)
-{
-	struct drm_plane **planes;
-	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
-	int i;
-
-	planes = devm_kcalloc(drm->dev, mixer->cfg->ui_num + 1,
-			      sizeof(*planes), GFP_KERNEL);
-	if (!planes)
-		return ERR_PTR(-ENOMEM);
-
-	for (i = 0; i < mixer->cfg->ui_num; i++) {
-		struct sun8i_layer *layer;
-
-		layer = sun8i_layer_init_one(drm, mixer, i);
-		if (IS_ERR(layer)) {
-			dev_err(drm->dev, "Couldn't initialize %s plane\n",
-				i ? "overlay" : "primary");
-			return ERR_CAST(layer);
-		};
-
-		layer->channel = mixer->cfg->vi_num + i;
-		layer->overlay = 0;
-		planes[i] = &layer->plane;
-	};
-
-	return planes;
-}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
deleted file mode 100644
index d246e0dd3d48..000000000000
--- a/drivers/gpu/drm/sun4i/sun8i_layer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
- *
- * 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 sunxi_engine;
-
-struct sun8i_layer {
-	struct drm_plane	plane;
-	struct sun4i_drv	*drv;
-	struct sun8i_mixer	*mixer;
-	int			channel;
-	int			overlay;
-};
-
-static inline struct sun8i_layer *
-plane_to_sun8i_layer(struct drm_plane *plane)
-{
-	return container_of(plane, struct sun8i_layer, plane);
-}
-
-struct drm_plane **sun8i_layers_init(struct drm_device *drm,
-				     struct sunxi_engine *engine);
-#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index d49eed97b452..1de98ad9f6c1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -26,14 +26,9 @@
 
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
-#include "sun8i_layer.h"
+#include "sun8i_ui_layer.h"
 #include "sunxi_engine.h"
 
-struct de2_fmt_info {
-	u32 drm_fmt;
-	u32 de2_fmt;
-};
-
 static const struct de2_fmt_info de2_formats[] = {
 	{
 		.drm_fmt = DRM_FORMAT_ARGB8888,
@@ -117,7 +112,7 @@ static const struct de2_fmt_info de2_formats[] = {
 	},
 };
 
-static const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
+const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
 {
 	unsigned int i;
 
@@ -136,157 +131,32 @@ static void sun8i_mixer_commit(struct sunxi_engine *engine)
 		     SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, int channel,
-			      int overlay, bool enable)
-{
-	u32 val;
-
-	DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
-			 enable ? "En" : "Dis", channel, overlay);
-
-	if (enable)
-		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
-	else
-		val = 0;
-
-	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
-
-	if (enable)
-		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
-	else
-		val = 0;
-
-	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_BLEND_PIPE_CTL,
-			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
-}
-
-int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
-				   int overlay, struct drm_plane *plane)
-{
-	struct drm_plane_state *state = plane->state;
-	u32 width, height, size;
-
-	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
-
-	/*
-	 * Same source and destination width and height are guaranteed
-	 * by atomic check function.
-	 */
-	width = drm_rect_width(&state->dst);
-	height = drm_rect_height(&state->dst);
-	size = SUN8I_MIXER_SIZE(width, height);
-
-	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
-		bool interlaced = false;
-		u32 val;
-
-		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
-				 width, height);
-		regmap_write(mixer->engine.regs,
-			     SUN8I_MIXER_GLOBAL_SIZE,
-			     size);
-		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
-			     size);
-
-		if (state->crtc)
-			interlaced = state->crtc->state->adjusted_mode.flags
-				& DRM_MODE_FLAG_INTERLACE;
-
-		if (interlaced)
-			val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
-		else
-			val = 0;
-
-		regmap_update_bits(mixer->engine.regs,
-				   SUN8I_MIXER_BLEND_OUTCTL,
-				   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
-				   val);
-
-		DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
-				 interlaced ? "on" : "off");
-	}
-
-	/* Set height and width */
-	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
-		     size);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
-		     size);
-
-	/* Set base coordinates */
-	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
-			 state->dst.x1, state->dst.y1);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
-		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
-		     size);
-
-	return 0;
-}
-
-int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
-				     int overlay, struct drm_plane *plane)
+static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
+					    struct sunxi_engine *engine)
 {
-	struct drm_plane_state *state = plane->state;
-	const struct de2_fmt_info *fmt_info;
-	u32 val;
+	struct drm_plane **planes;
+	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
+	int i;
 
-	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
-	if (!fmt_info) {
-		DRM_DEBUG_DRIVER("Invalid format\n");
-		return -EINVAL;
-	}
+	planes = devm_kcalloc(drm->dev, mixer->cfg->ui_num + 1,
+			      sizeof(*planes), GFP_KERNEL);
+	if (!planes)
+		return ERR_PTR(-ENOMEM);
 
-	val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
-	regmap_update_bits(mixer->engine.regs,
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
-			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+	for (i = 0; i < mixer->cfg->ui_num; i++) {
+		struct sun8i_ui_layer *layer;
 
-	return 0;
-}
+		layer = sun8i_ui_layer_init_one(drm, mixer, i);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
 
-int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
-				    int overlay, 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;
-	int bpp;
+		planes[i] = &layer->plane;
+	};
 
-	/* 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];
-
-	/* Fixup framebuffer address for src coordinates */
-	paddr += (state->src.x1 >> 16) * bpp;
-	paddr += (state->src.y1 >> 16) * fb->pitches[0];
-
-	/* Set the line width */
-	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
-		     fb->pitches[0]);
-
-	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
-
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(channel, overlay),
-		     lower_32_bits(paddr));
-
-	return 0;
+	return planes;
 }
 
 static const struct sunxi_engine_ops sun8i_engine_ops = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index e23525b9cf6d..bad0969ac105 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -52,35 +52,6 @@
 
 #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(12, 8)
-#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET	8
-#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
-
 #define SUN8I_MIXER_FBFMT_ARGB8888	0
 #define SUN8I_MIXER_FBFMT_ABGR8888	1
 #define SUN8I_MIXER_FBFMT_RGBA8888	2
@@ -118,6 +89,11 @@
 #define SUN8I_MIXER_FCC_EN			0xaa000
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
+struct de2_fmt_info {
+	u32 drm_fmt;
+	u32 de2_fmt;
+};
+
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
@@ -140,12 +116,5 @@ engine_to_sun8i_mixer(struct sunxi_engine *engine)
 	return container_of(engine, struct sun8i_mixer, engine);
 }
 
-void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer, int channel,
-			      int overlay, bool enable);
-int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer, int channel,
-				   int overlay, struct drm_plane *plane);
-int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer, int channel,
-				     int overlay, struct drm_plane *plane);
-int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer, int channel,
-				    int overlay, struct drm_plane *plane);
+const struct de2_fmt_info *sun8i_mixer_format_info(u32 format);
 #endif /* _SUN8I_MIXER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
new file mode 100644
index 000000000000..3ecf39c50111
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * 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.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 <drm/drmP.h>
+
+#include "sun8i_ui_layer.h"
+#include "sun8i_mixer.h"
+
+static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
+				  int overlay, bool enable)
+{
+	u32 val;
+
+	DRM_DEBUG_DRIVER("%sabling channel %d overlay %d\n",
+			 enable ? "En" : "Dis", channel, overlay);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+	if (enable)
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_BLEND_PIPE_CTL,
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+}
+
+static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
+				       int overlay, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	u32 width, height, size;
+
+	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
+
+	/*
+	 * Same source and destination width and height are guaranteed
+	 * by atomic check function.
+	 */
+	width = drm_rect_width(&state->dst);
+	height = drm_rect_height(&state->dst);
+	size = SUN8I_MIXER_SIZE(width, height);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		bool interlaced = false;
+		u32 val;
+
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 width, height);
+		regmap_write(mixer->engine.regs,
+			     SUN8I_MIXER_GLOBAL_SIZE,
+			     size);
+		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
+			     size);
+
+		if (state->crtc)
+			interlaced = state->crtc->state->adjusted_mode.flags
+				& DRM_MODE_FLAG_INTERLACE;
+
+		if (interlaced)
+			val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED;
+		else
+			val = 0;
+
+		regmap_update_bits(mixer->engine.regs,
+				   SUN8I_MIXER_BLEND_OUTCTL,
+				   SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+				   val);
+
+		DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+				 interlaced ? "on" : "off");
+	}
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
+		     size);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
+		     size);
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->dst.x1, state->dst.y1);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+		     size);
+
+	return 0;
+}
+
+static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel,
+					 int overlay, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	const struct de2_fmt_info *fmt_info;
+	u32 val;
+
+	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
+	if (!fmt_info) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return -EINVAL;
+	}
+
+	val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET;
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
+			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+	return 0;
+}
+
+static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
+					int overlay, 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;
+	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];
+
+	/* Fixup framebuffer address for src coordinates */
+	paddr += (state->src.x1 >> 16) * bpp;
+	paddr += (state->src.y1 >> 16) * fb->pitches[0];
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(channel, overlay),
+		     fb->pitches[0]);
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(channel, overlay),
+		     lower_32_bits(paddr));
+
+	return 0;
+}
+
+static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
+				       struct drm_plane_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+	return drm_plane_helper_check_state(state, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    true, true);
+}
+
+static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false);
+}
+
+static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	if (!plane->state->visible) {
+		sun8i_ui_layer_enable(mixer, layer->channel,
+				      layer->overlay, false);
+		return;
+	}
+
+	sun8i_ui_layer_update_coord(mixer, layer->channel,
+				    layer->overlay, plane);
+	sun8i_ui_layer_update_formats(mixer, layer->channel,
+				      layer->overlay, plane);
+	sun8i_ui_layer_update_buffer(mixer, layer->channel,
+				     layer->overlay, plane);
+	sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
+	.atomic_check	= sun8i_ui_layer_atomic_check,
+	.atomic_disable	= sun8i_ui_layer_atomic_disable,
+	.atomic_update	= sun8i_ui_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_ui_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 u32 sun8i_ui_layer_formats[] = {
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_ABGR4444,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_BGRA5551,
+	DRM_FORMAT_BGRA4444,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_RGBA5551,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB8888,
+};
+
+struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
+					       struct sun8i_mixer *mixer,
+					       int index)
+{
+	enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
+	int channel = mixer->cfg->vi_num + index;
+	struct sun8i_ui_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	if (index == 0)
+		type = DRM_PLANE_TYPE_PRIMARY;
+
+	/* possible crtcs are set later */
+	ret = drm_universal_plane_init(drm, &layer->plane, 0,
+				       &sun8i_ui_layer_funcs,
+				       sun8i_ui_layer_formats,
+				       ARRAY_SIZE(sun8i_ui_layer_formats),
+				       NULL, type, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	/* fixed zpos for now */
+	ret = drm_plane_create_zpos_immutable_property(&layer->plane, channel);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't add zpos property\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane, &sun8i_ui_layer_helper_funcs);
+	layer->mixer = mixer;
+	layer->channel = channel;
+	layer->overlay = 0;
+
+	return layer;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.h b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h
new file mode 100644
index 000000000000..123b15ea9918
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy@aosc.io>
+ *
+ * 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_UI_LAYER_H_
+#define _SUN8I_UI_LAYER_H_
+
+#include <drm/drm_plane.h>
+
+#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(12, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_OFFSET	8
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
+
+struct sun8i_mixer;
+
+struct sun8i_ui_layer {
+	struct drm_plane	plane;
+	struct sun8i_mixer	*mixer;
+	int			channel;
+	int			overlay;
+};
+
+static inline struct sun8i_ui_layer *
+plane_to_sun8i_ui_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_ui_layer, plane);
+}
+
+struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
+					       struct sun8i_mixer *mixer,
+					       int index);
+#endif /* _SUN8I_UI_LAYER_H_ */
-- 
2.15.1

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

* [PATCH v2 19/27] drm/sun4i: Add support for DE2 VI planes
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (17 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 18/27] drm/sun4i: Reorganize UI layer code in DE2 Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 20/27] drm/sun4i: Add scaler configuration to DE2 mixers Jernej Skrabec
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

This commit adds basic support for VI planes. They are meant for video
overlay and because of that they support YUV formats too. However, using
YUV format is not straightforward, so only RGB formats are supported for
now.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/Makefile         |   3 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c    |  19 ++-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 276 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h |  51 ++++++
 4 files changed, 346 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_layer.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_layer.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 0a839674cd1d..b0a2eb2c4806 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,8 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_enc.o
 sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
 sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
-sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o
+sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
+				   sun8i_vi_layer.o
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 1de98ad9f6c1..888620b1d3f1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -27,6 +27,7 @@
 #include "sun4i_drv.h"
 #include "sun8i_mixer.h"
 #include "sun8i_ui_layer.h"
+#include "sun8i_vi_layer.h"
 #include "sunxi_engine.h"
 
 static const struct de2_fmt_info de2_formats[] = {
@@ -138,11 +139,25 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 	struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine);
 	int i;
 
-	planes = devm_kcalloc(drm->dev, mixer->cfg->ui_num + 1,
+	planes = devm_kcalloc(drm->dev,
+			      mixer->cfg->vi_num + mixer->cfg->ui_num + 1,
 			      sizeof(*planes), GFP_KERNEL);
 	if (!planes)
 		return ERR_PTR(-ENOMEM);
 
+	for (i = 0; i < mixer->cfg->vi_num; i++) {
+		struct sun8i_vi_layer *layer;
+
+		layer = sun8i_vi_layer_init_one(drm, mixer, i);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev,
+				"Couldn't initialize overlay plane\n");
+			return ERR_CAST(layer);
+		};
+
+		planes[i] = &layer->plane;
+	};
+
 	for (i = 0; i < mixer->cfg->ui_num; i++) {
 		struct sun8i_ui_layer *layer;
 
@@ -153,7 +168,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
 			return ERR_CAST(layer);
 		};
 
-		planes[i] = &layer->plane;
+		planes[mixer->cfg->vi_num + i] = &layer->plane;
 	};
 
 	return planes;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
new file mode 100644
index 000000000000..b78d4f3e2b48
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * 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.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 <drm/drmP.h>
+
+#include "sun8i_vi_layer.h"
+#include "sun8i_mixer.h"
+
+static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
+				  int overlay, bool enable)
+{
+	u32 val;
+
+	DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n",
+			 enable ? "En" : "Dis", channel, overlay);
+
+	if (enable)
+		val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
+
+	if (enable)
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_BLEND_PIPE_CTL,
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+}
+
+static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
+				       int overlay, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	u32 width, height, size;
+
+	DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
+			 channel, overlay);
+	/*
+	 * Same source and destination width and height are guaranteed
+	 * by atomic check function.
+	 */
+	width = drm_rect_width(&state->dst);
+	height = drm_rect_height(&state->dst);
+	size = SUN8I_MIXER_SIZE(width, height);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
+		     size);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
+		     size);
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->dst.x1, state->dst.y1);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+		     size);
+
+	return 0;
+}
+
+static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
+					 int overlay, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	const struct de2_fmt_info *fmt_info;
+	u32 val;
+
+	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
+	if (!fmt_info) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return -EINVAL;
+	}
+
+	val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK |
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE,
+			   val | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE);
+
+	return 0;
+}
+
+static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
+					int overlay, 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;
+	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];
+
+	/* Fixup framebuffer address for src coordinates */
+	paddr += (state->src.x1 >> 16) * bpp;
+	paddr += (state->src.y1 >> 16) * fb->pitches[0];
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel, overlay, 0),
+		     fb->pitches[0]);
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel, overlay, 0),
+		     lower_32_bits(paddr));
+
+	return 0;
+}
+
+static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
+				       struct drm_plane_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+	return drm_plane_helper_check_state(state, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    true, true);
+}
+
+static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false);
+}
+
+static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+	struct sun8i_mixer *mixer = layer->mixer;
+
+	if (!plane->state->visible) {
+		sun8i_vi_layer_enable(mixer, layer->channel,
+				      layer->overlay, false);
+		return;
+	}
+
+	sun8i_vi_layer_update_coord(mixer, layer->channel,
+				    layer->overlay, plane);
+	sun8i_vi_layer_update_formats(mixer, layer->channel,
+				      layer->overlay, plane);
+	sun8i_vi_layer_update_buffer(mixer, layer->channel,
+				     layer->overlay, plane);
+	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
+	.atomic_check	= sun8i_vi_layer_atomic_check,
+	.atomic_disable	= sun8i_vi_layer_atomic_disable,
+	.atomic_update	= sun8i_vi_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_vi_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,
+};
+
+/*
+ * While all RGB formats are supported, VI planes don't support
+ * alpha blending, so there is no point having formats with alpha
+ * channel if their opaque analog exist.
+ */
+static const u32 sun8i_vi_layer_formats[] = {
+	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_ABGR4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_BGRA5551,
+	DRM_FORMAT_BGRA4444,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_RGBA5551,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB8888,
+};
+
+struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
+					       struct sun8i_mixer *mixer,
+					       int index)
+{
+	struct sun8i_vi_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_vi_layer_funcs,
+				       sun8i_vi_layer_formats,
+				       ARRAY_SIZE(sun8i_vi_layer_formats),
+				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	/* fixed zpos for now */
+	ret = drm_plane_create_zpos_immutable_property(&layer->plane, index);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't add zpos property\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs);
+	layer->mixer = mixer;
+	layer->channel = index;
+	layer->overlay = 0;
+
+	return layer;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
new file mode 100644
index 000000000000..6996627a0a76
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * 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_VI_LAYER_H_
+#define _SUN8I_VI_LAYER_H_
+
+#include <drm/drm_plane.h>
+
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch, layer) \
+		(0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch, layer) \
+		(0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_VI_LAYER_COORD(ch, layer) \
+		(0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch, layer, plane) \
+		(0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0xc + 4 * (plane))
+#define SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch, layer, plane) \
+		(0x2000 + 0x1000 * (ch) + 0x30 * (layer) + 0x18 + 4 * (plane))
+#define SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch)	(0x2000 + 0x1000 * (ch) + 0xe8)
+
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN		BIT(0)
+/* RGB mode should be set for RGB formats and cleared for YCbCr */
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE		BIT(15)
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET	8
+#define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK	GENMASK(12, 8)
+
+struct sun8i_mixer;
+
+struct sun8i_vi_layer {
+	struct drm_plane	plane;
+	struct sun8i_mixer	*mixer;
+	int			channel;
+	int			overlay;
+};
+
+static inline struct sun8i_vi_layer *
+plane_to_sun8i_vi_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun8i_vi_layer, plane);
+}
+
+struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
+					       struct sun8i_mixer *mixer,
+					       int index);
+#endif /* _SUN8I_VI_LAYER_H_ */
-- 
2.15.1

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

* [PATCH v2 20/27] drm/sun4i: Add scaler configuration to DE2 mixers
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (18 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 19/27] drm/sun4i: Add support for DE2 VI planes Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 21/27] drm/sun4i: Add support for HW scaling to DE2 Jernej Skrabec
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

No all SoCs support scaling on all channels. For example, V3s support
scaling only on VI channels. Because of that, add additional
configuration bitmask which tells which channel support scaler.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c |  1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 888620b1d3f1..e3296a060352 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -336,6 +336,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
 static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.vi_num = 2,
 	.ui_num = 1,
+	.scaler_mask = 0x3,
 };
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index bad0969ac105..a6270b307ae5 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -94,9 +94,19 @@ struct de2_fmt_info {
 	u32 de2_fmt;
 };
 
+/**
+ * struct sun8i_mixer_cfg - mixer HW configuration
+ * @vi_num: number of VI channels
+ * @ui_num: number of UI channels
+ * @scaler_mask: bitmask which tells which channel supports scaling
+ *	First, scaler supports for VI channels is defined and after that, scaler
+ *	support for UI channels. For example, if mixer has 2 VI channels without
+ *	scaler and 2 UI channels with scaler, bitmask would be 0xC.
+ */
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
+	int		scaler_mask;
 };
 
 struct sun8i_mixer {
-- 
2.15.1

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

* [PATCH v2 21/27] drm/sun4i: Add support for HW scaling to DE2
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (19 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 20/27] drm/sun4i: Add scaler configuration to DE2 mixers Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 22/27] drm/sun4i: Add CCSC property to DE2 configuration Jernej Skrabec
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Scaling is currently supported only for RGB framebuffers

Coefficients and algorithm which coefficients to select are taken
from BSP driver.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/Makefile          |   3 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.h     |   4 -
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c  |  73 +++--
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c | 172 ++++++++++
 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h |  49 +++
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c  |  62 +++-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 535 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h |  56 ++++
 8 files changed, 915 insertions(+), 39 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_ui_scaler.h
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index b0a2eb2c4806..a458ddbf4a8e 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -10,7 +10,8 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_i2c.o
 sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
 sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
-				   sun8i_vi_layer.o
+				   sun8i_vi_layer.o sun8i_ui_scaler.o \
+				   sun8i_vi_scaler.o
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index a6270b307ae5..9bbd762d26f7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -77,10 +77,6 @@
  * These sub-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
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 3ecf39c50111..3cf0729cc7e9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -24,6 +24,7 @@
 
 #include "sun8i_ui_layer.h"
 #include "sun8i_mixer.h"
+#include "sun8i_ui_scaler.h"
 
 static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
 				  int overlay, bool enable)
@@ -56,29 +57,35 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 				       int overlay, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
-	u32 width, height, size;
+	u32 src_w, src_h, dst_w, dst_h;
+	u32 outsize, insize;
+	u32 hphase, vphase;
 
-	DRM_DEBUG_DRIVER("Updating channel %d overlay %d\n", channel, overlay);
+	DRM_DEBUG_DRIVER("Updating UI channel %d overlay %d\n",
+			 channel, overlay);
 
-	/*
-	 * Same source and destination width and height are guaranteed
-	 * by atomic check function.
-	 */
-	width = drm_rect_width(&state->dst);
-	height = drm_rect_height(&state->dst);
-	size = SUN8I_MIXER_SIZE(width, height);
+	src_w = drm_rect_width(&state->src) >> 16;
+	src_h = drm_rect_height(&state->src) >> 16;
+	dst_w = drm_rect_width(&state->dst);
+	dst_h = drm_rect_height(&state->dst);
+
+	hphase = state->src.x1 & 0xffff;
+	vphase = state->src.y1 & 0xffff;
+
+	insize = SUN8I_MIXER_SIZE(src_w, src_h);
+	outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
 
 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
 		bool interlaced = false;
 		u32 val;
 
 		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
-				 width, height);
+				 dst_w, dst_h);
 		regmap_write(mixer->engine.regs,
 			     SUN8I_MIXER_GLOBAL_SIZE,
-			     size);
+			     outsize);
 		regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_OUTSIZE,
-			     size);
+			     outsize);
 
 		if (state->crtc)
 			interlaced = state->crtc->state->adjusted_mode.flags
@@ -99,23 +106,42 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	}
 
 	/* Set height and width */
-	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
+	DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
+			 state->src.x1 >> 16, state->src.y1 >> 16);
+	DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_UI_LAYER_SIZE(channel, overlay),
-		     size);
+		     insize);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_UI_OVL_SIZE(channel),
-		     size);
+		     insize);
+
+	if (insize != outsize || hphase || vphase) {
+		u32 hscale, vscale;
+
+		DRM_DEBUG_DRIVER("HW scaling is enabled\n");
+
+		hscale = state->src_w / state->crtc_w;
+		vscale = state->src_h / state->crtc_h;
+
+		sun8i_ui_scaler_setup(mixer, channel, src_w, src_h, dst_w,
+				      dst_h, hscale, vscale, hphase, vphase);
+		sun8i_ui_scaler_enable(mixer, channel, true);
+	} else {
+		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
+		sun8i_ui_scaler_enable(mixer, channel, false);
+	}
 
 	/* Set base coordinates */
-	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+	DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 			 state->dst.x1, state->dst.y1);
+	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
-		     size);
+		     outsize);
 
 	return 0;
 }
@@ -181,8 +207,10 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
 				       struct drm_plane_state *state)
 {
+	struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
 	struct drm_crtc *crtc = state->crtc;
 	struct drm_crtc_state *crtc_state;
+	int min_scale, max_scale;
 	struct drm_rect clip;
 
 	if (!crtc)
@@ -197,9 +225,16 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
 	clip.x2 = crtc_state->adjusted_mode.hdisplay;
 	clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
+	min_scale = DRM_PLANE_HELPER_NO_SCALING;
+	max_scale = DRM_PLANE_HELPER_NO_SCALING;
+
+	if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
+		min_scale = SUN8I_UI_SCALER_SCALE_MIN;
+		max_scale = SUN8I_UI_SCALER_SCALE_MAX;
+	}
+
 	return drm_plane_helper_check_state(state, &clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
+					    min_scale, max_scale,
 					    true, true);
 }
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
new file mode 100644
index 000000000000..6bb2aa164c8e
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Coefficients are taken from BSP driver, which is:
+ * Copyright (C) 2014-2015 Allwinner
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "sun8i_ui_scaler.h"
+
+static const u32 lan2coefftab16[240] = {
+	0x00004000, 0x00033ffe, 0x00063efc, 0x000a3bfb,
+	0xff0f37fb, 0xfe1433fb, 0xfd192ffb, 0xfd1f29fb,
+	0xfc2424fc, 0xfb291ffd, 0xfb2f19fd, 0xfb3314fe,
+	0xfb370fff, 0xfb3b0a00, 0xfc3e0600, 0xfe3f0300,
+
+	0xff053804, 0xff083801, 0xff0a3700, 0xff0e34ff,
+	0xff1232fd, 0xfe162ffd, 0xfd1b2cfc, 0xfd1f28fc,
+	0xfd2323fd, 0xfc281ffd, 0xfc2c1bfd, 0xfd2f16fe,
+	0xfd3212ff, 0xff340eff, 0x00360a00, 0x02370700,
+
+	0xff083207, 0xff0a3205, 0xff0d3103, 0xfe113001,
+	0xfe142e00, 0xfe182bff, 0xfe1b29fe, 0xfe1f25fe,
+	0xfe2222fe, 0xfe251ffe, 0xfe291bfe, 0xff2b18fe,
+	0x002e14fe, 0x013010ff, 0x03310dff, 0x05310a00,
+
+	0xff0a2e09, 0xff0c2e07, 0xff0f2d05, 0xff122c03,
+	0xfe152b02, 0xfe182901, 0xfe1b2700, 0xff1e24ff,
+	0xff2121ff, 0xff241eff, 0x00261bff, 0x012818ff,
+	0x022a15ff, 0x032c12ff, 0x052d0fff, 0x072d0c00,
+
+	0xff0c2a0b, 0xff0e2a09, 0xff102a07, 0xff132905,
+	0xff162803, 0xff182702, 0xff1b2501, 0xff1e2300,
+	0x00202000, 0x01221d00, 0x01251bff, 0x032618ff,
+	0x042815ff, 0x052913ff, 0x072a10ff, 0x092a0d00,
+
+	0xff0d280c, 0xff0f280a, 0xff112808, 0xff142706,
+	0xff162605, 0xff192503, 0x001b2302, 0x001d2201,
+	0x011f1f01, 0x01221d00, 0x02231b00, 0x04241800,
+	0x052616ff, 0x072713ff, 0x08271100, 0x0a280e00,
+
+	0xff0e260d, 0xff10260b, 0xff122609, 0xff142508,
+	0x00152506, 0x00182305, 0x001b2203, 0x011d2002,
+	0x011f1f01, 0x02201d01, 0x03221b00, 0x04231801,
+	0x06241600, 0x08251300, 0x09261100, 0x0b260f00,
+
+	0xff0e250e, 0xff10250c, 0x0011250a, 0x00142408,
+	0x00162307, 0x00182206, 0x011a2104, 0x011c2003,
+	0x021e1e02, 0x03201c01, 0x04211a01, 0x05221801,
+	0x07231600, 0x08241400, 0x0a241200, 0x0c241000,
+
+	0x000e240e, 0x0010240c, 0x0013230a, 0x00142309,
+	0x00162208, 0x01182106, 0x011a2005, 0x021b1f04,
+	0x031d1d03, 0x041e1c02, 0x05201a01, 0x06211801,
+	0x07221601, 0x09231400, 0x0a231300, 0x0c231100,
+
+	0x000f220f, 0x0011220d, 0x0013220b, 0x0015210a,
+	0x01162108, 0x01182007, 0x02191f06, 0x031a1e05,
+	0x041c1c04, 0x051d1b03, 0x061f1902, 0x07201801,
+	0x08211601, 0x0a211500, 0x0b221300, 0x0d221100,
+
+	0x0010210f, 0x0011210e, 0x0013210c, 0x0114200b,
+	0x01161f0a, 0x02171f08, 0x03181e07, 0x031a1d06,
+	0x041c1c04, 0x051d1a04, 0x071d1903, 0x081e1802,
+	0x091f1602, 0x0b1f1501, 0x0c211300, 0x0e201200,
+
+	0x00102010, 0x0012200e, 0x0013200d, 0x01151f0b,
+	0x01161f0a, 0x02171e09, 0x03191d07, 0x041a1c06,
+	0x051b1b05, 0x061c1a04, 0x071d1903, 0x081e1703,
+	0x0a1f1601, 0x0b1f1501, 0x0d201300, 0x0e201200,
+
+	0x00102010, 0x00121f0f, 0x00141f0d, 0x01141f0c,
+	0x02161e0a, 0x03171d09, 0x03181d08, 0x041a1c06,
+	0x051b1b05, 0x061c1a04, 0x081c1903, 0x091d1703,
+	0x0a1e1602, 0x0c1e1501, 0x0d1f1400, 0x0e1f1201,
+
+	0x00111e11, 0x00131e0f, 0x01131e0e, 0x02151d0c,
+	0x02161d0b, 0x03171c0a, 0x04181b09, 0x05191b07,
+	0x061a1a06, 0x071b1905, 0x091b1804, 0x0a1c1703,
+	0x0b1d1602, 0x0c1d1502, 0x0e1d1401, 0x0f1e1300,
+
+	0x00111e11, 0x00131d10, 0x01141d0e, 0x02151c0d,
+	0x03161c0b, 0x04171b0a, 0x05171b09, 0x06181a08,
+	0x07191907, 0x081a1806, 0x091a1805, 0x0a1b1704,
+	0x0b1c1603, 0x0d1c1502, 0x0e1d1401, 0x0f1d1301,
+};
+
+static int sun8i_ui_scaler_coef_index(unsigned int step)
+{
+	unsigned int scale, int_part, float_part;
+
+	scale = step >> (SUN8I_UI_SCALER_SCALE_FRAC - 3);
+	int_part = scale >> 3;
+	float_part = scale & 0x7;
+
+	switch (int_part) {
+	case 0:
+		return 0;
+	case 1:
+		return float_part;
+	case 2:
+		return 8 + (float_part >> 1);
+	case 3:
+		return 12;
+	case 4:
+		return 13;
+	default:
+		return 14;
+	}
+}
+
+void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
+{
+	int vi_cnt = mixer->cfg->vi_num;
+	u32 val;
+
+	if (WARN_ON(layer < vi_cnt))
+		return;
+
+	if (enable)
+		val = SUN8I_SCALER_GSU_CTRL_EN |
+		      SUN8I_SCALER_GSU_CTRL_COEFF_RDY;
+	else
+		val = 0;
+
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_CTRL(vi_cnt, layer - vi_cnt), val);
+}
+
+void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer,
+			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase)
+{
+	int vi_cnt = mixer->cfg->vi_num;
+	u32 insize, outsize;
+	int i, offset;
+
+	if (WARN_ON(layer < vi_cnt))
+		return;
+
+	hphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
+	vphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
+	hscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16;
+	vscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16;
+
+	insize = SUN8I_UI_SCALER_SIZE(src_w, src_h);
+	outsize = SUN8I_UI_SCALER_SIZE(dst_w, dst_h);
+
+	layer -= vi_cnt;
+
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, layer), outsize);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_INSIZE(vi_cnt, layer), insize);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_HSTEP(vi_cnt, layer), hscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_VSTEP(vi_cnt, layer), vscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_HPHASE(vi_cnt, layer), hphase);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_GSU_VPHASE(vi_cnt, layer), vphase);
+	offset = sun8i_ui_scaler_coef_index(hscale) *
+			SUN8I_UI_SCALER_COEFF_COUNT;
+	for (i = 0; i < SUN8I_UI_SCALER_COEFF_COUNT; i++)
+		regmap_write(mixer->engine.regs,
+			     SUN8I_SCALER_GSU_HCOEFF(vi_cnt, layer, i),
+			     lan2coefftab16[offset + i]);
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h
new file mode 100644
index 000000000000..86295be8be78
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_scaler.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _SUN8I_UI_SCALER_H_
+#define _SUN8I_UI_SCALER_H_
+
+#include "sun8i_mixer.h"
+
+/* this two macros assumes 16 fractional bits which is standard in DRM */
+#define SUN8I_UI_SCALER_SCALE_MIN		1
+#define SUN8I_UI_SCALER_SCALE_MAX		((1UL << 20) - 1)
+
+#define SUN8I_UI_SCALER_SCALE_FRAC		20
+#define SUN8I_UI_SCALER_PHASE_FRAC		20
+#define SUN8I_UI_SCALER_COEFF_COUNT		16
+#define SUN8I_UI_SCALER_SIZE(w, h)		(((h) - 1) << 16 | ((w) - 1))
+
+#define SUN8I_SCALER_GSU_CTRL(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x0)
+#define SUN8I_SCALER_GSU_OUTSIZE(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x40)
+#define SUN8I_SCALER_GSU_INSIZE(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x80)
+#define SUN8I_SCALER_GSU_HSTEP(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x88)
+#define SUN8I_SCALER_GSU_VSTEP(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x8c)
+#define SUN8I_SCALER_GSU_HPHASE(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x90)
+#define SUN8I_SCALER_GSU_VPHASE(vi_cnt, ui_idx) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x98)
+#define SUN8I_SCALER_GSU_HCOEFF(vi_cnt, ui_idx, index) \
+	(0x20000 + 0x20000 * (vi_cnt) + 0x10000 * (ui_idx) + 0x200 + \
+	0x4 * (index))
+
+#define SUN8I_SCALER_GSU_CTRL_EN		BIT(0)
+#define SUN8I_SCALER_GSU_CTRL_COEFF_RDY		BIT(4)
+
+void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable);
+void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer,
+			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase);
+
+#endif
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index b78d4f3e2b48..e47a0c1f640d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -18,6 +18,7 @@
 
 #include "sun8i_vi_layer.h"
 #include "sun8i_mixer.h"
+#include "sun8i_vi_scaler.h"
 
 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
 				  int overlay, bool enable)
@@ -50,36 +51,61 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 				       int overlay, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
-	u32 width, height, size;
+	u32 src_w, src_h, dst_w, dst_h;
+	u32 outsize, insize;
+	u32 hphase, vphase;
 
 	DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
 			 channel, overlay);
-	/*
-	 * Same source and destination width and height are guaranteed
-	 * by atomic check function.
-	 */
-	width = drm_rect_width(&state->dst);
-	height = drm_rect_height(&state->dst);
-	size = SUN8I_MIXER_SIZE(width, height);
+
+	src_w = drm_rect_width(&state->src) >> 16;
+	src_h = drm_rect_height(&state->src) >> 16;
+	dst_w = drm_rect_width(&state->dst);
+	dst_h = drm_rect_height(&state->dst);
+
+	hphase = state->src.x1 & 0xffff;
+	vphase = state->src.y1 & 0xffff;
+
+	insize = SUN8I_MIXER_SIZE(src_w, src_h);
+	outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
 
 	/* Set height and width */
-	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
+	DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
+			 state->src.x1 >> 16, state->src.y1 >> 16);
+	DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
-		     size);
+		     insize);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
-		     size);
+		     insize);
+
+	if (insize != outsize || hphase || vphase) {
+		u32 hscale, vscale;
+
+		DRM_DEBUG_DRIVER("HW scaling is enabled\n");
+
+		hscale = state->src_w / state->crtc_w;
+		vscale = state->src_h / state->crtc_h;
+
+		sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
+				      dst_h, hscale, vscale, hphase, vphase);
+		sun8i_vi_scaler_enable(mixer, channel, true);
+	} else {
+		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
+		sun8i_vi_scaler_enable(mixer, channel, false);
+	}
 
 	/* Set base coordinates */
-	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+	DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 			 state->dst.x1, state->dst.y1);
+	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
-		     size);
+		     outsize);
 
 	return 0;
 }
@@ -147,8 +173,10 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
 				       struct drm_plane_state *state)
 {
+	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
 	struct drm_crtc *crtc = state->crtc;
 	struct drm_crtc_state *crtc_state;
+	int min_scale, max_scale;
 	struct drm_rect clip;
 
 	if (!crtc)
@@ -163,9 +191,13 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
 	clip.x2 = crtc_state->adjusted_mode.hdisplay;
 	clip.y2 = crtc_state->adjusted_mode.vdisplay;
 
+	if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
+		min_scale = SUN8I_VI_SCALER_SCALE_MIN;
+		max_scale = SUN8I_VI_SCALER_SCALE_MAX;
+	}
+
 	return drm_plane_helper_check_state(state, &clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
+					    min_scale, max_scale,
 					    true, true);
 }
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
new file mode 100644
index 000000000000..68b92e46be68
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Coefficients are taken from BSP driver, which is:
+ * Copyright (C) 2014-2015 Allwinner
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "sun8i_vi_scaler.h"
+
+static const u32 lan3coefftab32_left[480] = {
+	0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100,
+	0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200,
+	0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200,
+	0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200,
+	0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100,
+	0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100,
+	0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000,
+	0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000,
+
+	0x3806fc02, 0x3805fc02, 0x3803fd01, 0x3801fe01,
+	0x3700fe01, 0x35ffff01, 0x35fdff01, 0x34fc0001,
+	0x34fb0000, 0x33fa0000, 0x31fa0100, 0x2ff90100,
+	0x2df80200, 0x2bf80200, 0x2af70200, 0x28f70200,
+	0x27f70200, 0x24f70300, 0x22f70300, 0x1ff70300,
+	0x1ef70300, 0x1cf70300, 0x1af70300, 0x18f70300,
+	0x16f80300, 0x13f80300, 0x11f90300, 0x0ef90300,
+	0x0efa0200, 0x0cfa0200, 0x0afb0200, 0x08fb0200,
+
+	0x320bfa02, 0x3309fa02, 0x3208fb02, 0x3206fb02,
+	0x3205fb02, 0x3104fc02, 0x3102fc01, 0x3001fd01,
+	0x3000fd01, 0x2ffffd01, 0x2efefe01, 0x2dfdfe01,
+	0x2bfcff01, 0x29fcff01, 0x28fbff01, 0x27fa0001,
+	0x26fa0000, 0x24f90000, 0x22f90100, 0x20f90100,
+	0x1ff80100, 0x1ef80100, 0x1cf80100, 0x1af80200,
+	0x18f80200, 0x17f80200, 0x15f80200, 0x12f80200,
+	0x11f90200, 0x0ff90200, 0x0df90200, 0x0cfa0200,
+
+	0x2e0efa01, 0x2f0dfa01, 0x2f0bfa01, 0x2e0afa01,
+	0x2e09fa01, 0x2e07fb01, 0x2d06fb01, 0x2d05fb01,
+	0x2c04fb01, 0x2b03fc01, 0x2a02fc01, 0x2a01fc01,
+	0x2800fd01, 0x28fffd01, 0x26fefd01, 0x25fefe01,
+	0x24fdfe01, 0x23fcfe01, 0x21fcff01, 0x20fbff01,
+	0x1efbff01, 0x1efbff00, 0x1cfa0000, 0x1bfa0000,
+	0x19fa0000, 0x18fa0000, 0x17f90000, 0x15f90100,
+	0x14f90100, 0x12f90100, 0x11f90100, 0x0ff90100,
+
+	0x2b10fa00, 0x2b0ffa00, 0x2b0efa00, 0x2b0cfa00,
+	0x2b0bfa00, 0x2a0afb01, 0x2a09fb01, 0x2908fb01,
+	0x2807fb01, 0x2806fb01, 0x2805fb01, 0x2604fc01,
+	0x2503fc01, 0x2502fc01, 0x2401fc01, 0x2301fc01,
+	0x2100fd01, 0x21fffd01, 0x21fffd01, 0x20fefd01,
+	0x1dfefe01, 0x1cfdfe01, 0x1cfdfe00, 0x1bfcfe00,
+	0x19fcff00, 0x19fbff00, 0x17fbff00, 0x16fbff00,
+	0x15fbff00, 0x14fb0000, 0x13fa0000, 0x11fa0000,
+
+	0x2811fcff, 0x2810fcff, 0x280ffbff, 0x280efbff,
+	0x270dfb00, 0x270cfb00, 0x270bfb00, 0x260afb00,
+	0x2609fb00, 0x2508fb00, 0x2507fb00, 0x2407fb00,
+	0x2406fc00, 0x2305fc00, 0x2204fc00, 0x2203fc00,
+	0x2103fc00, 0x2002fc00, 0x1f01fd00, 0x1e01fd00,
+	0x1d00fd00, 0x1dfffd00, 0x1cfffd00, 0x1bfefd00,
+	0x1afefe00, 0x19fefe00, 0x18fdfe00, 0x17fdfe00,
+	0x16fdfe00, 0x15fcff00, 0x13fcff00, 0x12fcff00,
+
+	0x2512fdfe, 0x2511fdff, 0x2410fdff, 0x240ffdff,
+	0x240efcff, 0x240dfcff, 0x240dfcff, 0x240cfcff,
+	0x230bfcff, 0x230afc00, 0x2209fc00, 0x2108fc00,
+	0x2108fc00, 0x2007fc00, 0x2006fc00, 0x2005fc00,
+	0x1f05fc00, 0x1e04fc00, 0x1e03fc00, 0x1c03fd00,
+	0x1c02fd00, 0x1b02fd00, 0x1b01fd00, 0x1a00fd00,
+	0x1900fd00, 0x1800fd00, 0x17fffe00, 0x16fffe00,
+	0x16fefe00, 0x14fefe00, 0x13fefe00, 0x13fdfe00,
+
+	0x2212fffe, 0x2211fefe, 0x2211fefe, 0x2110fefe,
+	0x210ffeff, 0x220efdff, 0x210dfdff, 0x210dfdff,
+	0x210cfdff, 0x210bfdff, 0x200afdff, 0x200afdff,
+	0x1f09fdff, 0x1f08fdff, 0x1d08fd00, 0x1c07fd00,
+	0x1d06fd00, 0x1b06fd00, 0x1b05fd00, 0x1c04fd00,
+	0x1b04fd00, 0x1a03fd00, 0x1a03fd00, 0x1902fd00,
+	0x1802fd00, 0x1801fd00, 0x1701fd00, 0x1600fd00,
+	0x1400fe00, 0x1400fe00, 0x14fffe00, 0x13fffe00,
+
+	0x201200fe, 0x201100fe, 0x1f11fffe, 0x2010fffe,
+	0x1f0ffffe, 0x1e0ffffe, 0x1f0efeff, 0x1f0dfeff,
+	0x1f0dfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1d0bfeff,
+	0x1d0afeff, 0x1d09fdff, 0x1d09fdff, 0x1c08fdff,
+	0x1c07fdff, 0x1b07fd00, 0x1b06fd00, 0x1a06fd00,
+	0x1a05fd00, 0x1805fd00, 0x1904fd00, 0x1804fd00,
+	0x1703fd00, 0x1703fd00, 0x1602fe00, 0x1502fe00,
+	0x1501fe00, 0x1401fe00, 0x1301fe00, 0x1300fe00,
+
+	0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe,
+	0x1b1001fe, 0x1b0f01ff, 0x1b0e00ff, 0x1b0e00ff,
+	0x1b0d00ff, 0x1a0d00ff, 0x1a0c00ff, 0x1a0cffff,
+	0x1a0bffff, 0x1a0bffff, 0x1a0affff, 0x180affff,
+	0x1909ffff, 0x1809ffff, 0x1808ffff, 0x1808feff,
+	0x1807feff, 0x1707fe00, 0x1606fe00, 0x1506fe00,
+	0x1605fe00, 0x1505fe00, 0x1504fe00, 0x1304fe00,
+	0x1304fe00, 0x1303fe00, 0x1203fe00, 0x1203fe00,
+
+	0x181104ff, 0x191103ff, 0x191003ff, 0x181003ff,
+	0x180f03ff, 0x190f02ff, 0x190e02ff, 0x180e02ff,
+	0x180d02ff, 0x180d01ff, 0x180d01ff, 0x180c01ff,
+	0x180c01ff, 0x180b00ff, 0x170b00ff, 0x170a00ff,
+	0x170a00ff, 0x170900ff, 0x160900ff, 0x160900ff,
+	0x1608ffff, 0x1508ffff, 0x1507ff00, 0x1507ff00,
+	0x1407ff00, 0x1306ff00, 0x1306ff00, 0x1305ff00,
+	0x1205ff00, 0x1105ff00, 0x1204ff00, 0x1104ff00,
+
+	0x171005ff, 0x171005ff, 0x171004ff, 0x170f04ff,
+	0x160f04ff, 0x170f03ff, 0x170e03ff, 0x160e03ff,
+	0x160d03ff, 0x160d02ff, 0x160d02ff, 0x160c02ff,
+	0x160c02ff, 0x160c02ff, 0x160b01ff, 0x150b01ff,
+	0x150a01ff, 0x150a01ff, 0x150a01ff, 0x140901ff,
+	0x14090000, 0x14090000, 0x14080000, 0x13080000,
+	0x13070000, 0x12070000, 0x12070000, 0x12060000,
+	0x11060000, 0x11060000, 0x11050000, 0x1105ff00,
+
+	0x14100600, 0x15100500, 0x150f0500, 0x150f0500,
+	0x140f0500, 0x150e0400, 0x140e0400, 0x130e0400,
+	0x140d0400, 0x150d0300, 0x130d0300, 0x140c0300,
+	0x140c0300, 0x140c0200, 0x140b0200, 0x130b0200,
+	0x120b0200, 0x130a0200, 0x130a0200, 0x130a0100,
+	0x13090100, 0x12090100, 0x11090100, 0x12080100,
+	0x11080100, 0x10080100, 0x11070100, 0x11070000,
+	0x10070000, 0x11060000, 0x10060000, 0x10060000,
+
+	0x140f0600, 0x140f0600, 0x130f0600, 0x140f0500,
+	0x140e0500, 0x130e0500, 0x130e0500, 0x140d0400,
+	0x140d0400, 0x130d0400, 0x120d0400, 0x130c0400,
+	0x130c0300, 0x130c0300, 0x130b0300, 0x130b0300,
+	0x110b0300, 0x130a0200, 0x120a0200, 0x120a0200,
+	0x120a0200, 0x12090200, 0x10090200, 0x11090100,
+	0x11080100, 0x11080100, 0x10080100, 0x10080100,
+	0x10070100, 0x10070100, 0x0f070100, 0x10060100,
+
+	0x120f0701, 0x130f0601, 0x130e0601, 0x130e0601,
+	0x120e0601, 0x130e0501, 0x130e0500, 0x130d0500,
+	0x120d0500, 0x120d0500, 0x130c0400, 0x130c0400,
+	0x120c0400, 0x110c0400, 0x120b0400, 0x120b0300,
+	0x120b0300, 0x120b0300, 0x120a0300, 0x110a0300,
+	0x110a0200, 0x11090200, 0x11090200, 0x10090200,
+	0x10090200, 0x10080200, 0x10080200, 0x10080100,
+	0x0f080100, 0x10070100, 0x0f070100, 0x0f070100
+};
+
+static const u32 lan3coefftab32_right[480] = {
+	0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06,
+	0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f,
+	0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19,
+	0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824,
+	0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f,
+	0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737,
+	0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d,
+	0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40,
+
+	0x0002fc06, 0x0002fb08, 0x0002fb0a, 0x0002fa0c,
+	0x0002fa0e, 0x0003f910, 0x0003f912, 0x0003f814,
+	0x0003f816, 0x0003f719, 0x0003f71a, 0x0003f71d,
+	0x0003f71f, 0x0003f721, 0x0003f723, 0x0003f725,
+	0x0002f727, 0x0002f729, 0x0002f72b, 0x0002f82d,
+	0x0002f82e, 0x0001f930, 0x0001fa31, 0x0000fa34,
+	0x0000fb34, 0x0100fc35, 0x01fffd36, 0x01ffff37,
+	0x01fe0037, 0x01fe0138, 0x01fd0338, 0x02fc0538,
+
+	0x0002fa0b, 0x0002fa0c, 0x0002f90e, 0x0002f910,
+	0x0002f911, 0x0002f813, 0x0002f816, 0x0002f817,
+	0x0002f818, 0x0002f81a, 0x0001f81c, 0x0001f81e,
+	0x0001f820, 0x0001f921, 0x0001f923, 0x0000f925,
+	0x0000fa26, 0x0100fa28, 0x01fffb29, 0x01fffc2a,
+	0x01fffc2c, 0x01fefd2d, 0x01fefe2e, 0x01fdff2f,
+	0x01fd0030, 0x01fd0130, 0x01fc0232, 0x02fc0432,
+	0x02fb0532, 0x02fb0633, 0x02fb0833, 0x02fa0933,
+
+	0x0001fa0e, 0x0001f90f, 0x0001f911, 0x0001f913,
+	0x0001f914, 0x0001f915, 0x0000f918, 0x0000fa18,
+	0x0000fa1a, 0x0000fa1b, 0x0000fa1d, 0x00fffb1e,
+	0x01fffb1f, 0x01fffb20, 0x01fffc22, 0x01fefc23,
+	0x01fefd24, 0x01fefe25, 0x01fdfe27, 0x01fdff28,
+	0x01fd0029, 0x01fc012a, 0x01fc022b, 0x01fc032b,
+	0x01fb042d, 0x01fb052d, 0x01fb062e, 0x01fb072e,
+	0x01fa092e, 0x01fa0a2f, 0x01fa0b2f, 0x01fa0d2f,
+
+	0x0000fa11, 0x0000fa12, 0x0000fa13, 0x0000fb14,
+	0x00fffb16, 0x00fffb16, 0x00fffb17, 0x00fffb19,
+	0x00fffc1a, 0x00fefc1c, 0x00fefd1c, 0x01fefd1d,
+	0x01fefe1e, 0x01fdfe20, 0x01fdff21, 0x01fdff22,
+	0x01fd0023, 0x01fc0124, 0x01fc0124, 0x01fc0225,
+	0x01fc0326, 0x01fc0427, 0x01fb0528, 0x01fb0629,
+	0x01fb0729, 0x01fb0829, 0x01fb092a, 0x01fb0a2a,
+	0x00fa0b2c, 0x00fa0c2b, 0x00fa0e2b, 0x00fa0f2c,
+
+	0x00fffc11, 0x00fffc12, 0x00fffc14, 0x00fffc15,
+	0x00fefd16, 0x00fefd17, 0x00fefd18, 0x00fefe19,
+	0x00fefe1a, 0x00fdfe1d, 0x00fdff1d, 0x00fdff1e,
+	0x00fd001d, 0x00fd011e, 0x00fd0120, 0x00fc0221,
+	0x00fc0321, 0x00fc0323, 0x00fc0423, 0x00fc0523,
+	0x00fc0624, 0x00fb0725, 0x00fb0726, 0x00fb0827,
+	0x00fb0926, 0x00fb0a26, 0x00fb0b27, 0x00fb0c27,
+	0x00fb0d27, 0xfffb0e28, 0xfffb0f29, 0xfffc1028,
+
+	0x00fefd13, 0x00fefd13, 0x00fefe14, 0x00fefe15,
+	0x00fefe17, 0x00feff17, 0x00feff17, 0x00fd0018,
+	0x00fd001a, 0x00fd001a, 0x00fd011b, 0x00fd021c,
+	0x00fd021c, 0x00fd031d, 0x00fc031f, 0x00fc041f,
+	0x00fc051f, 0x00fc0521, 0x00fc0621, 0x00fc0721,
+	0x00fc0821, 0x00fc0822, 0x00fc0922, 0x00fc0a23,
+	0xfffc0b24, 0xfffc0c24, 0xfffc0d24, 0xfffc0d25,
+	0xfffc0e25, 0xfffd0f25, 0xfffd1025, 0xfffd1125,
+
+	0x00feff12, 0x00feff14, 0x00feff14, 0x00fe0015,
+	0x00fe0015, 0x00fd0017, 0x00fd0118, 0x00fd0118,
+	0x00fd0218, 0x00fd0219, 0x00fd031a, 0x00fd031a,
+	0x00fd041b, 0x00fd041c, 0x00fd051c, 0x00fd061d,
+	0x00fd061d, 0x00fd071e, 0x00fd081e, 0xfffd081f,
+	0xfffd091f, 0xfffd0a20, 0xfffd0a20, 0xfffd0b21,
+	0xfffd0c21, 0xfffd0d21, 0xfffd0d22, 0xfffd0e23,
+	0xfffe0f22, 0xfefe1022, 0xfefe1122, 0xfefe1123,
+
+	0x00fe0012, 0x00fe0013, 0x00fe0114, 0x00fe0114,
+	0x00fe0116, 0x00fe0216, 0x00fe0216, 0x00fd0317,
+	0x00fd0317, 0x00fd0418, 0x00fd0419, 0x00fd0519,
+	0x00fd051a, 0x00fd061b, 0x00fd061b, 0x00fd071c,
+	0xfffd071e, 0xfffd081d, 0xfffd091d, 0xfffd091e,
+	0xfffe0a1d, 0xfffe0b1e, 0xfffe0b1e, 0xfffe0c1e,
+	0xfffe0d1f, 0xfffe0d1f, 0xfffe0e1f, 0xfeff0f1f,
+	0xfeff0f20, 0xfeff1020, 0xfeff1120, 0xfe001120,
+
+	0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314,
+	0x00fe0414, 0x00fe0414, 0x00fe0416, 0x00fe0515,
+	0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0717,
+	0xfffe0719, 0xfffe0818, 0xffff0818, 0xffff0919,
+	0xffff0919, 0xffff0a19, 0xffff0a1a, 0xffff0b1a,
+	0xffff0b1b, 0xffff0c1a, 0xff000c1b, 0xff000d1b,
+	0xff000d1b, 0xff000e1b, 0xff000e1c, 0xff010f1c,
+	0xfe01101c, 0xfe01101d, 0xfe02111c, 0xfe02111c,
+
+	0x00ff0411, 0x00ff0411, 0x00ff0412, 0x00ff0512,
+	0x00ff0513, 0x00ff0513, 0x00ff0613, 0x00ff0614,
+	0x00ff0714, 0x00ff0715, 0x00ff0715, 0xffff0816,
+	0xffff0816, 0xff000916, 0xff000917, 0xff000918,
+	0xff000a17, 0xff000a18, 0xff000b18, 0xff000b18,
+	0xff010c18, 0xff010c19, 0xff010d18, 0xff010d18,
+	0xff020d18, 0xff020e19, 0xff020e19, 0xff020f19,
+	0xff030f19, 0xff031019, 0xff031019, 0xff031119,
+
+	0x00ff0511, 0x00ff0511, 0x00000511, 0x00000611,
+	0x00000612, 0x00000612, 0x00000712, 0x00000713,
+	0x00000714, 0x00000814, 0x00000814, 0x00000914,
+	0x00000914, 0xff010914, 0xff010a15, 0xff010a16,
+	0xff010a17, 0xff010b16, 0xff010b16, 0xff020c16,
+	0xff020c16, 0xff020c16, 0xff020d16, 0xff020d17,
+	0xff030d17, 0xff030e17, 0xff030e17, 0xff030f17,
+	0xff040f17, 0xff040f17, 0xff041017, 0xff051017,
+
+	0x00000610, 0x00000610, 0x00000611, 0x00000611,
+	0x00000711, 0x00000712, 0x00010712, 0x00010812,
+	0x00010812, 0x00010812, 0x00010913, 0x00010913,
+	0x00010913, 0x00010a13, 0x00020a13, 0x00020a14,
+	0x00020b14, 0x00020b14, 0x00020b14, 0x00020c14,
+	0x00030c14, 0x00030c15, 0x00030d15, 0x00030d15,
+	0x00040d15, 0x00040e15, 0x00040e15, 0x00040e16,
+	0x00050f15, 0x00050f15, 0x00050f16, 0x00051015,
+
+	0x00000611, 0x00010610, 0x00010710, 0x00010710,
+	0x00010711, 0x00010811, 0x00010811, 0x00010812,
+	0x00010812, 0x00010912, 0x00020912, 0x00020912,
+	0x00020a12, 0x00020a12, 0x00020a13, 0x00020a13,
+	0x00030b13, 0x00030b13, 0x00030b14, 0x00030c13,
+	0x00030c13, 0x00040c13, 0x00040d14, 0x00040d14,
+	0x00040d15, 0x00040d15, 0x00050e14, 0x00050e14,
+	0x00050e15, 0x00050f14, 0x00060f14, 0x00060f14,
+
+	0x0001070f, 0x0001070f, 0x00010710, 0x00010710,
+	0x00010810, 0x00010810, 0x00020810, 0x00020811,
+	0x00020911, 0x00020911, 0x00020912, 0x00020912,
+	0x00020a12, 0x00030a12, 0x00030a12, 0x00030b12,
+	0x00030b12, 0x00030b12, 0x00040b12, 0x00040c12,
+	0x00040c13, 0x00040c14, 0x00040c14, 0x00050d13,
+	0x00050d13, 0x00050d14, 0x00050e13, 0x01050e13,
+	0x01060e13, 0x01060e13, 0x01060e14, 0x01060f13
+};
+
+static const u32 lan2coefftab32[480] = {
+	0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
+	0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
+	0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb,
+	0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
+	0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
+	0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
+	0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff,
+	0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
+
+	0xff053804, 0xff063803, 0xff083801, 0xff093701,
+	0xff0a3700, 0xff0c3500, 0xff0e34ff, 0xff1033fe,
+	0xff1232fd, 0xfe1431fd, 0xfe162ffd, 0xfe182dfd,
+	0xfd1b2cfc, 0xfd1d2afc, 0xfd1f28fc, 0xfd2126fc,
+	0xfd2323fd, 0xfc2621fd, 0xfc281ffd, 0xfc2a1dfd,
+	0xfc2c1bfd, 0xfd2d18fe, 0xfd2f16fe, 0xfd3114fe,
+	0xfd3212ff, 0xfe3310ff, 0xff340eff, 0x00350cff,
+	0x00360a00, 0x01360900, 0x02370700, 0x03370600,
+
+	0xff083207, 0xff093206, 0xff0a3205, 0xff0c3203,
+	0xff0d3103, 0xff0e3102, 0xfe113001, 0xfe132f00,
+	0xfe142e00, 0xfe162dff, 0xfe182bff, 0xfe192aff,
+	0xfe1b29fe, 0xfe1d27fe, 0xfe1f25fe, 0xfd2124fe,
+	0xfe2222fe, 0xfe2421fd, 0xfe251ffe, 0xfe271dfe,
+	0xfe291bfe, 0xff2a19fe, 0xff2b18fe, 0xff2d16fe,
+	0x002e14fe, 0x002f12ff, 0x013010ff, 0x02300fff,
+	0x03310dff, 0x04310cff, 0x05310a00, 0x06310900,
+
+	0xff0a2e09, 0xff0b2e08, 0xff0c2e07, 0xff0e2d06,
+	0xff0f2d05, 0xff102d04, 0xff122c03, 0xfe142c02,
+	0xfe152b02, 0xfe172a01, 0xfe182901, 0xfe1a2800,
+	0xfe1b2700, 0xfe1d2500, 0xff1e24ff, 0xfe2023ff,
+	0xff2121ff, 0xff2320fe, 0xff241eff, 0x00251dfe,
+	0x00261bff, 0x00281afe, 0x012818ff, 0x012a16ff,
+	0x022a15ff, 0x032b13ff, 0x032c12ff, 0x052c10ff,
+	0x052d0fff, 0x062d0d00, 0x072d0c00, 0x082d0b00,
+
+	0xff0c2a0b, 0xff0d2a0a, 0xff0e2a09, 0xff0f2a08,
+	0xff102a07, 0xff112a06, 0xff132905, 0xff142904,
+	0xff162803, 0xff172703, 0xff182702, 0xff1a2601,
+	0xff1b2501, 0xff1c2401, 0xff1e2300, 0xff1f2200,
+	0x00202000, 0x00211f00, 0x01221d00, 0x01231c00,
+	0x01251bff, 0x02251aff, 0x032618ff, 0x032717ff,
+	0x042815ff, 0x052814ff, 0x052913ff, 0x06291100,
+	0x072a10ff, 0x082a0e00, 0x092a0d00, 0x0a2a0c00,
+
+	0xff0d280c, 0xff0e280b, 0xff0f280a, 0xff102809,
+	0xff112808, 0xff122708, 0xff142706, 0xff152705,
+	0xff162605, 0xff172604, 0xff192503, 0xff1a2403,
+	0x001b2302, 0x001c2202, 0x001d2201, 0x001e2101,
+	0x011f1f01, 0x01211e00, 0x01221d00, 0x02221c00,
+	0x02231b00, 0x03241900, 0x04241800, 0x04251700,
+	0x052616ff, 0x06261400, 0x072713ff, 0x08271100,
+	0x08271100, 0x09271000, 0x0a280e00, 0x0b280d00,
+
+	0xff0e260d, 0xff0f260c, 0xff10260b, 0xff11260a,
+	0xff122609, 0xff132608, 0xff142508, 0xff152507,
+	0x00152506, 0x00172405, 0x00182305, 0x00192304,
+	0x001b2203, 0x001c2103, 0x011d2002, 0x011d2002,
+	0x011f1f01, 0x021f1e01, 0x02201d01, 0x03211c00,
+	0x03221b00, 0x04221a00, 0x04231801, 0x05241700,
+	0x06241600, 0x07241500, 0x08251300, 0x09251200,
+	0x09261100, 0x0a261000, 0x0b260f00, 0x0c260e00,
+
+	0xff0e250e, 0xff0f250d, 0xff10250c, 0xff11250b,
+	0x0011250a, 0x00132409, 0x00142408, 0x00152407,
+	0x00162307, 0x00172306, 0x00182206, 0x00192205,
+	0x011a2104, 0x011b2004, 0x011c2003, 0x021c1f03,
+	0x021e1e02, 0x031e1d02, 0x03201c01, 0x04201b01,
+	0x04211a01, 0x05221900, 0x05221801, 0x06231700,
+	0x07231600, 0x07241500, 0x08241400, 0x09241300,
+	0x0a241200, 0x0b241100, 0x0c241000, 0x0d240f00,
+
+	0x000e240e, 0x000f240d, 0x0010240c, 0x0011240b,
+	0x0013230a, 0x0013230a, 0x00142309, 0x00152308,
+	0x00162208, 0x00172207, 0x01182106, 0x01192105,
+	0x011a2005, 0x021b1f04, 0x021b1f04, 0x021d1e03,
+	0x031d1d03, 0x031e1d02, 0x041e1c02, 0x041f1b02,
+	0x05201a01, 0x05211901, 0x06211801, 0x07221700,
+	0x07221601, 0x08231500, 0x09231400, 0x0a231300,
+	0x0a231300, 0x0b231200, 0x0c231100, 0x0d231000,
+
+	0x000f220f, 0x0010220e, 0x0011220d, 0x0012220c,
+	0x0013220b, 0x0013220b, 0x0015210a, 0x0015210a,
+	0x01162108, 0x01172008, 0x01182007, 0x02191f06,
+	0x02191f06, 0x021a1e06, 0x031a1e05, 0x031c1d04,
+	0x041c1c04, 0x041d1c03, 0x051d1b03, 0x051e1a03,
+	0x061f1902, 0x061f1902, 0x07201801, 0x08201701,
+	0x08211601, 0x09211501, 0x0a211500, 0x0b211400,
+	0x0b221300, 0x0c221200, 0x0d221100, 0x0e221000,
+
+	0x0010210f, 0x0011210e, 0x0011210e, 0x0012210d,
+	0x0013210c, 0x0014200c, 0x0114200b, 0x0115200a,
+	0x01161f0a, 0x01171f09, 0x02171f08, 0x02181e08,
+	0x03181e07, 0x031a1d06, 0x031a1d06, 0x041b1c05,
+	0x041c1c04, 0x051c1b04, 0x051d1a04, 0x061d1a03,
+	0x071d1903, 0x071e1803, 0x081e1802, 0x081f1702,
+	0x091f1602, 0x0a201501, 0x0b1f1501, 0x0b201401,
+	0x0c211300, 0x0d211200, 0x0e201200, 0x0e211100,
+
+	0x00102010, 0x0011200f, 0x0012200e, 0x0013200d,
+	0x0013200d, 0x01141f0c, 0x01151f0b, 0x01151f0b,
+	0x01161f0a, 0x02171e09, 0x02171e09, 0x03181d08,
+	0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05,
+	0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071d1903,
+	0x071d1903, 0x081d1803, 0x081e1703, 0x091e1702,
+	0x0a1f1601, 0x0a1f1502, 0x0b1f1501, 0x0c1f1401,
+	0x0d201300, 0x0d201300, 0x0e201200, 0x0f201100,
+
+	0x00102010, 0x0011200f, 0x00121f0f, 0x00131f0e,
+	0x00141f0d, 0x01141f0c, 0x01141f0c, 0x01151e0c,
+	0x02161e0a, 0x02171e09, 0x03171d09, 0x03181d08,
+	0x03181d08, 0x04191c07, 0x041a1c06, 0x051a1b06,
+	0x051b1b05, 0x061b1a05, 0x061c1a04, 0x071c1904,
+	0x081c1903, 0x081d1803, 0x091d1703, 0x091e1702,
+	0x0a1e1602, 0x0b1e1502, 0x0c1e1501, 0x0c1f1401,
+	0x0d1f1400, 0x0e1f1300, 0x0e1f1201, 0x0f1f1200,
+
+	0x00111e11, 0x00121e10, 0x00131e0f, 0x00131e0f,
+	0x01131e0e, 0x01141d0e, 0x02151d0c, 0x02151d0c,
+	0x02161d0b, 0x03161c0b, 0x03171c0a, 0x04171c09,
+	0x04181b09, 0x05181b08, 0x05191b07, 0x06191a07,
+	0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805,
+	0x091b1804, 0x091c1704, 0x0a1c1703, 0x0a1c1604,
+	0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1d1402,
+	0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200,
+
+	0x00111e11, 0x00121e10, 0x00131d10, 0x01131d0f,
+	0x01141d0e, 0x01141d0e, 0x02151c0d, 0x02151c0d,
+	0x03161c0b, 0x03161c0b, 0x04171b0a, 0x04171b0a,
+	0x05171b09, 0x05181a09, 0x06181a08, 0x06191a07,
+	0x07191907, 0x071a1906, 0x081a1806, 0x081a1806,
+	0x091a1805, 0x0a1b1704, 0x0a1b1704, 0x0b1c1603,
+	0x0b1c1603, 0x0c1c1503, 0x0d1c1502, 0x0d1d1402,
+	0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200,
+};
+
+static int sun8i_vi_scaler_coef_index(unsigned int step)
+{
+	unsigned int scale, int_part, float_part;
+
+	scale = step >> (SUN8I_VI_SCALER_SCALE_FRAC - 3);
+	int_part = scale >> 3;
+	float_part = scale & 0x7;
+
+	switch (int_part) {
+	case 0:
+		return 0;
+	case 1:
+		return float_part;
+	case 2:
+		return 8 + (float_part >> 1);
+	case 3:
+		return 12;
+	case 4:
+		return 13;
+	default:
+		return 14;
+	}
+}
+
+static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer,
+				      u32 hstep, u32 vstep)
+{
+	int offset, i;
+
+	offset = sun8i_vi_scaler_coef_index(hstep) *
+			SUN8I_VI_SCALER_COEFF_COUNT;
+	for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
+		regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF0(layer, i),
+			     lan3coefftab32_left[offset + i]);
+		regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(layer, i),
+			     lan3coefftab32_right[offset + i]);
+		regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(layer, i),
+			     lan3coefftab32_left[offset + i]);
+		regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(layer, i),
+			     lan3coefftab32_right[offset + i]);
+	}
+
+	offset = sun8i_vi_scaler_coef_index(hstep) *
+			SUN8I_VI_SCALER_COEFF_COUNT;
+	for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
+		regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(layer, i),
+			     lan2coefftab32[offset + i]);
+		regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(layer, i),
+			     lan2coefftab32[offset + i]);
+	}
+}
+
+void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
+{
+	u32 val;
+
+	if (enable)
+		val = SUN8I_SCALER_VSU_CTRL_EN |
+		      SUN8I_SCALER_VSU_CTRL_COEFF_RDY;
+	else
+		val = 0;
+
+	regmap_write(mixer->engine.regs, SUN8I_SCALER_VSU_CTRL(layer), val);
+}
+
+void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
+			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase)
+{
+	u32 chphase, cvphase;
+	u32 insize, outsize;
+
+	hphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
+	vphase <<= SUN8I_VI_SCALER_PHASE_FRAC - 16;
+	hscale <<= SUN8I_VI_SCALER_SCALE_FRAC - 16;
+	vscale <<= SUN8I_VI_SCALER_SCALE_FRAC - 16;
+
+	insize = SUN8I_VI_SCALER_SIZE(src_w, src_h);
+	outsize = SUN8I_VI_SCALER_SIZE(dst_w, dst_h);
+
+	chphase = hphase;
+	cvphase = vphase;
+
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_OUTSIZE(layer), outsize);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_YINSIZE(layer), insize);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_YHSTEP(layer), hscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_YVSTEP(layer), vscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_YHPHASE(layer), hphase);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_YVPHASE(layer), vphase);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_CINSIZE(layer),
+		     SUN8I_VI_SCALER_SIZE(src_w, src_h));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_CHSTEP(layer),
+		     hscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_CVSTEP(layer),
+		     vscale);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_CHPHASE(layer), chphase);
+	regmap_write(mixer->engine.regs,
+		     SUN8I_SCALER_VSU_CVPHASE(layer), cvphase);
+	sun8i_vi_scaler_set_coeff(mixer->engine.regs, layer,
+				  hscale, vscale);
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
new file mode 100644
index 000000000000..09edb3491dc9
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _SUN8I_VI_SCALER_H_
+#define _SUN8I_VI_SCALER_H_
+
+#include "sun8i_mixer.h"
+
+/* this two macros assumes 16 fractional bits which is standard in DRM */
+#define SUN8I_VI_SCALER_SCALE_MIN		1
+#define SUN8I_VI_SCALER_SCALE_MAX		((1UL << 20) - 1)
+
+#define SUN8I_VI_SCALER_SCALE_FRAC		20
+#define SUN8I_VI_SCALER_PHASE_FRAC		20
+#define SUN8I_VI_SCALER_COEFF_COUNT		32
+#define SUN8I_VI_SCALER_SIZE(w, h)		(((h) - 1) << 16 | ((w) - 1))
+
+#define SUN8I_SCALER_VSU_CTRL(ch)	(0x20000 + 0x20000 * (ch) + 0x0)
+#define SUN8I_SCALER_VSU_OUTSIZE(ch)	(0x20000 + 0x20000 * (ch) + 0x40)
+#define SUN8I_SCALER_VSU_YINSIZE(ch)	(0x20000 + 0x20000 * (ch) + 0x80)
+#define SUN8I_SCALER_VSU_YHSTEP(ch)	(0x20000 + 0x20000 * (ch) + 0x88)
+#define SUN8I_SCALER_VSU_YVSTEP(ch)	(0x20000 + 0x20000 * (ch) + 0x8c)
+#define SUN8I_SCALER_VSU_YHPHASE(ch)	(0x20000 + 0x20000 * (ch) + 0x90)
+#define SUN8I_SCALER_VSU_YVPHASE(ch)	(0x20000 + 0x20000 * (ch) + 0x98)
+#define SUN8I_SCALER_VSU_CINSIZE(ch)	(0x20000 + 0x20000 * (ch) + 0xc0)
+#define SUN8I_SCALER_VSU_CHSTEP(ch)	(0x20000 + 0x20000 * (ch) + 0xc8)
+#define SUN8I_SCALER_VSU_CVSTEP(ch)	(0x20000 + 0x20000 * (ch) + 0xcc)
+#define SUN8I_SCALER_VSU_CHPHASE(ch)	(0x20000 + 0x20000 * (ch) + 0xd0)
+#define SUN8I_SCALER_VSU_CVPHASE(ch)	(0x20000 + 0x20000 * (ch) + 0xd8)
+#define SUN8I_SCALER_VSU_YHCOEFF0(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x200 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_YHCOEFF1(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x300 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_YVCOEFF(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x400 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CHCOEFF0(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x600 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CHCOEFF1(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x700 + 0x4 * (i))
+#define SUN8I_SCALER_VSU_CVCOEFF(ch, i) \
+	(0x20000 + 0x20000 * (ch) + 0x800 + 0x4 * (i))
+
+#define SUN8I_SCALER_VSU_CTRL_EN		BIT(0)
+#define SUN8I_SCALER_VSU_CTRL_COEFF_RDY		BIT(4)
+
+void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable);
+void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
+			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase);
+
+#endif
-- 
2.15.1

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

* [PATCH v2 22/27] drm/sun4i: Add CCSC property to DE2 configuration
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (20 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 21/27] drm/sun4i: Add support for HW scaling to DE2 Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 23/27] drm/sun4i: Add DE2 CSC library Jernej Skrabec
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Base addresses of channel output CSC (CCSC) depends whether mixer in
question is first or second and if it is second, if supports VEP or not.
This new property will tell which set of base addresses to take.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 1 +
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index e3296a060352..7f88cf5f97eb 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -337,6 +337,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.vi_num = 2,
 	.ui_num = 1,
 	.scaler_mask = 0x3,
+	.ccsc = 0,
 };
 
 static const struct of_device_id sun8i_mixer_of_table[] = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 9bbd762d26f7..994090858b18 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -98,11 +98,16 @@ struct de2_fmt_info {
  *	First, scaler supports for VI channels is defined and after that, scaler
  *	support for UI channels. For example, if mixer has 2 VI channels without
  *	scaler and 2 UI channels with scaler, bitmask would be 0xC.
+ * @ccsc: select set of CCSC base addresses
+ *	Set value to 0 if this is first mixer or second mixer with VEP support.
+ *	Set value to 1 if this is second mixer without VEP support. Other values
+ *	are invalid.
  */
 struct sun8i_mixer_cfg {
 	int		vi_num;
 	int		ui_num;
 	int		scaler_mask;
+	int		ccsc;
 };
 
 struct sun8i_mixer {
-- 
2.15.1

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

* [PATCH v2 23/27] drm/sun4i: Add DE2 CSC library
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (21 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 22/27] drm/sun4i: Add CCSC property to DE2 configuration Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 24/27] drm/sun4i: Add DE2 definitions for YUV formats Jernej Skrabec
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

DE2 have many CSC units - channel input CSC, channel output CSC and
mixer output CSC and maybe more.

Fortunately, they have all same register layout, only base offsets
differs.

Add support only for channel output CSC for now.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/Makefile    |  2 +-
 drivers/gpu/drm/sun4i/sun8i_csc.c | 93 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_csc.h | 36 +++++++++++++++
 3 files changed, 130 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_csc.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_csc.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index a458ddbf4a8e..82a6ac57fbe3 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -11,7 +11,7 @@ sun4i-drm-hdmi-y		+= sun4i_hdmi_tmds_clk.o
 
 sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
 				   sun8i_vi_layer.o sun8i_ui_scaler.o \
-				   sun8i_vi_scaler.o
+				   sun8i_vi_scaler.o sun8i_csc.o
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
new file mode 100644
index 000000000000..b14925b40ccf
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * 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 "sun8i_csc.h"
+#include "sun8i_mixer.h"
+
+static const u32 ccsc_base[2][2] = {
+	{CCSC00_OFFSET, CCSC01_OFFSET},
+	{CCSC10_OFFSET, CCSC11_OFFSET},
+};
+
+/*
+ * Factors are in two's complement format, 10 bits for fractinal part.
+ * First tree values in each line are multiplication factor and last
+ * value is constant, which is added at the end.
+ */
+static const u32 yuv2rgb[] = {
+	0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A,
+	0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4,
+	0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A,
+};
+
+static const u32 yvu2rgb[] = {
+	0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A,
+	0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4,
+	0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A,
+};
+
+static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
+				       enum sun8i_csc_mode mode)
+{
+	const u32 *table;
+	int i, data;
+
+	switch (mode) {
+	case SUN8I_CSC_MODE_YUV2RGB:
+		table = yuv2rgb;
+		break;
+	case SUN8I_CSC_MODE_YVU2RGB:
+		table = yvu2rgb;
+		break;
+	default:
+		DRM_WARN("Wrong CSC mode specified.\n");
+		return;
+	}
+
+	for (i = 0; i < 12; i++) {
+		data = table[i];
+		/* For some reason, 0x200 must be added to constant parts */
+		if (((i + 1) & 3) == 0)
+			data += 0x200;
+		regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
+	}
+}
+
+static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
+{
+	u32 val;
+
+	if (enable)
+		val = SUN8I_CSC_CTRL_EN;
+	else
+		val = 0;
+
+	regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
+}
+
+void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
+				     enum sun8i_csc_mode mode)
+{
+	u32 base;
+
+	base = ccsc_base[mixer->cfg->ccsc][layer];
+
+	sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
+}
+
+void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
+{
+	u32 base;
+
+	base = ccsc_base[mixer->cfg->ccsc][layer];
+
+	sun8i_csc_enable(mixer->engine.regs, base, enable);
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h
new file mode 100644
index 000000000000..880e8fbb0855
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * 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_CSC_H_
+#define _SUN8I_CSC_H_
+
+struct sun8i_mixer;
+
+/* VI channel CSC units offsets */
+#define CCSC00_OFFSET 0xAA050
+#define CCSC01_OFFSET 0xFA000
+#define CCSC10_OFFSET 0xA0000
+#define CCSC11_OFFSET 0xF0000
+
+#define SUN8I_CSC_CTRL(base)		(base + 0x0)
+#define SUN8I_CSC_COEFF(base, i)	(base + 0x10 + 4 * i)
+
+#define SUN8I_CSC_CTRL_EN		BIT(0)
+
+enum sun8i_csc_mode {
+	SUN8I_CSC_MODE_OFF,
+	SUN8I_CSC_MODE_YUV2RGB,
+	SUN8I_CSC_MODE_YVU2RGB,
+};
+
+void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
+				     enum sun8i_csc_mode mode);
+void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable);
+
+#endif
-- 
2.15.1

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

* [PATCH v2 24/27] drm/sun4i: Add DE2 definitions for YUV formats
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (22 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 23/27] drm/sun4i: Add DE2 CSC library Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 25/27] drm/sun4i: Expand DE2 scaler lib with YUV support Jernej Skrabec
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

This commit expands translation of DRM YUV format to HW specific
information.

It doesn't do any functional changes.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c    | 136 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h    |  23 +++++-
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c |   2 +-
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c |   2 +-
 4 files changed, 159 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 7f88cf5f97eb..29ceeb016d72 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -34,82 +34,218 @@ static const struct de2_fmt_info de2_formats[] = {
 	{
 		.drm_fmt = DRM_FORMAT_ARGB8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_ABGR8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGBA8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGRA8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_XRGB8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_XRGB8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_XBGR8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_XBGR8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGBX8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBX8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGRX8888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRX8888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGB888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGR888,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGR888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGB565,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGB565,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGR565,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGR565,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_ARGB4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_ABGR4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGBA4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGRA4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_ARGB1555,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_ABGR1555,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_RGBA5551,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
 		.drm_fmt = DRM_FORMAT_BGRA5551,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_UYVY,
+		.de2_fmt = SUN8I_MIXER_FBFMT_UYVY,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_VYUY,
+		.de2_fmt = SUN8I_MIXER_FBFMT_VYUY,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YUYV,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUYV,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YVYU,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YVYU,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_NV16,
+		.de2_fmt = SUN8I_MIXER_FBFMT_NV16,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_NV61,
+		.de2_fmt = SUN8I_MIXER_FBFMT_NV61,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_NV12,
+		.de2_fmt = SUN8I_MIXER_FBFMT_NV12,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_NV21,
+		.de2_fmt = SUN8I_MIXER_FBFMT_NV21,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YUV444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YUV422,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YUV420,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV420,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YUV411,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV411,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YVU444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_YVU2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YVU422,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YVU2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YVU420,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV420,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YVU2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_YVU411,
+		.de2_fmt = SUN8I_MIXER_FBFMT_YUV411,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YVU2RGB,
 	},
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 994090858b18..bc58040a88f9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -14,6 +14,7 @@
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
+#include "sun8i_csc.h"
 #include "sunxi_engine.h"
 
 #define SUN8I_MIXER_SIZE(w, h)			(((h) - 1) << 16 | ((w) - 1))
@@ -73,6 +74,22 @@
 #define SUN8I_MIXER_FBFMT_RGBA5551	18
 #define SUN8I_MIXER_FBFMT_BGRA5551	19
 
+#define SUN8I_MIXER_FBFMT_YUYV		0
+#define SUN8I_MIXER_FBFMT_UYVY		1
+#define SUN8I_MIXER_FBFMT_YVYU		2
+#define SUN8I_MIXER_FBFMT_VYUY		3
+#define SUN8I_MIXER_FBFMT_NV16		4
+#define SUN8I_MIXER_FBFMT_NV61		5
+#define SUN8I_MIXER_FBFMT_YUV422	6
+/* format 7 doesn't exist */
+#define SUN8I_MIXER_FBFMT_NV12		8
+#define SUN8I_MIXER_FBFMT_NV21		9
+#define SUN8I_MIXER_FBFMT_YUV420	10
+/* format 11 doesn't exist */
+/* format 12 is semi-planar YUV411 UVUV */
+/* format 13 is semi-planar YUV411 VUVU */
+#define SUN8I_MIXER_FBFMT_YUV411	14
+
 /*
  * These sub-engines are still unknown now, the EN registers are here only to
  * be used to disable these sub-engines.
@@ -86,8 +103,10 @@
 #define SUN8I_MIXER_DCSC_EN			0xb0000
 
 struct de2_fmt_info {
-	u32 drm_fmt;
-	u32 de2_fmt;
+	u32			drm_fmt;
+	u32			de2_fmt;
+	bool			rgb;
+	enum sun8i_csc_mode	csc;
 };
 
 /**
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 3cf0729cc7e9..fd76ffd40580 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -154,7 +154,7 @@ static int sun8i_ui_layer_update_formats(struct sun8i_mixer *mixer, int channel,
 	u32 val;
 
 	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
-	if (!fmt_info) {
+	if (!fmt_info || !fmt_info->rgb) {
 		DRM_DEBUG_DRIVER("Invalid format\n");
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index e47a0c1f640d..5a09abec189b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -118,7 +118,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
 	u32 val;
 
 	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
-	if (!fmt_info) {
+	if (!fmt_info || !fmt_info->rgb) {
 		DRM_DEBUG_DRIVER("Invalid format\n");
 		return -EINVAL;
 	}
-- 
2.15.1

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

* [PATCH v2 25/27] drm/sun4i: Expand DE2 scaler lib with YUV support
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (23 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 24/27] drm/sun4i: Add DE2 definitions for YUV formats Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 26/27] drm/sun4i: Wire in DE2 " Jernej Skrabec
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Basic principle of operation when using YUV framebuffer is that chroma
planes have to be upscaled to same size as luma.

Because of that, expand DE2 scaler library to support that.

BSP driver uses another set of FIR filter coefficients for YUV planes.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c  |   4 +-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.c | 458 +++++++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun8i_vi_scaler.h |   4 +-
 3 files changed, 453 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 5a09abec189b..02aaa7d3fceb 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -51,6 +51,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 				       int overlay, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
+	const struct drm_format_info *format = state->fb->format;
 	u32 src_w, src_h, dst_w, dst_h;
 	u32 outsize, insize;
 	u32 hphase, vphase;
@@ -89,7 +90,8 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 		vscale = state->src_h / state->crtc_h;
 
 		sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
-				      dst_h, hscale, vscale, hphase, vphase);
+				      dst_h, hscale, vscale, hphase, vphase,
+				      format);
 		sun8i_vi_scaler_enable(mixer, channel, true);
 	} else {
 		DRM_DEBUG_DRIVER("HW scaling is not needed\n");
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
index 68b92e46be68..d3f1acb234b7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.c
@@ -422,6 +422,417 @@ static const u32 lan2coefftab32[480] = {
 	0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200,
 };
 
+static const u32 bicubic8coefftab32_left[480] = {
+	0x40000000, 0x40ff0000, 0x3ffe0000, 0x3efe0000,
+	0x3dfd0000, 0x3cfc0000, 0x3bfc0000, 0x39fc0000,
+	0x36fc0000, 0x35fb0000, 0x33fb0000, 0x31fb0000,
+	0x2ffb0000, 0x2cfb0000, 0x29fc0000, 0x27fc0000,
+	0x24fc0000, 0x21fc0000, 0x1efd0000, 0x1cfd0000,
+	0x19fd0000, 0x16fe0000, 0x14fe0000, 0x11fe0000,
+	0x0dff0000, 0x0cff0000, 0x0aff0000, 0x08ff0000,
+	0x05000000, 0x03000000, 0x02000000, 0x01000000,
+
+	0x3904ff00, 0x3903ff00, 0x3902ff00, 0x38010000,
+	0x37000000, 0x36ff0000, 0x35ff0000, 0x34fe0000,
+	0x32fe0000, 0x31fd0000, 0x30fd0000, 0x2efc0000,
+	0x2cfc0000, 0x2afc0000, 0x28fc0000, 0x26fc0000,
+	0x24fc0000, 0x22fc0000, 0x20fc0000, 0x1efc0000,
+	0x1cfc0000, 0x19fc0000, 0x17fc0000, 0x15fd0000,
+	0x12fd0000, 0x11fd0000, 0x0ffd0000, 0x0dfe0000,
+	0x0bfe0000, 0x09fe0000, 0x08fe0000, 0x06ff0000,
+
+	0x3209fe00, 0x3407fe00, 0x3306fe00, 0x3305fe00,
+	0x3204fe00, 0x3102ff00, 0x3102ff00, 0x3001ff00,
+	0x2f00ff00, 0x2effff00, 0x2cff0000, 0x2bfe0000,
+	0x29fe0000, 0x28fe0000, 0x26fd0000, 0x24fd0000,
+	0x23fd0000, 0x21fd0000, 0x20fc0000, 0x1efc0000,
+	0x1dfc0000, 0x1bfc0000, 0x19fc0000, 0x17fc0000,
+	0x16fc0000, 0x14fc0000, 0x12fc0000, 0x10fd0000,
+	0x0ffd0000, 0x0dfd0000, 0x0cfd0000, 0x0afd0000,
+
+	0x2e0cfd00, 0x2e0bfd00, 0x2e09fd00, 0x2e08fd00,
+	0x2e07fd00, 0x2c06fe00, 0x2c05fe00, 0x2b04fe00,
+	0x2b03fe00, 0x2a02fe00, 0x2901fe00, 0x2701ff00,
+	0x2700ff00, 0x26ffff00, 0x24ffff00, 0x23ffff00,
+	0x22feff00, 0x20fe0000, 0x1ffe0000, 0x1efd0000,
+	0x1dfd0000, 0x1bfd0000, 0x1afd0000, 0x19fd0000,
+	0x17fd0000, 0x15fd0000, 0x13fd0000, 0x12fd0000,
+	0x11fd0000, 0x10fd0000, 0x0ffd0000, 0x0cfd0000,
+
+	0x2a0efd00, 0x2a0dfd00, 0x2a0cfd00, 0x290bfd00,
+	0x290afd00, 0x2909fd00, 0x2908fd00, 0x2807fd00,
+	0x2706fd00, 0x2705fd00, 0x2604fe00, 0x2603fe00,
+	0x2502fe00, 0x2402fe00, 0x2401fe00, 0x2200fe00,
+	0x2200fe00, 0x2000ff00, 0x1fffff00, 0x1effff00,
+	0x1dfeff00, 0x1cfeff00, 0x1afeff00, 0x19feff00,
+	0x17fe0000, 0x16fd0000, 0x15fd0000, 0x14fd0000,
+	0x12fd0000, 0x11fd0000, 0x10fd0000, 0x0ffd0000,
+
+	0x2610fd00, 0x260ffd00, 0x260efd00, 0x260dfd00,
+	0x260cfd00, 0x260bfd00, 0x260afd00, 0x2609fd00,
+	0x2508fd00, 0x2507fd00, 0x2406fd00, 0x2406fd00,
+	0x2305fd00, 0x2304fd00, 0x2203fe00, 0x2103fe00,
+	0x2002fe00, 0x1f01fe00, 0x1e01fe00, 0x1e00fe00,
+	0x1c00fe00, 0x1b00fe00, 0x1afffe00, 0x19ffff00,
+	0x18ffff00, 0x17feff00, 0x16feff00, 0x15feff00,
+	0x14feff00, 0x13feff00, 0x11feff00, 0x10fd0000,
+
+	0x2411feff, 0x2410feff, 0x240ffeff, 0x230efeff,
+	0x240dfeff, 0x240cfeff, 0x230cfd00, 0x230bfd00,
+	0x230afd00, 0x2309fd00, 0x2208fd00, 0x2108fd00,
+	0x2007fd00, 0x2106fd00, 0x2005fd00, 0x1f05fd00,
+	0x1f04fd00, 0x1e03fd00, 0x1d03fe00, 0x1c02fe00,
+	0x1b02fe00, 0x1a01fe00, 0x1a01fe00, 0x1900fe00,
+	0x1800fe00, 0x1700fe00, 0x16fffe00, 0x15fffe00,
+	0x13ffff00, 0x12ffff00, 0x12feff00, 0x11feff00,
+
+	0x2212fffe, 0x2211fffe, 0x2210ffff, 0x220ffeff,
+	0x220efeff, 0x210efeff, 0x210dfeff, 0x210cfeff,
+	0x210bfeff, 0x200bfeff, 0x200afeff, 0x1f09feff,
+	0x1f08feff, 0x1d08fe00, 0x1e07fd00, 0x1e06fd00,
+	0x1d06fd00, 0x1c05fd00, 0x1b04fe00, 0x1a04fe00,
+	0x1a03fe00, 0x1903fe00, 0x1802fe00, 0x1802fe00,
+	0x1701fe00, 0x1601fe00, 0x1501fe00, 0x1500fe00,
+	0x1400fe00, 0x1400fe00, 0x13fffe00, 0x12fffe00,
+
+	0x201200fe, 0x201100fe, 0x1f1100fe, 0x2010fffe,
+	0x200ffffe, 0x1f0ffffe, 0x1f0efffe, 0x1e0dffff,
+	0x1f0cfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1e0afeff,
+	0x1d0afeff, 0x1d09feff, 0x1c08feff, 0x1b08feff,
+	0x1b07feff, 0x1a07feff, 0x1a06feff, 0x1a05feff,
+	0x1805fe00, 0x1904fe00, 0x1704fe00, 0x1703fe00,
+	0x1603fe00, 0x1602fe00, 0x1402fe00, 0x1402fe00,
+	0x1401fe00, 0x1301fe00, 0x1201fe00, 0x1200fe00,
+
+	0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe,
+	0x1b1001fe, 0x1c0f01fe, 0x1b0f00fe, 0x1b0e00fe,
+	0x1b0e00fe, 0x1b0d00fe, 0x1b0c00fe, 0x1a0cfffe,
+	0x1a0bfffe, 0x1a0bfffe, 0x190afffe, 0x190afffe,
+	0x1909fffe, 0x1709ffff, 0x1808ffff, 0x1708feff,
+	0x1707feff, 0x1707feff, 0x1606feff, 0x1506feff,
+	0x1505feff, 0x1505feff, 0x1404feff, 0x1404feff,
+	0x1404feff, 0x1303feff, 0x1203feff, 0x1202feff,
+
+	0x191104fe, 0x191104fe, 0x191003fe, 0x191003fe,
+	0x171003fe, 0x180f03fe, 0x180f02fe, 0x180e02fe,
+	0x180e02fe, 0x180d01fe, 0x180d01fe, 0x180d01fe,
+	0x170c01fe, 0x160c01fe, 0x170b00fe, 0x170b00fe,
+	0x160a00fe, 0x160a00fe, 0x160a00fe, 0x150900fe,
+	0x1509fffe, 0x1508fffe, 0x1508fffe, 0x1408fffe,
+	0x1407fffe, 0x1307ffff, 0x1306ffff, 0x1206ffff,
+	0x1206ffff, 0x1205ffff, 0x1205ffff, 0x1104feff,
+
+	0x161006ff, 0x161005ff, 0x161005ff, 0x160f05ff,
+	0x160f04ff, 0x150f04ff, 0x150e04ff, 0x150e04ff,
+	0x150e03ff, 0x150d03ff, 0x150d03ff, 0x150d02ff,
+	0x140c02ff, 0x150c02fe, 0x150c02fe, 0x150b02fe,
+	0x140b01fe, 0x140b01fe, 0x140a01fe, 0x140a01fe,
+	0x140a01fe, 0x130900fe, 0x130900fe, 0x130900fe,
+	0x130800fe, 0x120800fe, 0x120800fe, 0x120700fe,
+	0x120700fe, 0x1107fffe, 0x1106fffe, 0x1106fffe,
+
+	0x140f0700, 0x140f0600, 0x140f0600, 0x140f0600,
+	0x140e0600, 0x130e0500, 0x140e05ff, 0x130e05ff,
+	0x140d05ff, 0x130d04ff, 0x130d04ff, 0x120d04ff,
+	0x130c04ff, 0x130c03ff, 0x130c03ff, 0x120c03ff,
+	0x120b03ff, 0x120b02ff, 0x120b02ff, 0x120a02ff,
+	0x120a02ff, 0x110a02ff, 0x110a01ff, 0x120901ff,
+	0x100901ff, 0x100901ff, 0x110801ff, 0x110801ff,
+	0x100800ff, 0x100800ff, 0x100700ff, 0x100700fe,
+
+	0x120f0701, 0x120e0701, 0x120e0701, 0x120e0701,
+	0x120e0600, 0x110e0600, 0x120d0600, 0x120d0600,
+	0x120d0500, 0x120d0500, 0x110d0500, 0x110c0500,
+	0x110c0500, 0x110c0400, 0x110c0400, 0x110b04ff,
+	0x110b04ff, 0x110b04ff, 0x110b03ff, 0x110b03ff,
+	0x110a03ff, 0x110a03ff, 0x100a03ff, 0x110a02ff,
+	0x100902ff, 0x100902ff, 0x100902ff, 0x0f0902ff,
+	0x0e0902ff, 0x100801ff, 0x0f0801ff, 0x0f0801ff,
+
+	0x100e0802, 0x100e0802, 0x110e0702, 0x110d0701,
+	0x110d0701, 0x100d0701, 0x100d0701, 0x110d0601,
+	0x110d0601, 0x110c0601, 0x110c0601, 0x100c0600,
+	0x100c0500, 0x100c0500, 0x100c0500, 0x100b0500,
+	0x100b0500, 0x100b0400, 0x100b0400, 0x0f0b0400,
+	0x100a0400, 0x0f0a0400, 0x0f0a0400, 0x0f0a0300,
+	0x0f0a03ff, 0x0f0903ff, 0x0f0903ff, 0x0f0903ff,
+	0x0f0903ff, 0x0f0902ff, 0x0f0902ff, 0x0f0802ff
+};
+
+static const u32 bicubic8coefftab32_right[480] = {
+	0x00000000, 0x00000001, 0x00000003, 0x00000004,
+	0x00000006, 0x0000ff09, 0x0000ff0a, 0x0000ff0c,
+	0x0000ff0f, 0x0000fe12, 0x0000fe14, 0x0000fe16,
+	0x0000fd19, 0x0000fd1c, 0x0000fd1e, 0x0000fc21,
+	0x0000fc24, 0x0000fc27, 0x0000fc29, 0x0000fb2c,
+	0x0000fb2f, 0x0000fb31, 0x0000fb33, 0x0000fb36,
+	0x0000fc38, 0x0000fc39, 0x0000fc3b, 0x0000fc3d,
+	0x0000fd3e, 0x0000fe3f, 0x0000fe40, 0x0000ff40,
+
+	0x0000ff05, 0x0000ff06, 0x0000fe08, 0x0000fe09,
+	0x0000fe0b, 0x0000fe0d, 0x0000fd0f, 0x0000fd11,
+	0x0000fd13, 0x0000fd15, 0x0000fc17, 0x0000fc1a,
+	0x0000fc1c, 0x0000fc1e, 0x0000fc20, 0x0000fc22,
+	0x0000fc24, 0x0000fc26, 0x0000fc28, 0x0000fc2a,
+	0x0000fc2c, 0x0000fc2f, 0x0000fd30, 0x0000fd31,
+	0x0000fe33, 0x0000fe34, 0x0000ff35, 0x0000ff36,
+	0x00000037, 0x00000138, 0x00ff0239, 0x00ff0339,
+
+	0x0000fe09, 0x0000fd0a, 0x0000fd0c, 0x0000fd0d,
+	0x0000fd0f, 0x0000fd11, 0x0000fc12, 0x0000fc14,
+	0x0000fc16, 0x0000fc18, 0x0000fc19, 0x0000fc1b,
+	0x0000fc1d, 0x0000fc1e, 0x0000fc21, 0x0000fd22,
+	0x0000fd23, 0x0000fd25, 0x0000fd27, 0x0000fe28,
+	0x0000fe29, 0x0000fe2b, 0x0000ff2c, 0x00ffff2f,
+	0x00ff002f, 0x00ff0130, 0x00ff0231, 0x00ff0232,
+	0x00fe0432, 0x00fe0533, 0x00fe0633, 0x00fe0734,
+
+	0x0000fd0c, 0x0000fd0d, 0x0000fd0f, 0x0000fd10,
+	0x0000fd11, 0x0000fd13, 0x0000fd14, 0x0000fd16,
+	0x0000fd17, 0x0000fd19, 0x0000fd1b, 0x0000fd1c,
+	0x0000fd1d, 0x0000fd1f, 0x0000fe20, 0x0000fe21,
+	0x00fffe24, 0x00ffff24, 0x00ffff25, 0x00ffff27,
+	0x00ff0027, 0x00ff0128, 0x00fe012a, 0x00fe022a,
+	0x00fe032b, 0x00fe042c, 0x00fe052d, 0x00fe062d,
+	0x00fd072e, 0x00fd082e, 0x00fd092e, 0x00fd0b2f,
+
+	0x0000fd0e, 0x0000fd0f, 0x0000fd10, 0x0000fd12,
+	0x0000fd13, 0x0000fd14, 0x0000fd15, 0x0000fd17,
+	0x0000fe18, 0x00fffe1a, 0x00fffe1b, 0x00fffe1c,
+	0x00fffe1e, 0x00ffff1e, 0x00ffff1f, 0x00ff0021,
+	0x00fe0022, 0x00fe0023, 0x00fe0124, 0x00fe0224,
+	0x00fe0226, 0x00fe0326, 0x00fe0427, 0x00fd0528,
+	0x00fd0628, 0x00fd0729, 0x00fd0829, 0x00fd0929,
+	0x00fd0a2a, 0x00fd0b2a, 0x00fd0c2a, 0x00fd0d2a,
+
+	0x0000fd10, 0x0000fd11, 0x00fffe12, 0x00fffe13,
+	0x00fffe14, 0x00fffe15, 0x00fffe16, 0x00fffe17,
+	0x00ffff18, 0x00ffff19, 0x00feff1c, 0x00fe001b,
+	0x00fe001d, 0x00fe001e, 0x00fe011e, 0x00fe011f,
+	0x00fe0220, 0x00fe0321, 0x00fe0322, 0x00fd0423,
+	0x00fd0524, 0x00fd0624, 0x00fd0626, 0x00fd0725,
+	0x00fd0825, 0x00fd0926, 0x00fd0a26, 0x00fd0b26,
+	0x00fd0c26, 0x00fd0d26, 0x00fd0e27, 0x00fd0f27,
+
+	0x00fffe11, 0x00fffe12, 0x00fffe13, 0x00ffff14,
+	0x00ffff14, 0x00feff16, 0x00feff17, 0x00fe0017,
+	0x00fe0018, 0x00fe0019, 0x00fe011a, 0x00fe011b,
+	0x00fe021c, 0x00fe021c, 0x00fe031d, 0x00fd031f,
+	0x00fd041f, 0x00fd0520, 0x00fd0520, 0x00fd0621,
+	0x00fd0721, 0x00fd0822, 0x00fd0822, 0x00fd0923,
+	0x00fd0a23, 0x00fd0b23, 0x00fd0b25, 0x00fe0c24,
+	0x00fe0d24, 0x00fe0e24, 0x00fe0f24, 0x00fe1024,
+
+	0x00feff12, 0x00feff13, 0x00feff13, 0x00fe0014,
+	0x00fe0015, 0x00fe0016, 0x00fe0116, 0x00fe0117,
+	0x00fe0118, 0x00fe0218, 0x00fe0219, 0x00fe031a,
+	0x00fe031b, 0x00fe041b, 0x00fd041d, 0x00fd051d,
+	0x00fd061d, 0x00fd061f, 0x00fe071e, 0x00fe081e,
+	0x00fe081f, 0x00fe091f, 0x00fe0a20, 0x00fe0a20,
+	0x00fe0b21, 0x00fe0c21, 0x00fe0d21, 0x00fe0d22,
+	0x00fe0e22, 0x00fe0f21, 0x00ff1021, 0x00ff1022,
+
+	0x00fe0012, 0x00fe0013, 0x00fe0113, 0x00fe0114,
+	0x00fe0115, 0x00fe0215, 0x00fe0216, 0x00fe0217,
+	0x00fe0317, 0x00fe0318, 0x00fe0418, 0x00fe0419,
+	0x00fe0519, 0x00fe051a, 0x00fe061b, 0x00fe071b,
+	0x00fe071c, 0x00fe081c, 0x00fe081d, 0x00fe091d,
+	0x00fe0a1d, 0x00fe0a1d, 0x00fe0b1e, 0x00fe0c1e,
+	0x00ff0c1e, 0x00ff0d1e, 0x00ff0e1f, 0x00ff0e1f,
+	0x00ff0f1f, 0x00ff0f20, 0x0000101f, 0x0000111f,
+
+	0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314,
+	0x00fe0414, 0x00fe0414, 0x00fe0515, 0x00fe0516,
+	0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0718,
+	0x00fe0719, 0x00fe0818, 0x00ff0819, 0x00ff0918,
+	0x00ff0919, 0x00ff0a19, 0x00ff0a19, 0x00ff0b1a,
+	0x00ff0b1b, 0x00ff0c1a, 0x00000c1b, 0x00000d1b,
+	0x00000d1c, 0x00000e1b, 0x00000e1d, 0x00010f1b,
+	0x00010f1b, 0x0001101c, 0x0001101d, 0x0002111c,
+
+	0x00fe0412, 0x00fe0412, 0x00ff0512, 0x00ff0512,
+	0x00ff0613, 0x00ff0613, 0x00ff0614, 0x00ff0714,
+	0x00ff0714, 0x00ff0815, 0x00ff0815, 0x00ff0815,
+	0x00ff0916, 0x00000916, 0x00000a16, 0x00000a16,
+	0x00000a18, 0x00000b17, 0x00000b17, 0x00010c17,
+	0x00010c18, 0x00010d18, 0x00010d18, 0x00010d19,
+	0x00020e18, 0x00020e18, 0x00020f18, 0x00030f18,
+	0x00030f18, 0x00031018, 0x00031018, 0x00041119,
+
+	0x00ff0610, 0x00ff0611, 0x00ff0611, 0x00ff0711,
+	0x00000711, 0x00000712, 0x00000812, 0x00000812,
+	0x00000813, 0x00000913, 0x00000913, 0x00000914,
+	0x00010a14, 0x00010a14, 0x00010a14, 0x00010b14,
+	0x00010b16, 0x00020b15, 0x00020c15, 0x00020c15,
+	0x00020c15, 0x00020d17, 0x00030d16, 0x00030d16,
+	0x00030e16, 0x00040e16, 0x00040e16, 0x00040f16,
+	0x00040f16, 0x00050f17, 0x00051017, 0x00051017,
+
+	0x0000070f, 0x00000710, 0x00000710, 0x00000710,
+	0x00000810, 0x00010811, 0x00010811, 0x00010911,
+	0x00010911, 0x00010913, 0x00010913, 0x00020a12,
+	0x00020a12, 0x00020a13, 0x00020b12, 0x00020b13,
+	0x00030b13, 0x00030c13, 0x00030c13, 0x00030c14,
+	0x00040c13, 0x00040d13, 0x00040d14, 0x00040d14,
+	0x00050e14, 0x00050e14, 0x00050e14, 0x00050e14,
+	0x00060f14, 0x00060f14, 0x00060f15, 0x00061015,
+
+	0x0001070f, 0x0001080f, 0x0001080f, 0x0001080f,
+	0x00010811, 0x00020910, 0x00020910, 0x00020910,
+	0x00020911, 0x00020a10, 0x00030a10, 0x00030a11,
+	0x00030a11, 0x00030b11, 0x00030b11, 0x00040b12,
+	0x00040b12, 0x00040c11, 0x00040c12, 0x00040c12,
+	0x00050c12, 0x00050c12, 0x00050d12, 0x00050d12,
+	0x00060d13, 0x00060d13, 0x00060e12, 0x00060e13,
+	0x00070e13, 0x00070e13, 0x00070f13, 0x00070f13,
+
+	0x0002080e, 0x0002080e, 0x0002080e, 0x00020810,
+	0x0002090f, 0x0003090f, 0x0003090f, 0x0003090f,
+	0x0003090f, 0x00030a0f, 0x00030a0f, 0x00040a10,
+	0x00040a11, 0x00040b10, 0x00040b10, 0x00040b11,
+	0x00050b10, 0x00050b11, 0x00050c10, 0x00050c11,
+	0x00050c11, 0x00060c11, 0x00060c11, 0x00060d11,
+	0x00060d12, 0x00070d12, 0x00070d12, 0x00070e11,
+	0x00070e11, 0x00070e12, 0x00080e11, 0x00080e12
+};
+
+static const u32 bicubic4coefftab32[480] = {
+	0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd,
+	0x00063dfd, 0xff083dfc, 0xff0a3bfc, 0xff0c39fc,
+	0xff0e37fc, 0xfe1136fb, 0xfe1433fb, 0xfe1631fb,
+	0xfd192ffb, 0xfd1c2cfb, 0xfd1e29fc, 0xfc2127fc,
+	0xfc2424fc, 0xfc2721fc, 0xfc291efd, 0xfb2c1cfd,
+	0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfb3611fe,
+	0xfc370eff, 0xfc390cff, 0xfc3b0aff, 0xfc3d08ff,
+	0xfd3d0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
+
+	0xfe053904, 0xfe063903, 0xfe083901, 0xfe0a3800,
+	0xfd0b3800, 0xfe0d36ff, 0xfd0f35ff, 0xfd1134fe,
+	0xfd1332fe, 0xfd1531fd, 0xfc1730fd, 0xfc1a2efc,
+	0xfc1c2cfc, 0xfc1e2afc, 0xfc2028fc, 0xfc2226fc,
+	0xfc2424fc, 0xfc2622fc, 0xfc2820fc, 0xfc2a1efc,
+	0xfc2c1cfc, 0xfc2e1afc, 0xfd3017fc, 0xfd3115fd,
+	0xfe3213fd, 0xfe3411fd, 0xff350ffd, 0xff360dfe,
+	0x00370bfe, 0x013809fe, 0x023808fe, 0x033806ff,
+
+	0xfd093208, 0xfd0a3207, 0xfd0c3205, 0xfd0d3204,
+	0xfc0f3203, 0xfc113102, 0xfc123002, 0xfc143000,
+	0xfc152f00, 0xfc172d00, 0xfc192cff, 0xfc1b2bfe,
+	0xfc1d29fe, 0xfc1e28fe, 0xfc2027fd, 0xfd2125fd,
+	0xfd2323fd, 0xfd2521fd, 0xfd2720fc, 0xfe281efc,
+	0xfe291dfc, 0xfe2b1bfc, 0xff2c19fc, 0x002d17fc,
+	0x002e16fc, 0x012f14fc, 0x022f12fd, 0x023110fd,
+	0x03310ffd, 0x05310dfd, 0x06320bfd, 0x07320afd,
+
+	0xfc0c2d0b, 0xfc0d2d0a, 0xfc0e2d09, 0xfc102d07,
+	0xfc112c07, 0xfc132c05, 0xfc142c04, 0xfc162b03,
+	0xfc172a03, 0xfc192a01, 0xfc1a2901, 0xfd1b2800,
+	0xfd1c2700, 0xfd1e2500, 0xfe1f24ff, 0xfe2023ff,
+	0xfe2222fe, 0xff2320fe, 0xff241ffe, 0x00251efd,
+	0x00271cfd, 0x01271bfd, 0x01281afd, 0x022918fd,
+	0x032a16fd, 0x032b15fd, 0x042b14fd, 0x052c12fd,
+	0x072c10fd, 0x082c0ffd, 0x092c0efd, 0x0a2c0dfd,
+
+	0xfd0d290d, 0xfd0e290c, 0xfd0f290b, 0xfd11280a,
+	0xfd122809, 0xfd132808, 0xfd142807, 0xfd162706,
+	0xfd172705, 0xfd192604, 0xfe1a2503, 0xfe1b2502,
+	0xfe1c2402, 0xfe1d2302, 0xff1e2201, 0xff1f2101,
+	0x00202000, 0x00211f00, 0x01221eff, 0x02221dff,
+	0x02241cfe, 0x03241bfe, 0x042519fe, 0x042618fe,
+	0x052617fe, 0x062716fd, 0x072714fe, 0x082713fe,
+	0x092812fd, 0x0a2811fd, 0x0b2810fd, 0x0c280ffd,
+
+	0xfd0f250f, 0xfd10250e, 0xfd11250d, 0xfd12250c,
+	0xfd13250b, 0xfe13250a, 0xfe152409, 0xfe162408,
+	0xfe172308, 0xff182306, 0xff192305, 0xff1a2205,
+	0x001b2104, 0x001c2103, 0x001d2003, 0x011e1f02,
+	0x011f1f01, 0x021f1e01, 0x03201d00, 0x03211c00,
+	0x04211b00, 0x05221aff, 0x062219ff, 0x062318ff,
+	0x082316ff, 0x082316ff, 0x092415fe, 0x0a2414fe,
+	0x0b2413fe, 0x0c2412fe, 0x0d2411fe, 0x0e2410fe,
+
+	0xfe10230f, 0xfe11230e, 0xfe12220e, 0xfe13220d,
+	0xfe14220c, 0xff14220b, 0xff15220a, 0xff16210a,
+	0x00162109, 0x00172108, 0x00182008, 0x01192006,
+	0x011a1f06, 0x021a1f05, 0x021b1e05, 0x031c1d04,
+	0x031d1d03, 0x041d1c03, 0x041e1b03, 0x051e1b02,
+	0x061f1a01, 0x06201901, 0x07201801, 0x08201800,
+	0x09201700, 0x0a211500, 0x0b2115ff, 0x0c2114ff,
+	0x0c2213ff, 0x0d2212ff, 0x0e2211ff, 0x0f2211fe,
+
+	0xff112010, 0xff12200f, 0xff12200f, 0xff13200e,
+	0x0013200d, 0x0014200c, 0x00151f0c, 0x00161f0b,
+	0x01161f0a, 0x01171e0a, 0x02171e09, 0x02181e08,
+	0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05,
+	0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071c1a03,
+	0x071d1903, 0x081e1802, 0x091d1802, 0x091e1702,
+	0x0a1f1601, 0x0b1f1600, 0x0b1f1501, 0x0c201400,
+	0x0d1f1400, 0x0e2013ff, 0x0f1f1200, 0x102011ff,
+
+	0x00111f10, 0x00121e10, 0x00131e0f, 0x00131e0f,
+	0x01131e0e, 0x01141e0d, 0x01151d0d, 0x02151d0c,
+	0x02161d0b, 0x03161d0a, 0x03171c0a, 0x04171c09,
+	0x04181c08, 0x05181b08, 0x05191b07, 0x06191a07,
+	0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805,
+	0x081c1804, 0x091c1704, 0x0a1c1703, 0x0a1d1603,
+	0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1e1401,
+	0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200,
+
+	0x02111c11, 0x02121c10, 0x02131b10, 0x03131b0f,
+	0x03131b0f, 0x03141b0e, 0x04141b0d, 0x04151a0d,
+	0x05151a0c, 0x05151a0c, 0x05161a0b, 0x0616190b,
+	0x0616190b, 0x0716190a, 0x0717180a, 0x08171809,
+	0x08181808, 0x09181708, 0x09181708, 0x0a181707,
+	0x0a191607, 0x0b191606, 0x0b1a1605, 0x0c1a1505,
+	0x0c1a1505, 0x0d1a1504, 0x0d1b1404, 0x0e1b1403,
+	0x0f1b1303, 0x0f1b1303, 0x101b1302, 0x101c1202,
+
+	0x04111a11, 0x04121911, 0x04131910, 0x0513190f,
+	0x0513190f, 0x0513190f, 0x0613190e, 0x0614180e,
+	0x0714180d, 0x0714180d, 0x0715180c, 0x0814180c,
+	0x0815170c, 0x0816170b, 0x0916170a, 0x0916170a,
+	0x0a16160a, 0x0a171609, 0x0a171609, 0x0b171608,
+	0x0b171509, 0x0c171508, 0x0c181507, 0x0d171507,
+	0x0d181407, 0x0e181406, 0x0e181406, 0x0e191306,
+	0x0f191305, 0x0f191305, 0x10191304, 0x10191205,
+
+	0x05121811, 0x06121810, 0x06121810, 0x06131710,
+	0x0713170f, 0x0713170f, 0x0713170f, 0x0813170e,
+	0x0813170e, 0x0814170d, 0x0914160d, 0x0914160d,
+	0x0914160d, 0x0a14160c, 0x0a15160b, 0x0a15150c,
+	0x0b15150b, 0x0b15150b, 0x0b16150a, 0x0c15150a,
+	0x0c16140a, 0x0d161409, 0x0d161409, 0x0d171408,
+	0x0e161408, 0x0e171308, 0x0e171308, 0x0f171307,
+	0x0f171307, 0x10171306, 0x10181206, 0x10181206,
+
+	0x07111711, 0x07121710, 0x07121611, 0x08121610,
+	0x08121610, 0x0813160f, 0x0912160f, 0x0913160e,
+	0x0913160e, 0x0913160e, 0x0a14150d, 0x0a14150d,
+	0x0a14150d, 0x0b14150c, 0x0b14150c, 0x0b14150c,
+	0x0c14140c, 0x0c15140b, 0x0c15140b, 0x0c15140b,
+	0x0d15140a, 0x0d15140a, 0x0d15140a, 0x0e161309,
+	0x0e161309, 0x0e161309, 0x0f151309, 0x0f161308,
+	0x0f161209, 0x10161208, 0x10161208, 0x10171207,
+
+	0x0a111411, 0x0b111410, 0x0b111410, 0x0b111410,
+	0x0b111410, 0x0b12140f, 0x0b12140f, 0x0c12130f,
+	0x0c12130f, 0x0c12130f, 0x0c12130f, 0x0c12130f,
+	0x0d12130e, 0x0d12130e, 0x0d12130e, 0x0d13130d,
+	0x0d13130d, 0x0d13130d, 0x0e12130d, 0x0e13120d,
+	0x0e13120d, 0x0e13120d, 0x0e13120d, 0x0f13120c,
+	0x0f13120c, 0x0f13120c, 0x0f14120b, 0x0f14120b,
+	0x1013120b, 0x1013120b, 0x1013120b, 0x1014110b,
+
+	0x0c111310, 0x0c111310, 0x0c111310, 0x0d101310,
+	0x0d101310, 0x0d111210, 0x0d111210, 0x0d111210,
+	0x0d12120f, 0x0d12120f, 0x0d12120f, 0x0d12120f,
+	0x0e11120f, 0x0e12120e, 0x0e12120e, 0x0e12120e,
+	0x0e12120e, 0x0e12120e, 0x0e12120e, 0x0e12120e,
+	0x0f11120e, 0x0f12120d, 0x0f12120d, 0x0f12120d,
+	0x0f12120d, 0x0f12110e, 0x0f12110e, 0x0f12110e,
+	0x1012110d, 0x1012110d, 0x1013110c, 0x1013110c,
+};
+
 static int sun8i_vi_scaler_coef_index(unsigned int step)
 {
 	unsigned int scale, int_part, float_part;
@@ -447,10 +858,22 @@ static int sun8i_vi_scaler_coef_index(unsigned int step)
 }
 
 static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer,
-				      u32 hstep, u32 vstep)
+				      u32 hstep, u32 vstep,
+				      const struct drm_format_info *format)
 {
+	const u32 *ch_left, *ch_right, *cy;
 	int offset, i;
 
+	if (format->hsub == 1 && format->vsub == 1) {
+		ch_left = lan3coefftab32_left;
+		ch_right = lan3coefftab32_right;
+		cy = lan2coefftab32;
+	} else {
+		ch_left = bicubic8coefftab32_left;
+		ch_right = bicubic8coefftab32_right;
+		cy = bicubic4coefftab32;
+	}
+
 	offset = sun8i_vi_scaler_coef_index(hstep) *
 			SUN8I_VI_SCALER_COEFF_COUNT;
 	for (i = 0; i < SUN8I_VI_SCALER_COEFF_COUNT; i++) {
@@ -459,9 +882,9 @@ static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer,
 		regmap_write(map, SUN8I_SCALER_VSU_YHCOEFF1(layer, i),
 			     lan3coefftab32_right[offset + i]);
 		regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF0(layer, i),
-			     lan3coefftab32_left[offset + i]);
+			     ch_left[offset + i]);
 		regmap_write(map, SUN8I_SCALER_VSU_CHCOEFF1(layer, i),
-			     lan3coefftab32_right[offset + i]);
+			     ch_right[offset + i]);
 	}
 
 	offset = sun8i_vi_scaler_coef_index(hstep) *
@@ -470,7 +893,7 @@ static void sun8i_vi_scaler_set_coeff(struct regmap *map, int layer,
 		regmap_write(map, SUN8I_SCALER_VSU_YVCOEFF(layer, i),
 			     lan2coefftab32[offset + i]);
 		regmap_write(map, SUN8I_SCALER_VSU_CVCOEFF(layer, i),
-			     lan2coefftab32[offset + i]);
+			     cy[offset + i]);
 	}
 }
 
@@ -489,7 +912,8 @@ void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
 
 void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
-			   u32 hscale, u32 vscale, u32 hphase, u32 vphase)
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase,
+			   const struct drm_format_info *format)
 {
 	u32 chphase, cvphase;
 	u32 insize, outsize;
@@ -502,8 +926,19 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 	insize = SUN8I_VI_SCALER_SIZE(src_w, src_h);
 	outsize = SUN8I_VI_SCALER_SIZE(dst_w, dst_h);
 
-	chphase = hphase;
-	cvphase = vphase;
+	/*
+	 * This is chroma V/H phase calculation as it appears in
+	 * BSP driver. There is no detailed explanation. YUV 420
+	 * chroma is threated specialy for some reason.
+	 */
+	if (format->hsub == 2 && format->vsub == 2) {
+		chphase = hphase >> 1;
+		cvphase = (vphase >> 1) -
+			(1UL << (SUN8I_VI_SCALER_SCALE_FRAC - 2));
+	} else {
+		chphase = hphase;
+		cvphase = vphase;
+	}
 
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_OUTSIZE(layer), outsize);
@@ -519,17 +954,18 @@ void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 		     SUN8I_SCALER_VSU_YVPHASE(layer), vphase);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_CINSIZE(layer),
-		     SUN8I_VI_SCALER_SIZE(src_w, src_h));
+		     SUN8I_VI_SCALER_SIZE(src_w / format->hsub,
+					  src_h / format->vsub));
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_CHSTEP(layer),
-		     hscale);
+		     hscale / format->hsub);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_CVSTEP(layer),
-		     vscale);
+		     vscale / format->vsub);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_CHPHASE(layer), chphase);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_SCALER_VSU_CVPHASE(layer), cvphase);
 	sun8i_vi_scaler_set_coeff(mixer->engine.regs, layer,
-				  hscale, vscale);
+				  hscale, vscale, format);
 }
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
index 09edb3491dc9..a595ab643a5a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_scaler.h
@@ -9,6 +9,7 @@
 #ifndef _SUN8I_VI_SCALER_H_
 #define _SUN8I_VI_SCALER_H_
 
+#include <drm/drm_fourcc.h>
 #include "sun8i_mixer.h"
 
 /* this two macros assumes 16 fractional bits which is standard in DRM */
@@ -51,6 +52,7 @@
 void sun8i_vi_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable);
 void sun8i_vi_scaler_setup(struct sun8i_mixer *mixer, int layer,
 			   u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
-			   u32 hscale, u32 vscale, u32 hphase, u32 vphase);
+			   u32 hscale, u32 vscale, u32 hphase, u32 vphase,
+			   const struct drm_format_info *format);
 
 #endif
-- 
2.15.1

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

* [PATCH v2 26/27] drm/sun4i: Wire in DE2 YUV support
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (24 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 25/27] drm/sun4i: Expand DE2 scaler lib with YUV support Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-01  6:05 ` [PATCH v2 27/27] [DO NOT MERGE]drm/sun4i: Change zpos of bottom VI plane Jernej Skrabec
  2017-12-05 10:36 ` [PATCH v2 00/27] Improve DE2 support Maxime Ripard
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Now that we have all required bits, add support for YUV formats.

DRM subsystem doesn't know YUV411 semi-planar format, so leave that out
for now.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 127 ++++++++++++++++++++++++++-------
 1 file changed, 102 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 02aaa7d3fceb..0b4800fd7ba1 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -55,6 +55,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	u32 src_w, src_h, dst_w, dst_h;
 	u32 outsize, insize;
 	u32 hphase, vphase;
+	bool subsampled;
 
 	DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
 			 channel, overlay);
@@ -67,12 +68,32 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	hphase = state->src.x1 & 0xffff;
 	vphase = state->src.y1 & 0xffff;
 
+	/* make coordinates dividable by subsampling factor */
+	if (format->hsub > 1) {
+		int mask, remainder;
+
+		mask = format->hsub - 1;
+		remainder = (state->src.x1 >> 16) & mask;
+		src_w = (src_w + remainder) & ~mask;
+		hphase += remainder << 16;
+	}
+
+	if (format->vsub > 1) {
+		int mask, remainder;
+
+		mask = format->vsub - 1;
+		remainder = (state->src.y1 >> 16) & mask;
+		src_h = (src_h + remainder) & ~mask;
+		vphase += remainder << 16;
+	}
+
 	insize = SUN8I_MIXER_SIZE(src_w, src_h);
 	outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
 
 	/* Set height and width */
 	DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
-			 state->src.x1 >> 16, state->src.y1 >> 16);
+			 (state->src.x1 >> 16) & ~(format->hsub - 1),
+			 (state->src.y1 >> 16) & ~(format->vsub - 1));
 	DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
 	regmap_write(mixer->engine.regs,
 		     SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
@@ -81,7 +102,13 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 		     SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
 		     insize);
 
-	if (insize != outsize || hphase || vphase) {
+	/*
+	 * Scaler must be enabled for subsampled formats, so it scales
+	 * chroma to same size as luma.
+	 */
+	subsampled = format->hsub > 1 || format->vsub > 1;
+
+	if (insize != outsize || subsampled || hphase || vphase) {
 		u32 hscale, vscale;
 
 		DRM_DEBUG_DRIVER("HW scaling is enabled\n");
@@ -120,7 +147,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
 	u32 val;
 
 	fmt_info = sun8i_mixer_format_info(state->fb->format->format);
-	if (!fmt_info || !fmt_info->rgb) {
+	if (!fmt_info) {
 		DRM_DEBUG_DRIVER("Invalid format\n");
 		return -EINVAL;
 	}
@@ -128,9 +155,23 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,
 	val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET;
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
-			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK |
-			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE,
-			   val | SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE);
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val);
+
+	if (fmt_info->csc != SUN8I_CSC_MODE_OFF) {
+		sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc);
+		sun8i_csc_enable_ccsc(mixer, channel, true);
+	} else {
+		sun8i_csc_enable_ccsc(mixer, channel, false);
+	}
+
+	if (fmt_info->rgb)
+		val = SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE;
+	else
+		val = 0;
+
+	regmap_update_bits(mixer->engine.regs,
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
+			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val);
 
 	return 0;
 }
@@ -140,34 +181,53 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 {
 	struct drm_plane_state *state = plane->state;
 	struct drm_framebuffer *fb = state->fb;
+	const struct drm_format_info *format = fb->format;
 	struct drm_gem_cma_object *gem;
+	u32 dx, dy, src_x, src_y;
 	dma_addr_t paddr;
-	int bpp;
+	int i;
 
-	/* Get the physical address of the buffer in memory */
-	gem = drm_fb_cma_get_gem_obj(fb, 0);
+	/* Adjust x and y to be dividable by subsampling factor */
+	src_x = (state->src.x1 >> 16) & ~(format->hsub - 1);
+	src_y = (state->src.y1 >> 16) & ~(format->vsub - 1);
 
-	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+	for (i = 0; i < format->num_planes; i++) {
+		/* Get the physical address of the buffer in memory */
+		gem = drm_fb_cma_get_gem_obj(fb, i);
 
-	/* Compute the start of the displayed memory */
-	bpp = fb->format->cpp[0];
-	paddr = gem->paddr + fb->offsets[0];
+		DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
 
-	/* Fixup framebuffer address for src coordinates */
-	paddr += (state->src.x1 >> 16) * bpp;
-	paddr += (state->src.y1 >> 16) * fb->pitches[0];
+		/* Compute the start of the displayed memory */
+		paddr = gem->paddr + fb->offsets[i];
 
-	/* Set the line width */
-	DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel, overlay, 0),
-		     fb->pitches[0]);
+		dx = src_x;
+		dy = src_y;
 
-	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+		if (i > 0) {
+			dx /= format->hsub;
+			dy /= format->vsub;
+		}
 
-	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel, overlay, 0),
-		     lower_32_bits(paddr));
+		/* Fixup framebuffer address for src coordinates */
+		paddr += dx * format->cpp[i];
+		paddr += dy * fb->pitches[i];
+
+		/* Set the line width */
+		DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
+				 i + 1, fb->pitches[i]);
+		regmap_write(mixer->engine.regs,
+			     SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel,
+							     overlay, i),
+	       fb->pitches[i]);
+
+		DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
+				 i + 1, &paddr);
+
+		regmap_write(mixer->engine.regs,
+			     SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel,
+								 overlay, i),
+	       lower_32_bits(paddr));
+	}
 
 	return 0;
 }
@@ -270,6 +330,23 @@ static const u32 sun8i_vi_layer_formats[] = {
 	DRM_FORMAT_RGBX8888,
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
+
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV61,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_YUV411,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YUV444,
+	DRM_FORMAT_YVU411,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_YVU444,
 };
 
 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
-- 
2.15.1

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

* [PATCH v2 27/27] [DO NOT MERGE]drm/sun4i: Change zpos of bottom VI plane
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (25 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 26/27] drm/sun4i: Wire in DE2 " Jernej Skrabec
@ 2017-12-01  6:05 ` Jernej Skrabec
  2017-12-05 10:36 ` [PATCH v2 00/27] Improve DE2 support Maxime Ripard
  27 siblings, 0 replies; 31+ messages in thread
From: Jernej Skrabec @ 2017-12-01  6:05 UTC (permalink / raw)
  To: maxime.ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Change zpos of VI plane so it is above primary.

Clearly this works only if mixer supports only one VI plane, but it is
good enough for testing and developing.

Proper solution with zpos property should be developed instead.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c    |  2 +-
 drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 10 ++++++----
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 10 ++++++----
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 29ceeb016d72..5a6774d40912 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -424,7 +424,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 		     SUN8I_MIXER_BLEND_COLOR_BLACK);
 
 	/* Fixed zpos for now */
-	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43210);
+	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43201);
 
 	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
 	for (i = 0; i < plane_cnt; i++)
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index fd76ffd40580..472a846ac967 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -26,6 +26,8 @@
 #include "sun8i_mixer.h"
 #include "sun8i_ui_scaler.h"
 
+static int lmap[] = {1, 0, 2, 3, 4};
+
 static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
 				  int overlay, bool enable)
 {
@@ -44,13 +46,13 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
 			   SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
 
 	if (enable)
-		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(lmap[channel]);
 	else
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_BLEND_PIPE_CTL,
-			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(lmap[channel]), val);
 }
 
 static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
@@ -137,10 +139,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 			 state->dst.x1, state->dst.y1);
 	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+		     SUN8I_MIXER_BLEND_ATTR_COORD(lmap[channel]),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+		     SUN8I_MIXER_BLEND_ATTR_INSIZE(lmap[channel]),
 		     outsize);
 
 	return 0;
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 0b4800fd7ba1..e4ee2b51457f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -20,6 +20,8 @@
 #include "sun8i_mixer.h"
 #include "sun8i_vi_scaler.h"
 
+static int lmap[] = {1, 0, 2, 3, 4};
+
 static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
 				  int overlay, bool enable)
 {
@@ -38,13 +40,13 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
 			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
 
 	if (enable)
-		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
+		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(lmap[channel]);
 	else
 		val = 0;
 
 	regmap_update_bits(mixer->engine.regs,
 			   SUN8I_MIXER_BLEND_PIPE_CTL,
-			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(lmap[channel]), val);
 }
 
 static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
@@ -130,10 +132,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 			 state->dst.x1, state->dst.y1);
 	DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+		     SUN8I_MIXER_BLEND_ATTR_COORD(lmap[channel]),
 		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
 	regmap_write(mixer->engine.regs,
-		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+		     SUN8I_MIXER_BLEND_ATTR_INSIZE(lmap[channel]),
 		     outsize);
 
 	return 0;
-- 
2.15.1

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

* Re: [PATCH v2 00/27] Improve DE2 support
  2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
                   ` (26 preceding siblings ...)
  2017-12-01  6:05 ` [PATCH v2 27/27] [DO NOT MERGE]drm/sun4i: Change zpos of bottom VI plane Jernej Skrabec
@ 2017-12-05 10:36 ` Maxime Ripard
  2017-12-05 15:52   ` Jernej Škrabec
  27 siblings, 1 reply; 31+ messages in thread
From: Maxime Ripard @ 2017-12-05 10:36 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

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

Hi,

On Fri, Dec 01, 2017 at 07:05:23AM +0100, Jernej Skrabec wrote:
> Current DE2 driver is very basic and uses a lot of magic constants since
> there is no documentation and knowledge about it was limited at the time.
> 
> With studying BSP source code, deeper knowledge was gained which allows
> to improve mainline driver considerably.
> 
> At the beginning of this series, some code refactoring is done as well
> as adding some checks (patches 1-15).
> 
> Further patches add multi-plane support with HW scaling and all possible
> RGB formats (patches 16-21).
> 
> At last, support for YUV formats is added (patches 22-26).
> 
> At the end, I included patch which puts lowest plane before second lowest.
> This should help testing VI planes when mixer has configuration 1 VI plane
> and 1 or more UI planes (most SoCs except V3s).
> 
> This code was developed on H3, but it should work on every SoC if correct
> configuration structure is provided.
> 
> H3 code can be found here:
> https://github.com/jernejsk/linux-1/commits/de2_impr_for_next

Thanks a lot for that huge rework.

I've applied the patches 1 to 26, and will push them to drm-misc once
the compilations are done.

In the future, if you happen to do such a huge rework again (which
hopefully won't be needed :)), please use the -M option of
format-patch. It will reduce a lot the verbosity of files renaming and
will help the review.

Thanks!
Maxime

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

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

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

* Re: [PATCH v2 00/27] Improve DE2 support
  2017-12-05 10:36 ` [PATCH v2 00/27] Improve DE2 support Maxime Ripard
@ 2017-12-05 15:52   ` Jernej Škrabec
  2017-12-05 19:23     ` Maxime Ripard
  0 siblings, 1 reply; 31+ messages in thread
From: Jernej Škrabec @ 2017-12-05 15:52 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

Hi Maxime,

Dne torek, 05. december 2017 ob 11:36:18 CET je Maxime Ripard napisal(a):
> Hi,
> 
> On Fri, Dec 01, 2017 at 07:05:23AM +0100, Jernej Skrabec wrote:
> > Current DE2 driver is very basic and uses a lot of magic constants since
> > there is no documentation and knowledge about it was limited at the time.
> > 
> > With studying BSP source code, deeper knowledge was gained which allows
> > to improve mainline driver considerably.
> > 
> > At the beginning of this series, some code refactoring is done as well
> > as adding some checks (patches 1-15).
> > 
> > Further patches add multi-plane support with HW scaling and all possible
> > RGB formats (patches 16-21).
> > 
> > At last, support for YUV formats is added (patches 22-26).
> > 
> > At the end, I included patch which puts lowest plane before second lowest.
> > This should help testing VI planes when mixer has configuration 1 VI plane
> > and 1 or more UI planes (most SoCs except V3s).
> > 
> > This code was developed on H3, but it should work on every SoC if correct
> > configuration structure is provided.
> > 
> > H3 code can be found here:
> > https://github.com/jernejsk/linux-1/commits/de2_impr_for_next
> 
> Thanks a lot for that huge rework.
> 
> I've applied the patches 1 to 26, and will push them to drm-misc once
> the compilations are done.
> 
> In the future, if you happen to do such a huge rework again (which
> hopefully won't be needed :)), please use the -M option of
> format-patch. It will reduce a lot the verbosity of files renaming and
> will help the review.

Noted.

I think I missed initialization of min_scaler and max_scaler in 
sun8i_vi_layer_atomic_check() in sun8i_vi_layer.c when I was reworking 
patches.

Will you fix patch with those two lines
min_scale = DRM_PLANE_HELPER_NO_SCALING;
max_scale = DRM_PLANE_HELPER_NO_SCALING;

or should I send new patch which fixes that or should I send new version of 
original patch?

Best regards,
Jernej

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

* Re: [PATCH v2 00/27] Improve DE2 support
  2017-12-05 15:52   ` Jernej Škrabec
@ 2017-12-05 19:23     ` Maxime Ripard
  0 siblings, 0 replies; 31+ messages in thread
From: Maxime Ripard @ 2017-12-05 19:23 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: wens, airlied, linux-kernel, dri-devel, linux-arm-kernel,
	icenowy, linux-sunxi

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

Hi,

On Tue, Dec 05, 2017 at 04:52:57PM +0100, Jernej Škrabec wrote:
> Dne torek, 05. december 2017 ob 11:36:18 CET je Maxime Ripard napisal(a):
> > Hi,
> > 
> > On Fri, Dec 01, 2017 at 07:05:23AM +0100, Jernej Skrabec wrote:
> > > Current DE2 driver is very basic and uses a lot of magic constants since
> > > there is no documentation and knowledge about it was limited at the time.
> > > 
> > > With studying BSP source code, deeper knowledge was gained which allows
> > > to improve mainline driver considerably.
> > > 
> > > At the beginning of this series, some code refactoring is done as well
> > > as adding some checks (patches 1-15).
> > > 
> > > Further patches add multi-plane support with HW scaling and all possible
> > > RGB formats (patches 16-21).
> > > 
> > > At last, support for YUV formats is added (patches 22-26).
> > > 
> > > At the end, I included patch which puts lowest plane before second lowest.
> > > This should help testing VI planes when mixer has configuration 1 VI plane
> > > and 1 or more UI planes (most SoCs except V3s).
> > > 
> > > This code was developed on H3, but it should work on every SoC if correct
> > > configuration structure is provided.
> > > 
> > > H3 code can be found here:
> > > https://github.com/jernejsk/linux-1/commits/de2_impr_for_next
> > 
> > Thanks a lot for that huge rework.
> > 
> > I've applied the patches 1 to 26, and will push them to drm-misc once
> > the compilations are done.
> > 
> > In the future, if you happen to do such a huge rework again (which
> > hopefully won't be needed :)), please use the -M option of
> > format-patch. It will reduce a lot the verbosity of files renaming and
> > will help the review.
> 
> Noted.

It turned out that there was also a change queued for drm-misc that
was renaming (and changing the prototype of)
drm_plane_helper_check_state into
drm_atomic_helper_check_plane_state. I fixed that up in tree, and
tested on the A83t, but you probably want to double check.

> I think I missed initialization of min_scaler and max_scaler in 
> sun8i_vi_layer_atomic_check() in sun8i_vi_layer.c when I was reworking 
> patches.
> 
> Will you fix patch with those two lines
> min_scale = DRM_PLANE_HELPER_NO_SCALING;
> max_scale = DRM_PLANE_HELPER_NO_SCALING;
> 
> or should I send new patch which fixes that or should I send new version of 
> original patch?

We don't rebase in drm-misc, so please send an additional patch.

Thanks!
Maxime

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

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

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

end of thread, other threads:[~2017-12-05 19:23 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-01  6:05 [PATCH v2 00/27] Improve DE2 support Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 01/27] drm/sun4i: Fix format mask in DE2 driver Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 02/27] drm/sun4i: Rename DE2 RGB format macros Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 03/27] drm/sun4i: Remove setting alpha mode in DE2 driver Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 04/27] drm/sun4i: Fix debug message in DE2 Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 05/27] drm/sun4i: Remove setting default values in DE2 driver Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 06/27] drm/sun4i: Explain color macro " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 07/27] drm/sun4i: Set blending mode for all channels (DE2) Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 08/27] drm/sun4i: Rename some macros in DE2 driver Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 09/27] drm/sun4i: Rework enabling plane " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 10/27] drm/sun4i: Start using layer id " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 11/27] drm/sun4i: Add constraints checking to " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 12/27] drm/sun4i: Use values calculated by atomic check Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 13/27] drm/sun4i: Move line width setting in DE2 Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 14/27] drm/sun4i: Move channel size related code " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 15/27] drm/sun4i: Move interlace " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 16/27] drm/sun4i: Add multi plane support to DE2 driver Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 17/27] drm/sun4i: Add support for all HW supported DE2 RGB formats Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 18/27] drm/sun4i: Reorganize UI layer code in DE2 Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 19/27] drm/sun4i: Add support for DE2 VI planes Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 20/27] drm/sun4i: Add scaler configuration to DE2 mixers Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 21/27] drm/sun4i: Add support for HW scaling to DE2 Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 22/27] drm/sun4i: Add CCSC property to DE2 configuration Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 23/27] drm/sun4i: Add DE2 CSC library Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 24/27] drm/sun4i: Add DE2 definitions for YUV formats Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 25/27] drm/sun4i: Expand DE2 scaler lib with YUV support Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 26/27] drm/sun4i: Wire in DE2 " Jernej Skrabec
2017-12-01  6:05 ` [PATCH v2 27/27] [DO NOT MERGE]drm/sun4i: Change zpos of bottom VI plane Jernej Skrabec
2017-12-05 10:36 ` [PATCH v2 00/27] Improve DE2 support Maxime Ripard
2017-12-05 15:52   ` Jernej Škrabec
2017-12-05 19:23     ` Maxime Ripard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).