diff mbox series

[v3,06/21] drm/sun4i: frontend: Configure and enable YUV to RGB CSC when needed

Message ID 20181204142218.16284-7-paul.kocialkowski@bootlin.com (mailing list archive)
State New, archived
Headers show
Series drm/sun4i: Support for linear and tiled YUV formats with the frontend | expand

Commit Message

Paul Kocialkowski Dec. 4, 2018, 2:22 p.m. UTC
In prevision of adding support for YUV formats, set the YUV to RGB
colorspace conversion coefficients if required and don't bypass the
CSC engine when converting.

The BT601 coefficients from the A33 BSP are copied over from the backend
code. Because of module inter-dependency, we can't have the frontend use
these coefficients from the backend directly.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
---
 drivers/gpu/drm/sun4i/sun4i_frontend.c | 45 ++++++++++++++++++++++++--
 drivers/gpu/drm/sun4i/sun4i_frontend.h |  2 ++
 2 files changed, 45 insertions(+), 2 deletions(-)

Comments

Maxime Ripard Dec. 4, 2018, 3:29 p.m. UTC | #1
On Tue, Dec 04, 2018 at 03:22:03PM +0100, Paul Kocialkowski wrote:
> In prevision of adding support for YUV formats, set the YUV to RGB
> colorspace conversion coefficients if required and don't bypass the
> CSC engine when converting.
> 
> The BT601 coefficients from the A33 BSP are copied over from the backend
> code. Because of module inter-dependency, we can't have the frontend use
> these coefficients from the backend directly.
> 
> Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_frontend.c | 45 ++++++++++++++++++++++++--
>  drivers/gpu/drm/sun4i/sun4i_frontend.h |  2 ++
>  2 files changed, 45 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
> index d0eca4b8784d..1737a4394401 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
> @@ -48,6 +48,28 @@ static const u32 sun4i_frontend_horz_coef[64] = {
>  	0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
>  };
>  
> +/*
> + * These coefficients are taken from the A33 BSP from Allwinner.
> + *
> + * The first three values of each row are coded as 13-bit signed fixed-point
> + * numbers, with 10 bits for the fractional part. The fourth value is a
> + * constant coded as a 14-bit signed fixed-point number with 4 bits for the
> + * fractional part.
> + *
> + * The values in table order give the following colorspace translation:
> + * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
> + * R = 1.164 * Y + 1.596 * V - 222
> + * B = 1.164 * Y + 2.018 * U + 276
> + *
> + * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
> + * following the BT601 spec.
> + */
> +static const u32 sunxi_bt601_yuv2rgb_coef[12] = {
> +	0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
> +	0x000004a7, 0x00000000, 0x00000662, 0x00003211,
> +	0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
> +};
> +

I'd really prefer not to duplicate that structure. IIRC, we already
have a dependency between the frontend and the backend (or the other
way around), maybe we should just move that structure to either so
that we don't have a circular dependency?

Maxime
diff mbox series

Patch

diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index d0eca4b8784d..1737a4394401 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -48,6 +48,28 @@  static const u32 sun4i_frontend_horz_coef[64] = {
 	0x03ff0000, 0x0000fd41, 0x01ff0000, 0x0000fe42,
 };
 
+/*
+ * These coefficients are taken from the A33 BSP from Allwinner.
+ *
+ * The first three values of each row are coded as 13-bit signed fixed-point
+ * numbers, with 10 bits for the fractional part. The fourth value is a
+ * constant coded as a 14-bit signed fixed-point number with 4 bits for the
+ * fractional part.
+ *
+ * The values in table order give the following colorspace translation:
+ * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135
+ * R = 1.164 * Y + 1.596 * V - 222
+ * B = 1.164 * Y + 2.018 * U + 276
+ *
+ * This seems to be a conversion from Y[16:235] UV[16:240] to RGB[0:255],
+ * following the BT601 spec.
+ */
+static const u32 sunxi_bt601_yuv2rgb_coef[12] = {
+	0x000004a7, 0x00001e6f, 0x00001cbf, 0x00000877,
+	0x000004a7, 0x00000000, 0x00000662, 0x00003211,
+	0x000004a7, 0x00000812, 0x00000000, 0x00002eb1,
+};
+
 static void sun4i_frontend_scaler_init(struct sun4i_frontend *frontend)
 {
 	int i;
@@ -188,6 +210,8 @@  int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
 	const struct drm_format_info *format = fb->format;
 	u32 out_fmt_val;
 	u32 in_fmt_val, in_mod_val, in_ps_val;
+	unsigned int i;
+	u32 bypass;
 	int ret;
 
 	ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val);
@@ -226,9 +250,26 @@  int sun4i_frontend_update_formats(struct sun4i_frontend *frontend,
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400);
 
+	/*
+	 * Checking the input format is sufficient since we currently only
+	 * support RGB output formats to the backend. If YUV output formats
+	 * ever get supported, an YUV input and output would require bypassing
+	 * the CSC engine too.
+	 */
+	if (format->is_yuv) {
+		/* Setup the CSC engine for YUV to RGB conversion. */
+		bypass = 0;
+
+		for (i = 0; i < ARRAY_SIZE(sunxi_bt601_yuv2rgb_coef); i++)
+			regmap_write(frontend->regs,
+				     SUN4I_FRONTEND_CSC_COEF_REG(i),
+				     sunxi_bt601_yuv2rgb_coef[i]);
+	} else {
+		bypass = SUN4I_FRONTEND_BYPASS_CSC_EN;
+	}
+
 	regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG,
-			   SUN4I_FRONTEND_BYPASS_CSC_EN,
-			   SUN4I_FRONTEND_BYPASS_CSC_EN);
+			   SUN4I_FRONTEND_BYPASS_CSC_EN, bypass);
 
 	regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG,
 		     in_mod_val | in_fmt_val | in_ps_val);
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h
index ad146e8d8d70..326cd5607efa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h
@@ -35,6 +35,8 @@ 
 #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888	1
 #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888	2
 
+#define SUN4I_FRONTEND_CSC_COEF_REG(c)		(0x070 + (0x4 * (c)))
+
 #define SUN4I_FRONTEND_CH0_INSIZE_REG		0x100
 #define SUN4I_FRONTEND_INSIZE(h, w)			((((h) - 1) << 16) | (((w) - 1)))