From 8bb896aff75407632108d2bc745973a5b1ad9807 Mon Sep 17 00:00:00 2001
From: Devarsh Thakkar <devarsht@ti.com>
Date: Sat, 19 Apr 2025 15:38:17 +0530
Subject: [PATCH 3/3] HACK: drm/tidss: Add bt656 progressive mode support

Add bt656 progressive mode support with scaling
table for NTSC 720x480 resolution.

Signed-off-by: Devarsh Thakkar <devarsht@ti.com>
---
 drivers/gpu/drm/tidss/tidss_dispc.c | 102 +++++++++++++++++++++-------
 drivers/gpu/drm/tidss/tidss_drv.c   |   1 +
 drivers/gpu/drm/tidss/tidss_drv.h   |   1 +
 3 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
index e235741d84f7..9f92780a1dc2 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -1176,6 +1176,7 @@ struct dispc_bus_format {
 static const struct dispc_bus_format dispc_bus_formats[] = {
 	{ MEDIA_BUS_FMT_RGB444_1X12,		12, false, 0 },
 	{ MEDIA_BUS_FMT_RGB565_1X16,		16, false, 0 },
+	{ MEDIA_BUS_FMT_UYVY8_2X8,		16, false, 0 },
 	{ MEDIA_BUS_FMT_RGB666_1X18,		18, false, 0 },
 	{ MEDIA_BUS_FMT_RGB888_1X24,		24, false, 0 },
 	{ MEDIA_BUS_FMT_RGB101010_1X30,		30, false, 0 },
@@ -1350,15 +1351,29 @@ void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
 	vsw = mode->vsync_end - mode->vsync_start;
 	vbp = mode->vtotal - mode->vsync_end;
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
-		       FLD_VAL(hsw - 1, 7, 0) |
-		       FLD_VAL(hfp - 1, 19, 8) |
-		       FLD_VAL(hbp - 1, 31, 20));
+	if (dispc->tidss->bt656_enabled) {
+		dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
+				FLD_VAL(((hsw & 0xFF) - 1), 7, 0) |
+				FLD_VAL(hfp - 1, 19, 8) |
+				FLD_VAL(hbp - 1, 31, 20));
+	} else {
+		dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
+				FLD_VAL(hsw - 1, 7, 0) |
+				FLD_VAL(hfp - 1, 19, 8) |
+				FLD_VAL(hbp - 1, 31, 20));
+	}
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
-		       FLD_VAL(vsw - 1, 7, 0) |
-		       FLD_VAL(vfp, 19, 8) |
-		       FLD_VAL(vbp, 31, 20));
+	if (dispc->tidss->bt656_enabled) {
+		dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
+				FLD_VAL(((hsw) >> 8), 3, 0) |
+				FLD_VAL(vfp, 19, 8) |
+				FLD_VAL(vbp, 31, 20));
+	} else {
+		dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
+				FLD_VAL(vsw - 1, 7, 0) |
+				FLD_VAL(vfp, 19, 8) |
+				FLD_VAL(vbp, 31, 20));
+	}
 
 	ivs = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
 
@@ -1540,14 +1555,26 @@ enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
 	vsw = mode->vsync_end - mode->vsync_start;
 	vbp = mode->vtotal - mode->vsync_end;
 
-	if (hsw < 1 || hsw > 256 ||
-	    hfp < 1 || hfp > 4096 ||
-	    hbp < 1 || hbp > 4096)
-		return MODE_BAD_HVALUE;
 
