[PATCH v5 10/26] drm: sun4i: de3: add YUV support to the color space correction module

Ryan Walklin
2024-09-29T09:12:31Z

Add coefficients and support for YUV formats to the display engine
colorspace and dynamic range correction submodule.

Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Ryan Walklin <ryan@testtoast.com>
---
drivers/gpu/drm/sun4i/sun8i_csc.c | 164 +++++++++++++++++++++++++++++-
1 file changed, 162 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 8a336ccb27d33..e12a81fa91083 100644
--- a/drivers/gpu/drm/sun4i/sun8i_csc.c
+++ b/drivers/gpu/drm/sun4i/sun8i_csc.c
@@ -5,6 +5,8 @@

#include <drm/drm_print.h>

+#include <uapi/linux/media-bus-format.h>
+
#include "sun8i_csc.h"
#include "sun8i_mixer.h"

@@ -107,6 +109,135 @@ static const u32 yuv2rgb_de3[2][3][12] = {
},
};

+/* always convert to limited mode */
+static const u32 rgb2yuv_de3[3][12] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x0000837A, 0x0001021D, 0x00003221, 0x00000040,
+ 0xFFFFB41C, 0xFFFF6B03, 0x0000E0E1, 0x00000200,
+ 0x0000E0E1, 0xFFFF43B1, 0xFFFFDB6E, 0x00000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x00005D7C, 0x00013A7C, 0x00001FBF, 0x00000040,
+ 0xFFFFCC78, 0xFFFF52A7, 0x0000E0E1, 0x00000200,
+ 0x0000E0E1, 0xFFFF33BE, 0xFFFFEB61, 0x00000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x00007384, 0x00012A21, 0x00001A13, 0x00000040,
+ 0xFFFFC133, 0xFFFF5DEC, 0x0000E0E1, 0x00000200,
+ 0x0000E0E1, 0xFFFF3135, 0xFFFFEDEA, 0x00000200,
+ },
+};
+
+/* always convert to limited mode */
+static const u32 yuv2yuv_de3[2][3][3][12] = {
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x00020000, 0xFFFFC4D7, 0xFFFF9589, 0xFFC00040,
+ 0x00000000, 0x0002098B, 0x00003AAF, 0xFE000200,
+ 0x00000000, 0x0000266D, 0x00020CF8, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x00020000, 0xFFFFBFCE, 0xFFFFC5FF, 0xFFC00040,
+ 0x00000000, 0x00020521, 0x00001F89, 0xFE000200,
+ 0x00000000, 0x00002C87, 0x00020F07, 0xFE000200,
+ },
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x00020000, 0x000032D9, 0x00006226, 0xFFC00040,
+ 0x00000000, 0x0001FACE, 0xFFFFC759, 0xFE000200,
+ 0x00000000, 0xFFFFDAE7, 0x0001F780, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x00020000, 0xFFFFF782, 0x00003036, 0xFFC00040,
+ 0x00000000, 0x0001FD99, 0xFFFFE5CA, 0xFE000200,
+ 0x00000000, 0x000005E4, 0x0002015A, 0xFE000200,
+ },
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x00020000, 0x00003B03, 0x000034D2, 0xFFC00040,
+ 0x00000000, 0x0001FD8C, 0xFFFFE183, 0xFE000200,
+ 0x00000000, 0xFFFFD4F3, 0x0001F3FA, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x00020000, 0x00000916, 0xFFFFD061, 0xFFC00040,
+ 0x00000000, 0x0002021C, 0x00001A40, 0xFE000200,
+ 0x00000000, 0xFFFFFA19, 0x0001FE5A, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x00020000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00020000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00000000,
+ },
+ },
+ },
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x0001B7B8, 0xFFFFCC08, 0xFFFFA27B, 0x00000040,
+ 0x00000000, 0x0001CA24, 0x0000338D, 0xFE000200,
+ 0x00000000, 0x000021C1, 0x0001CD26, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x0001B7B8, 0xFFFFC79C, 0xFFFFCD0C, 0x00000040,
+ 0x00000000, 0x0001C643, 0x00001BB4, 0xFE000200,
+ 0x00000000, 0x0000271D, 0x0001CEF5, 0xFE000200,
+ },
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x0001B7B8, 0x00002CAB, 0x00005638, 0x00000040,
+ 0x00000000, 0x0001BD32, 0xFFFFCE3C, 0xFE000200,
+ 0x00000000, 0xFFFFDF6A, 0x0001BA4A, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x0001B7B8, 0xFFFFF88A, 0x00002A5A, 0x00000040,
+ 0x00000000, 0x0001BFA5, 0xFFFFE8FA, 0xFE000200,
+ 0x00000000, 0x0000052D, 0x0001C2F1, 0xFE000200,
+ },
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ 0x0001B7B8, 0x000033D6, 0x00002E66, 0x00000040,
+ 0x00000000, 0x0001BF9A, 0xFFFFE538, 0xFE000200,
+ 0x00000000, 0xFFFFDA2F, 0x0001B732, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ 0x0001B7B8, 0x000007FB, 0xFFFFD62B, 0x00000040,
+ 0x00000000, 0x0001C39D, 0x0000170F, 0xFE000200,
+ 0x00000000, 0xFFFFFAD1, 0x0001C04F, 0xFE000200,
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ 0x0001B7B8, 0x00000000, 0x00000000, 0x00000040,
+ 0x00000000, 0x0001C1C2, 0x00000000, 0xFE000200,
+ 0x00000000, 0x00000000, 0x0001C1C2, 0xFE000200,
+ },
+ },
+ },
+};
+
static void sun8i_csc_setup(struct regmap *map, u32 base,
enum format_type fmt_type,
enum drm_color_encoding encoding,
@@ -148,12 +279,27 @@ static void sun8i_csc_setup(struct regmap *map, u32 base,
regmap_write(map, SUN8I_CSC_CTRL(base), val);
}

+static const u32 *sun8i_csc_get_de3_yuv_table(enum drm_color_encoding in_enc,
+ enum drm_color_range in_range,
+ u32 out_format,
+ enum drm_color_encoding out_enc)
+{
+ if (out_format == MEDIA_BUS_FMT_RGB888_1X24)
+ return yuv2rgb_de3[in_range][in_enc];
+
+ /* check for identity transformation */
+ if (in_range == DRM_COLOR_YCBCR_LIMITED_RANGE && out_enc == in_enc)
+ return NULL;
+
+ return yuv2yuv_de3[in_range][in_enc][out_enc];
+}
+
static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,
enum format_type fmt_type,
enum drm_color_encoding encoding,
enum drm_color_range range)
{
- u32 addr, val, mask;
+ u32 addr, val = 0, mask;
struct regmap *map;
const u32 *table;
int i;
@@ -164,14 +310,28 @@ static void sun8i_de3_ccsc_setup(struct sunxi_engine *engine, int layer,

switch (fmt_type) {
case FORMAT_TYPE_RGB:
- val = 0;
+ if (engine->format == MEDIA_BUS_FMT_RGB888_1X24)
+ break;
+ val = mask;
+ addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
+ regmap_bulk_write(map, addr, rgb2yuv_de3[engine->encoding], 12);
break;
case FORMAT_TYPE_YUV:
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
+ engine->format,
+ engine->encoding);
+ if (!table)
+ break;
val = mask;
addr = SUN50I_MIXER_BLEND_CSC_COEFF(DE3_BLD_BASE, layer, 0);
regmap_bulk_write(map, addr, table, 12);
break;
case FORMAT_TYPE_YVU:
+ table = sun8i_csc_get_de3_yuv_table(encoding, range,
+ engine->format,
+ engine->encoding);
+ if (!table)
+ table = yuv2yuv_de3[range][encoding][encoding];
val = mask;
for (i = 0; i < 12; i++) {
if ((i & 3) == 1)
--
2.46.1