linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] drm/sun4i: DE2/DE3 improvements
@ 2019-02-28 20:03 Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate Jernej Skrabec
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jernej Skrabec @ 2019-02-28 20:03 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: mturquette, sboyd, airlied, daniel, linux-arm-kernel, linux-clk,
	linux-kernel, dri-devel, linux-sunxi

DE2 and DE3 VI channels support coarse scaling to overcome VI scaler
limitations. That is especially useful for downscaling big planes, for
example 4K to 1080p.

Following patches were tested on H3 and A64 with 4K video playback on
1080p monitor. Without them, picture was mangled.

Please take a look.

Best regards,
Jernej

Jernej Skrabec (3):
  clk: sunxi-ng: Allow DE clock to set parent rate
  drm/sun4i: Add VI scaler line size quirk for DE2/DE3
  drm/sun4i: Improve VI scaling for DE2/DE3

 drivers/clk/sunxi-ng/ccu-sun50i-a64.c  |  3 +-
 drivers/clk/sunxi-ng/ccu-sun50i-h6.c   |  2 +-
 drivers/clk/sunxi-ng/ccu-sun8i-v3s.c   |  3 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.c    |  9 +++++
 drivers/gpu/drm/sun4i/sun8i_mixer.h    |  2 +
 drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 54 ++++++++++++++++++++++++--
 drivers/gpu/drm/sun4i/sun8i_vi_layer.h | 11 ++++++
 7 files changed, 78 insertions(+), 6 deletions(-)

-- 
2.20.1


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

