From: Jernej Skrabec <jernej.skrabec@xxxxxxxxx> Add coefficients and support for YUV formats to the display engine colorspace and dynamic range correction submodule. Signed-off-by: Jernej Skrabec <jernej.skrabec@xxxxxxxxx> Signed-off-by: Ryan Walklin <ryan@xxxxxxxxxxxxx> --- 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.45.2