Skip to content

drm/hdmi: fix Dolby Vision colour base at decide time#31

Closed
allolive wants to merge 1 commit into
CoreELEC:5.15.196_20260225from
allolive:dv-4k-colour-base
Closed

drm/hdmi: fix Dolby Vision colour base at decide time#31
allolive wants to merge 1 commit into
CoreELEC:5.15.196_20260225from
allolive:dv-4k-colour-base

Conversation

@allolive

Copy link
Copy Markdown
Contributor

decide_color_attr picks the colour base from hdmi_current_eotf_type, but for Dolby Vision that is not set yet when the mode is committed (the DV core sets it later over VSIF). So a DV title gets an SDR base: no signal at 4K60, and the wrong depth after a 24/23.976 switch.

is_amdv_enable() and get_amdv_ll_policy() are already valid here, so use them to pin the tunnel base for any 4K vic: TV-led is YUV444 8-bit, player-led is YUV422 12-bit. SDR and HDR10 are left alone.

Needs the matching xbmc change to force the re-decide.

decide_color_attr picks the colour base from hdmi_current_eotf_type, but for
Dolby Vision that is not set yet when the mode is committed (the DV core sets
it later over VSIF). So a DV title gets an SDR base: no signal at 4K60, and the
wrong depth after a 24/23.976 switch.

is_amdv_enable() and get_amdv_ll_policy() are already valid here, so use them to
pin the tunnel base for any 4K vic: TV-led is YUV444 8-bit, player-led is YUV422
12-bit. SDR and HDR10 are left alone.

Needs the matching xbmc change to force the re-decide.

Signed-off-by: Olivier Allauzen <olivier.allauzen@gmail.com>
@Portisch

Portisch commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Instead force on end rewrite it complete?
You said the is_amdv_enable() is working relailable. Please test!
Then the test of hdmi_current_eotf_type is useless.

But maybe it's still good to check hdmi_current_tunnel_mode as it may indicate RGB 10/12bit support instead 8bit only.

diff --git a/drivers/drm/meson_hdmi.c b/drivers/drm/meson_hdmi.c
index 69e6db48a2..1c431e8d79 100644
--- a/drivers/drm/meson_hdmi.c
+++ b/drivers/drm/meson_hdmi.c
@@ -319,140 +319,97 @@ static int meson_hdmitx_decide_color_attr
 	// try autoselect
 	// check if any colour subsampling is set
 	// force colour subsampling when DV mode