* [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate
  2019-02-28 20:03 [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Jernej Skrabec
@ 2019-02-28 20:03 ` Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3 Jernej Skrabec
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jernej Skrabec @ 2019-02-28 20:03 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: mturquette, sboyd, airlied, daniel, linux-arm-kernel, linux-clk,
	linux-kernel, dri-devel, linux-sunxi

DE2/DE3 mixers have to run at specific frequency in order to work
optimally. This wasn't actually possible for some SoCs because "de"
clock wasn't allowed to adjust parent rate.

Add CLK_SET_RATE_PARENT flag to all "de" clocks which didn't have it
yet.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 3 ++-
 drivers/clk/sunxi-ng/ccu-sun50i-h6.c  | 2 +-
 drivers/clk/sunxi-ng/ccu-sun8i-v3s.c  | 3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 932836d26e2b..be0deee70182 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -531,7 +531,8 @@ static SUNXI_CCU_GATE(dram_ts_clk,	"dram-ts",	"dram",
 
 static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-				 0x104, 0, 4, 24, 3, BIT(31), 0);
+				 0x104, 0, 4, 24, 3, BIT(31),
+				 CLK_SET_RATE_PARENT);
 
 static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
 static const u8 tcon0_table[] = { 0, 2, };
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index 139e8389615c..daf78966555e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -266,7 +266,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
 				       0, 4,	/* M */
 				       24, 1,	/* mux */
 				       BIT(31),	/* gate */
-				       0);
+				       CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
 		      0x60c, BIT(0), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index ac12f261f8ca..eada0e291859 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -325,7 +325,8 @@ static SUNXI_CCU_GATE(dram_ohci_clk,	"dram-ohci",	"dram",
 
 static const char * const de_parents[] = { "pll-video", "pll-periph0" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-				 0x104, 0, 4, 24, 2, BIT(31), 0);
+				 0x104, 0, 4, 24, 2, BIT(31),
+				 CLK_SET_RATE_PARENT);
 
 static const char * const tcon_parents[] = { "pll-video" };
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
-- 
2.20.1


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

* [PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3
  2019-02-28 20:03 [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate Jernej Skrabec
@ 2019-02-28 20:03 ` Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 3/3] drm/sun4i: Improve VI scaling " Jernej Skrabec
  2019-03-01 14:59 ` [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Jernej Skrabec @ 2019-02-28 20:03 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: mturquette, sboyd, airlied, daniel, linux-arm-kernel, linux-clk,
	linux-kernel, dri-devel, linux-sunxi

While all RGB scalers have maximum line size of 2048, some YUV scalers
have maximum line size of 2048 and some have line size of 4096.

Since there is no rule for that, add a quirk.

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

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 30a2eff55687..a2c4807fc9b7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -554,6 +554,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev)
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
 	.ccsc		= 0,
 	.scaler_mask	= 0xf,
+	.scanline_yuv	= 2048,
 	.ui_num		= 3,
 	.vi_num		= 1,
 };
@@ -561,6 +562,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
 static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
 	.ccsc		= 1,
 	.scaler_mask	= 0x3,
+	.scanline_yuv	= 2048,
 	.ui_num		= 1,
 	.vi_num		= 1,
 };
@@ -569,6 +571,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
 	.ccsc		= 0,
 	.mod_rate	= 432000000,
 	.scaler_mask	= 0xf,
+	.scanline_yuv	= 2048,
 	.ui_num		= 3,
 	.vi_num		= 1,
 };
@@ -577,6 +580,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
 	.ccsc		= 0,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0xf,
+	.scanline_yuv	= 2048,
 	.ui_num		= 3,
 	.vi_num		= 1,
 };
@@ -585,6 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
 	.ccsc		= 1,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x3,
+	.scanline_yuv	= 2048,
 	.ui_num		= 1,
 	.vi_num		= 1,
 };
@@ -593,6 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.vi_num = 2,
 	.ui_num = 1,
 	.scaler_mask = 0x3,
+	.scanline_yuv = 2048,
 	.ccsc = 0,
 	.mod_rate = 150000000,
 };
@@ -601,6 +607,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
 	.ccsc		= 0,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0xf,
+	.scanline_yuv	= 4096,
 	.ui_num		= 3,
 	.vi_num		= 1,
 };
@@ -609,6 +616,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
 	.ccsc		= 1,
 	.mod_rate	= 297000000,
 	.scaler_mask	= 0x3,
+	.scanline_yuv	= 2048,
 	.ui_num		= 1,
 	.vi_num		= 1,
 };
@@ -618,6 +626,7 @@ static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
 	.is_de3		= true,
 	.mod_rate	= 600000000,
 	.scaler_mask	= 0xf,
+	.scanline_yuv	= 4096,
 	.ui_num		= 3,
 	.vi_num		= 1,
 };
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 913d14ce68b0..80e084caa084 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -159,6 +159,7 @@ struct de2_fmt_info {
  * @mod_rate: module clock rate that needs to be set in order to have
  *	a functional block.
  * @is_de3: true, if this is next gen display engine 3.0, false otherwise.
+ * @scaline_yuv: size of a scanline for VI scaler for YUV formats.
  */
 struct sun8i_mixer_cfg {
 	int		vi_num;
@@ -167,6 +168,7 @@ struct sun8i_mixer_cfg {
 	int		ccsc;
 	unsigned long	mod_rate;
 	unsigned int	is_de3 : 1;
+	unsigned int	scanline_yuv;
 };
 
 struct sun8i_mixer {
-- 
2.20.1


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

* [PATCH 3/3] drm/sun4i: Improve VI scaling for DE2/DE3
  2019-02-28 20:03 [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate Jernej Skrabec
  2019-02-28 20:03 ` [PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3 Jernej Skrabec
@ 2019-02-28 20:03 ` Jernej Skrabec
  2019-03-01 14:59 ` [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Jernej Skrabec @ 2019-02-28 20:03 UTC (permalink / raw)
  To: maxime.ripard, wens
  Cc: mturquette, sboyd, airlied, daniel, linux-arm-kernel, linux-clk,
	linux-kernel, dri-devel, linux-sunxi

VI planes support coarse scaling which helps to overcome VI scaler
limitations. While exact working of coarse scaling isn't known, it seems
that it just skips programmed amount of rows and columns. This is
especially useful for downscaling very big planes (4K down to 1080p).

Horizontal coarse scaling is currently used to fit one line to VI scaler
buffer.

Vertical coarse scaling is used to assure that VI scaler is actually
capable of processing framebuffer in one frame time.

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

diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 8a0616238467..bb8e026d6405 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -80,6 +80,8 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	u32 bld_base, ch_base;
 	u32 outsize, insize;
 	u32 hphase, vphase;
+	u32 hn = 0, hm = 0;
+	u32 vn = 0, vm = 0;
 	bool subsampled;
 
 	DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
@@ -137,12 +139,41 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 	subsampled = format->hsub > 1 || format->vsub > 1;
 
 	if (insize != outsize || subsampled || hphase || vphase) {
-		u32 hscale, vscale;
+		unsigned int scanline, required;
+		struct drm_display_mode *mode;
+		u32 hscale, vscale, fps;
+		u64 ability;
 
 		DRM_DEBUG_DRIVER("HW scaling is enabled\n");
 
-		hscale = state->src_w / state->crtc_w;
-		vscale = state->src_h / state->crtc_h;
+		mode = &plane->state->crtc->state->mode;
+		fps = (mode->clock * 1000) / (mode->vtotal * mode->htotal);
+		ability = clk_get_rate(mixer->mod_clk);
+		/* BSP algorithm assumes 80% efficiency of VI scaler unit */
+		ability *= 80;
+		do_div(ability, mode->vdisplay * fps * max(src_w, dst_w));
+
+		required = src_h * 100 / dst_h;
+
+		if (ability < required) {
+			DRM_DEBUG_DRIVER("Using vertical coarse scaling\n");
+			vm = src_h;
+			vn = (u32)ability * dst_h / 100;
+			src_h = vn;
+		}
+
+		/* it seems that every RGB scaler has buffer for 2048 pixels */
+		scanline = subsampled ? mixer->cfg->scanline_yuv : 2048;
+
+		if (src_w > scanline) {
+			DRM_DEBUG_DRIVER("Using horizontal coarse scaling\n");
+			hm = src_w;
+			hn = scanline;
+			src_w = hn;
+		}
+
+		hscale = (src_w << 16) / dst_w;
+		vscale = (src_h << 16) / dst_h;
 
 		sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
 				      dst_h, hscale, vscale, hphase, vphase,
@@ -153,6 +184,23 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
 		sun8i_vi_scaler_enable(mixer, channel, false);
 	}
 
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_HDS_Y(ch_base),
+		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_HDS_UV(ch_base),
+		     SUN8I_MIXER_CHAN_VI_DS_N(hn) |
+		     SUN8I_MIXER_CHAN_VI_DS_M(hm));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_VDS_Y(ch_base),
+		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
+	regmap_write(mixer->engine.regs,
+		     SUN8I_MIXER_CHAN_VI_VDS_UV(ch_base),
+		     SUN8I_MIXER_CHAN_VI_DS_N(vn) |
+		     SUN8I_MIXER_CHAN_VI_DS_M(vm));
+
 	/* Set base coordinates */
 	DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
 			 state->dst.x1, state->dst.y1);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
index 8a5e6d01c85d..a223a4839f45 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.h
@@ -24,6 +24,14 @@
 		((base) + 0x30 * (layer) + 0x18 + 4 * (plane))
 #define SUN8I_MIXER_CHAN_VI_OVL_SIZE(base) \
 		((base) + 0xe8)
+#define SUN8I_MIXER_CHAN_VI_HDS_Y(base) \
+		((base) + 0xf0)
+#define SUN8I_MIXER_CHAN_VI_HDS_UV(base) \
+		((base) + 0xf4)
+#define SUN8I_MIXER_CHAN_VI_VDS_Y(base) \
+		((base) + 0xf8)
+#define SUN8I_MIXER_CHAN_VI_VDS_UV(base) \
+		((base) + 0xfc)
 
 #define SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN		BIT(0)
 /* RGB mode should be set for RGB formats and cleared for YCbCr */
@@ -33,6 +41,9 @@
 #define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK	GENMASK(31, 24)
 #define SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(x)	((x) << 24)
 
+#define SUN8I_MIXER_CHAN_VI_DS_N(x)			((x) << 16)
+#define SUN8I_MIXER_CHAN_VI_DS_M(x)			((x) << 0)
+
 struct sun8i_mixer;
 
 struct sun8i_vi_layer {
-- 
2.20.1


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

* Re: [PATCH 0/3] drm/sun4i: DE2/DE3 improvements
  2019-02-28 20:03 [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Jernej Skrabec
                   ` (2 preceding siblings ...)
  2019-02-28 20:03 ` [PATCH 3/3] drm/sun4i: Improve VI scaling " Jernej Skrabec
@ 2019-03-01 14:59 ` Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Maxime Ripard @ 2019-03-01 14:59 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, mturquette, sboyd, airlied, daniel, linux-arm-kernel,
	linux-clk, linux-kernel, dri-devel, linux-sunxi

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

On Thu, Feb 28, 2019 at 09:03:26PM +0100, Jernej Skrabec wrote:
> DE2 and DE3 VI channels support coarse scaling to overcome VI scaler
> limitations. That is especially useful for downscaling big planes, for
> example 4K to 1080p.
> 
> Following patches were tested on H3 and A64 with 4K video playback on
> 1080p monitor. Without them, picture was mangled.

Applied all three, thanks!
Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

end of thread, other threads:[~2019-03-01 14:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-28 20:03 [PATCH 0/3] drm/sun4i: DE2/DE3 improvements Jernej Skrabec
2019-02-28 20:03 ` [PATCH 1/3] clk: sunxi-ng: Allow DE clock to set parent rate Jernej Skrabec
2019-02-28 20:03 ` [PATCH 2/3] drm/sun4i: Add VI scaler line size quirk for DE2/DE3 Jernej Skrabec
2019-02-28 20:03 ` [PATCH 3/3] drm/sun4i: Improve VI scaling " Jernej Skrabec
2019-03-01 14:59 ` [PATCH 0/3] drm/sun4i: DE2/DE3 improvements 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).