-	if (vsw < 1 || vsw > 256 ||
-	    vfp > 4095 || vbp > 4095)
-		return MODE_BAD_VVALUE;
+	if (dispc->tidss->bt656_enabled) {
+		if (hsw < 1 || hsw > 554 ||
+		    hfp < 1 || hfp > 4096 ||
+		    hbp < 1 || hbp > 4096)
+			return MODE_BAD_HVALUE;
+
+		if (vsw < 0 || vsw > 256 ||
+		    vfp > 4095 || vbp > 4095)
+			return MODE_BAD_VVALUE;
+	} else {
+		if (hsw < 1 || hsw > 256 ||
+		    hfp < 1 || hfp > 4096 ||
+		    hbp < 1 || hbp > 4096)
+			return MODE_BAD_HVALUE;
+
+		if (vsw < 1 || vsw > 256 ||
+		    vfp > 4095 || vbp > 4095)
+			return MODE_BAD_VVALUE;
+	}
 
 	if (dispc->memory_bandwidth_limit) {
 		if (!dispc->tidss->shared_mode ||
@@ -1758,15 +1785,15 @@ void dispc_csc_yuv2rgb_regval(const struct dispc_csc_coef *csc, u32 *regval)
 	dispc_csc_offset_regval(csc, regval);
 }
 
-__maybe_unused static
+static
 void dispc_csc_rgb2yuv_regval(const struct dispc_csc_coef *csc, u32 *regval)
 {
 	regval[0] = CVAL(csc->m[CSC_YR], csc->m[CSC_YG]);
-	regval[1] = CVAL(csc->m[CSC_YB], csc->m[CSC_CRR]);
-	regval[2] = CVAL(csc->m[CSC_CRG], csc->m[CSC_CRB]);
-	regval[3] = CVAL(csc->m[CSC_CBR], csc->m[CSC_CBG]);
-	regval[4] = CVAL(csc->m[CSC_CBB], 0);
-
+	regval[1] = CVAL(csc->m[CSC_YB], csc->m[CSC_CBR]);
+	regval[2] = CVAL(csc->m[CSC_CBG], csc->m[CSC_CBB]);
+	regval[3] = CVAL(csc->m[CSC_CRR], csc->m[CSC_CRG]);
+	regval[4] = CVAL(csc->m[CSC_CRB], 0);
+	pr_info("csc->m[CSS_CbR] %x fld_val %x \n", csc->m[CSC_CBR], FLD_VAL(-38, 26, 16));
 	dispc_csc_offset_regval(csc, regval);
 }
 
@@ -1874,6 +1901,19 @@ static const struct dispc_csc_coef csc_yuv2rgb_bt709_lim = {
 	"BT.709 Limited",
 };
 
+
+/* YUV -> RGB, ITU-R BT.601, limited range */
+static const struct dispc_csc_coef csc_rgb2yuv_bt601_lim = {
+	dispc_csc_rgb2yuv_regval,
+	{ 66,  129,  25,	/* ry, rcb, rcr |0.257  0.504  0.098|*/
+	 -38,  -75, 112,	/* gy, gcb, gcr |-0.148 -0.291 0.439|*/
+	  112, -94, -18, },	/* by, bcb, bcr |0.439  -0.368  -0.071|*/
+	{  0,    0,  0, },
+	{ 256, 2048, 2048, },	/* limited range */
+	CLIP_FULL_RANGE,
+	"BT.601 Limited",
+};
+
 static const struct {
 	enum drm_color_encoding encoding;
 	enum drm_color_range range;
@@ -1887,6 +1927,8 @@ static const struct {
 	  &csc_yuv2rgb_bt709_full, },
 	{ DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE,
 	  &csc_yuv2rgb_bt709_lim, },
+	{ DRM_COLOR_YCBCR_BT601, DRM_COLOR_YCBCR_LIMITED_RANGE,
+	  &csc_rgb2yuv_bt601_lim, },
 };
 
 static const
@@ -2620,8 +2662,11 @@ static void dispc_vp_init(struct dispc_device *dispc)
 	dev_dbg(dispc->dev, "%s()\n", __func__);
 
 	/* Enable the gamma Shadow bit-field for all VPs*/
-	for (i = 0; i < dispc->feat->num_vps; i++)
+	for (i = 0; i < dispc->feat->num_vps; i++) {
 		VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1, 2, 2);
+		if (dispc->tidss->bt656_enabled)
+			VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1, 20, 20);
+	}
 }
 
 static void dispc_initial_config(struct dispc_device *dispc)
@@ -2904,11 +2949,14 @@ static void dispc_k3_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
 
 	csc->to_regval(csc, regval);
 
-	for (i = 0; i < ARRAY_SIZE(regval); i++)
+	for (i = 0; i < ARRAY_SIZE(regval); i++) {
+		pr_info("Writing %x at %x\n", dispc_vp_csc_coef_reg[i], regval[i]);
 		dispc_vp_write(dispc, hw_videoport, dispc_vp_csc_coef_reg[i],
 			       regval[i]);
+	}
 }
 
+
 static void dispc_k3_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
 				struct drm_color_ctm *ctm)
 {
@@ -2952,6 +3000,14 @@ static void dispc_vp_set_color_mgmt(struct dispc_device *dispc,
 		dispc_k2g_vp_set_ctm(dispc, hw_videoport, ctm);
 	else
 		dispc_k3_vp_set_ctm(dispc, hw_videoport, ctm);
+
+	if (dispc->tidss->bt656_enabled) {
+		dispc_k3_vp_write_csc(dispc, hw_videoport, dispc_csc_table[4].csc);
+		u8 colorconvenable = 1;
+
+		VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
+				colorconvenable, 24, 24);
+	}
 }
 
 static int get_vp_idx_from_vp(const char *vp_name)
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 284c2364e96b..a54e2cfcaaed 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -252,6 +252,7 @@ static int tidss_probe(struct platform_device *pdev)
 
 	spin_lock_init(&tidss->irq_lock);
 
+	tidss->bt656_enabled = device_property_read_bool(dev, "ti,bt656-mode");
 	tidss->shared_mode = device_property_read_bool(dev, "ti,dss-shared-mode");
 	if (!tidss->shared_mode) {
 		/* powering up associated OLDI domains */
diff --git a/drivers/gpu/drm/tidss/tidss_drv.h b/drivers/gpu/drm/tidss/tidss_drv.h
index 99d4711ad3ab..fd4e292a2e1c 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.h
+++ b/drivers/gpu/drm/tidss/tidss_drv.h
@@ -49,6 +49,7 @@ struct tidss_device {
 
 	u32 boot_enabled_vp_mask;
 	bool simplefb_enabled;
+	bool bt656_enabled;
 };
 
 #define to_tidss(__dev) container_of(__dev, struct tidss_device, ddev)
-- 
2.39.1