-	switch (common->hdmi_current_eotf_type) {
-		case EOTF_T_DOLBYVISION:
-		case EOTF_T_LL_MODE:
-		case EOTF_T_DV_AHEAD:
-			{
-				int cs = attr->colorformat;
-				switch (common->hdmi_current_tunnel_mode) {
-					case RGB_8BIT:
-					case RGB_10_12BIT:
-						attr->colorformat = HDMI_COLORSPACE_YUV444;
-						break;
-					case YUV422_BIT12:
-						attr->colorformat = HDMI_COLORSPACE_YUV422;
-						break;
-					case YUV444_10_12BIT:
-						attr->colorformat = HDMI_COLORSPACE_YUV444;
-						break;
-					default:
-						break;
-				}
-				if (cs != attr->colorformat)
-					DRM_INFO("[%s]: display colour subsampling is forced to %s by Dolby Vision tunneling\n", __func__,
-						colour_sampling[attr->colorformat]);
-			}
-			break;
-		default:
-			if (strstr(common->fmt_attr, "rgb") == NULL &&
-			    strstr(common->fmt_attr, "420") == NULL &&
-			    strstr(common->fmt_attr, "422") == NULL &&
-			    strstr(common->fmt_attr, "444") == NULL) {
-				if (is_hdmi4k_support_420(vic & 0xff)) {
-					/*
-					* Use YCbCr 4:2:2 when supported by the sink,
-					* otherwise retain the existing YCbCr 4:2:0
-					* behaviour.
-					*/
-					if (is_support_y422(&common->rxcap))
-						attr->colorformat = HDMI_COLORSPACE_YUV422;
-					else
-						attr->colorformat = HDMI_COLORSPACE_YUV420;
-
-					DRM_INFO("[%s]: display colour subsampling is forced to %s because of current video information code %d\n", __func__,
-						colour_sampling[attr->colorformat], vic);
-				}
+	if (is_amdv_enable()) {
+		int cs = attr->colorformat;
+		if (get_amdv_ll_policy() == DOLBY_VISION_LL_YUV422) {
+			attr->colorformat = HDMI_COLORSPACE_YUV422;
+		} else {
+			attr->colorformat = HDMI_COLORSPACE_YUV444;
+		}
+		if (cs != attr->colorformat)
+			DRM_INFO("[%s]: display colour subsampling is forced to %s by Dolby Vision tunneling\n", __func__,
+				colour_sampling[attr->colorformat]);
+	} else {
+		if (strstr(common->fmt_attr, "rgb") == NULL &&
+		    strstr(common->fmt_attr, "420") == NULL &&
+		    strstr(common->fmt_attr, "422") == NULL &&
+		    strstr(common->fmt_attr, "444") == NULL) {
+			if (is_hdmi4k_support_420(vic & 0xff)) {
+				/*
+				* Use YCbCr 4:2:2 when supported by the sink,
+				* otherwise retain the existing YCbCr 4:2:0
+				* behaviour.
+				*/
+				if (is_support_y422(&common->rxcap))
+					attr->colorformat = HDMI_COLORSPACE_YUV422;
 				else
-					DRM_INFO("[%s]: display colour subsampling is auto set to %s\n", __func__,
-						colour_sampling[attr->colorformat]);
+					attr->colorformat = HDMI_COLORSPACE_YUV420;
+
+				DRM_INFO("[%s]: display colour subsampling is forced to %s because of current video information code %d\n", __func__,
+					colour_sampling[attr->colorformat], vic);
 			}
 			else
-			{
-				DRM_INFO("[%s]: display colour subsampling is forced by attr to %s: %s\n", __func__,
-					colour_sampling[fmt_attr.colorformat], common->fmt_attr);
-					attr->colorformat = fmt_attr.colorformat;
-			}
-			break;
+				DRM_INFO("[%s]: display colour subsampling is auto set to %s\n", __func__,
+					colour_sampling[attr->colorformat]);
+		}
+		else
+		{
+			DRM_INFO("[%s]: display colour subsampling is forced by attr to %s: %s\n", __func__,
+				colour_sampling[fmt_attr.colorformat], common->fmt_attr);
+				attr->colorformat = fmt_attr.colorformat;
+		}
 	}
 
 	// parse and set maximum colourdepth given by edid
 	// check for colour subsampling limit
-	switch (common->hdmi_current_eotf_type) {
-		case EOTF_T_DOLBYVISION:
-		case EOTF_T_LL_MODE:
-		case EOTF_T_DV_AHEAD:
-			{
-				const struct dv_info *dv_info = &common->rxcap.dv_info;
-				int cd = bitdepth_to_colordepth(attr->bitdepth);
-				switch (common->hdmi_current_tunnel_mode) {
-					case RGB_8BIT:
-							attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
-						break;
-					case RGB_10_12BIT:
-					case YUV444_10_12BIT:
-						if (dv_info->ver == 2) {
-							switch (dv_info->sup_10b_12b_444) {
-								case 1:
-									attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_30B);
-									break;
-								case 2:
-									attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_36B);
-									break;
-								default:
-									break;
-							}
-						}
-						break;
-					case YUV422_BIT12:
-						attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_36B);
-						break;
-					default:
+	if (is_amdv_enable()) {
+		const struct dv_info *dv_info = &common->rxcap.dv_info;
+		int cd = bitdepth_to_colordepth(attr->bitdepth);
+		if (get_amdv_ll_policy() == DOLBY_VISION_LL_YUV422) {
+			attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_36B);
+		} else {
+			attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
+		}
+		if (cd != bitdepth_to_colordepth(attr->bitdepth))
+			DRM_INFO("[%s]: display colourdepth is forced to %d bits because of Dolby Vision sink capability\n", __func__,
+				attr->bitdepth);
+	} else {
+		// check colourdepth
+		if (strstr(common->fmt_attr, "bit") != NULL) {
+			DRM_INFO("[%s]: display colourdepth is forced by attr to %d bits: %s\n", __func__,
+				fmt_attr.bitdepth, common->fmt_attr);
+				attr->bitdepth = fmt_attr.bitdepth;
+		} else {
+			if (common->rxcap.ColorDeepSupport & 0x78 && attr->colorformat != HDMI_COLORSPACE_YUV420) {
+				enum hdmi_color_depth cd;
+				for (cd = COLORDEPTH_30B; cd >= COLORDEPTH_24B; cd--) {
+					if (common->rxcap.ColorDeepSupport & (1 << (cd - 1))) {
+						attr->bitdepth = colordepth_to_bitdepth(cd);
 						break;
-				}
-				if (cd != bitdepth_to_colordepth(attr->bitdepth))
-					DRM_INFO("[%s]: display colourdepth is forced to %d bits because of Dolby Vision sink capability\n", __func__,
-						attr->bitdepth);
-			}
-			break;
-		default:
-			// check colourdepth
-			if (strstr(common->fmt_attr, "bit") != NULL) {
-				DRM_INFO("[%s]: display colourdepth is forced by attr to %d bits: %s\n", __func__,
-					fmt_attr.bitdepth, common->fmt_attr);
-					attr->bitdepth = fmt_attr.bitdepth;
-			} else {
-				if (common->rxcap.ColorDeepSupport & 0x78 && attr->colorformat != HDMI_COLORSPACE_YUV420) {
-					enum hdmi_color_depth cd;
-					for (cd = COLORDEPTH_30B; cd >= COLORDEPTH_24B; cd--) {
-						if (common->rxcap.ColorDeepSupport & (1 << (cd - 1))) {
-							attr->bitdepth = colordepth_to_bitdepth(cd);
-							break;
-						}
 					}
-				} else if (common->rxcap.hf_ieeeoui == HF_IEEEOUI) {
-					if (common->rxcap.dc_30bit_420)
-						attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_30B);
-					else
-						attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
 				}
+			} else if (common->rxcap.hf_ieeeoui == HF_IEEEOUI) {
+				if (common->rxcap.dc_30bit_420)
+					attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_30B);
+				else
+					attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
+			}
 
-				if (is_hdmi4k_support_420(vic & 0xff)) {
-					if (attr->colorformat == HDMI_COLORSPACE_RGB || attr->colorformat == HDMI_COLORSPACE_YUV444) {
-						attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
-						DRM_INFO("[%s]: display colourdepth is forced to %d bits because of current video information code %d\n", __func__,
-							attr->bitdepth, vic);
-					}
-				}
-				if (common->flag_3dfp) {
+			if (is_hdmi4k_support_420(vic & 0xff)) {
+				if (attr->colorformat == HDMI_COLORSPACE_RGB || attr->colorformat == HDMI_COLORSPACE_YUV444) {
 					attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
-					DRM_INFO("[%s]: display colourdepth is auto set to %d bits because of 3dfp mode\n", __func__,
-						attr->bitdepth);
-				} else
-					DRM_INFO("[%s]: display colourdepth is auto set to %d bits\n", __func__,
-						attr->bitdepth);
+					DRM_INFO("[%s]: display colourdepth is forced to %d bits because of current video information code %d\n", __func__,
+						attr->bitdepth, vic);
+				}
 			}
-			break;
+			if (common->flag_3dfp) {
+				attr->bitdepth = colordepth_to_bitdepth(COLORDEPTH_24B);
+				DRM_INFO("[%s]: display colourdepth is auto set to %d bits because of 3dfp mode\n", __func__,
+					attr->bitdepth);
+			} else
+				DRM_INFO("[%s]: display colourdepth is auto set to %d bits\n", __func__,
+					attr->bitdepth);
+		}
 	}
 
 	DRM_INFO("[%s]:[%s,eotf:%d,vic:%d]=>attr[%s,%dbit]\n", __func__,

@Portisch Portisch closed this in 6e10fef Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants