From 2c866e31ecf2386fc4ca5f0b83ee8438c99a27d0 Mon Sep 17 00:00:00 2001 From: Nicholas Sielicki Date: Wed, 4 Jan 2017 16:41:39 -0600 Subject: [PATCH] Disable deep color modes when sink violates spec As per the HDMI 1.3 and 1.4 spec, "deep color modes" are color depths greater than 24 bits per pixel. The spec explicitly states, "All Deep Color modes are optional though if an HDMI Source or Sink supports any Deep Color mode, it shall support 36-bit mode." (6.2.4 Color Depth Requirements). i915 relies on this being respected. Much of the intel hardware is incapable of operating at any bit-per-component setting besides 8 and 12, and the spec implies that if any deep color support is found that it is a safe assumption to operate at 12. I came across a monitor (Acer X233H) that supplies an illegal EDID where DC_30bit is set and DC_36bit is not set. The end result is badly garbled output because the driver is sending 36BPP when the monitor can't handle it. This patch ensures that the EDID is within the spec (specifically, that DC_36bit is set) _before_ committing going forward with deep colors. There was a check for this EDID inconsistency, but it resulted only in a warning and did not fall-back to safer settings. --- drivers/gpu/drm/drm_edid.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 336be31ff3de..6ea5387b30e5 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3772,6 +3772,7 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, { struct drm_display_info *info = &connector->display_info; unsigned int dc_bpc = 0; + u8 modes = 0; /* HDMI supports at least 8 bpc */ info->bpc = 8; @@ -3781,21 +3782,21 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, if (hdmi[6] & DRM_EDID_HDMI_DC_30) { dc_bpc = 10; - info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30; + modes |= DRM_EDID_HDMI_DC_30; DRM_DEBUG("%s: HDMI sink does deep color 30.\n", connector->name); } if (hdmi[6] & DRM_EDID_HDMI_DC_36) { dc_bpc = 12; - info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36; + modes |= DRM_EDID_HDMI_DC_36; DRM_DEBUG("%s: HDMI sink does deep color 36.\n", connector->name); } if (hdmi[6] & DRM_EDID_HDMI_DC_48) { dc_bpc = 16; - info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48; + modes |= DRM_EDID_HDMI_DC_48; DRM_DEBUG("%s: HDMI sink does deep color 48.\n", connector->name); } @@ -3806,6 +3807,20 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, return; } + /* + * All deep color modes are optional, but if a sink supports any deep + * color mode, it must support 36-bit mode. If this is found not + * to be the case, sink is in violation of HDMI 1.3 / 1.4 spec and it + * is prudent to diable all deep color modes. Return here before + * committing bpc and DRM_EDID_DC_XX. + */ + if (modes & ~DRM_EDID_HDMI_DC_36){ + DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n", + connector->name); + return; + } + + info->edid_hdmi_dc_modes |= modes; DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n", connector->name, dc_bpc); info->bpc = dc_bpc; @@ -3823,15 +3838,6 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector, DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n", connector->name); } - - /* - * Spec says that if any deep color mode is supported at all, - * then deep color 36 bit must be supported. - */ - if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) { - DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n", - connector->name); - } } static void -- 2.11.0