Commit 1cea146a authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/edid: Reduce the number of times we parse the CEA extension block

Instead of parsing parts of the CEA extension block in two places
to determine supported color formats and whatnot, let's just
consolidate it to one function. This also makes it possible to neatly
flatten drm_assign_hdmi_deep_color_info().
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1475070703-6435-7-git-send-email-ville.syrjala@linux.intel.com
parent 1826750f
...@@ -3733,105 +3733,110 @@ bool drm_rgb_quant_range_selectable(struct edid *edid) ...@@ -3733,105 +3733,110 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
} }
EXPORT_SYMBOL(drm_rgb_quant_range_selectable); EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
/* static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
* Parse the CEA extension according to CEA-861-B. const u8 *hdmi)
* Return true if HDMI deep color supported, false if not or unknown.
*/
static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
struct drm_connector *connector)
{ {
struct drm_display_info *info = &connector->display_info; struct drm_display_info *info = &connector->display_info;
u8 *edid_ext, *hdmi;
int i;
int start_offset, end_offset;
unsigned int dc_bpc = 0; unsigned int dc_bpc = 0;
edid_ext = drm_find_cea_extension(edid); /* HDMI supports at least 8 bpc */
if (!edid_ext) info->bpc = 8;
return false;
if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) if (cea_db_payload_len(hdmi) < 6)
return false; return;
if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
dc_bpc = 10;
info->edid_hdmi_dc_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;
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;
DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
connector->name);
}
if (dc_bpc == 0) {
DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
connector->name);
return;
}
DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
connector->name, dc_bpc);
info->bpc = dc_bpc;
/* /*
* Because HDMI identifier is in Vendor Specific Block, * Deep color support mandates RGB444 support for all video
* search it from all data blocks of CEA extension. * modes and forbids YCRCB422 support for all video modes per
* HDMI 1.3 spec.
*/ */
for_each_cea_db(edid_ext, i, start_offset, end_offset) { info->color_formats = DRM_COLOR_FORMAT_RGB444;
if (cea_db_is_hdmi_vsdb(&edid_ext[i])) {
/* HDMI supports at least 8 bpc */
info->bpc = 8;
hdmi = &edid_ext[i];
if (cea_db_payload_len(hdmi) < 6)
return false;
if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
dc_bpc = 10;
info->edid_hdmi_dc_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) { /* YCRCB444 is optional according to spec. */
dc_bpc = 12; if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36; info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
DRM_DEBUG("%s: HDMI sink does deep color 36.\n", DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
connector->name); connector->name);
} }
if (hdmi[6] & DRM_EDID_HDMI_DC_48) { /*
dc_bpc = 16; * Spec says that if any deep color mode is supported at all,
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48; * then deep color 36 bit must be supported.
DRM_DEBUG("%s: HDMI sink does deep color 48.\n", */
connector->name); if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
} DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
connector->name);
}
}
if (dc_bpc > 0) { static void drm_parse_cea_ext(struct drm_connector *connector,
DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n", struct edid *edid)
connector->name, dc_bpc); {
info->bpc = dc_bpc; struct drm_display_info *info = &connector->display_info;
const u8 *edid_ext;
/* int i, start, end;
* Deep color support mandates RGB444 support for all video
* modes and forbids YCRCB422 support for all video modes per
* HDMI 1.3 spec.
*/
info->color_formats = DRM_COLOR_FORMAT_RGB444;
/* YCRCB444 is optional according to spec. */
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
connector->name);
}
/* edid_ext = drm_find_cea_extension(edid);
* Spec says that if any deep color mode is supported at all, if (!edid_ext)
* then deep color 36 bit must be supported. return;
*/
if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
connector->name);
}
return true; info->cea_rev = edid_ext[1];
}
else {
DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
connector->name);
}
}
}
return false; /* The existence of a CEA block should imply RGB support */
info->color_formats = DRM_COLOR_FORMAT_RGB444;
if (edid_ext[3] & EDID_CEA_YCRCB444)
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
if (edid_ext[3] & EDID_CEA_YCRCB422)
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
if (cea_db_offsets(edid_ext, &start, &end))
return;
for_each_cea_db(edid_ext, i, start, end) {
const u8 *db = &edid_ext[i];
if (!cea_db_is_hdmi_vsdb(db))
continue;
drm_parse_hdmi_deep_color_info(connector, db);
}
} }
static void drm_add_display_info(struct edid *edid, static void drm_add_display_info(struct drm_connector *connector,
struct drm_connector *connector) struct edid *edid)
{ {
struct drm_display_info *info = &connector->display_info; struct drm_display_info *info = &connector->display_info;
u8 *edid_ext;
info->width_mm = edid->width_cm * 10; info->width_mm = edid->width_cm * 10;
info->height_mm = edid->height_cm * 10; info->height_mm = edid->height_cm * 10;
...@@ -3846,21 +3851,7 @@ static void drm_add_display_info(struct edid *edid, ...@@ -3846,21 +3851,7 @@ static void drm_add_display_info(struct edid *edid,
if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
return; return;
/* Get data from CEA blocks if present */ drm_parse_cea_ext(connector, edid);
edid_ext = drm_find_cea_extension(edid);
if (edid_ext) {
info->cea_rev = edid_ext[1];
/* The existence of a CEA block should imply RGB support */
info->color_formats = DRM_COLOR_FORMAT_RGB444;
if (edid_ext[3] & EDID_CEA_YCRCB444)
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
if (edid_ext[3] & EDID_CEA_YCRCB422)
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
}
/* HDMI deep color modes supported? Assign to info, if so */
drm_assign_hdmi_deep_color_info(edid, connector);
/* /*
* Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
...@@ -4096,7 +4087,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) ...@@ -4096,7 +4087,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
edid_fixup_preferred(connector, quirks); edid_fixup_preferred(connector, quirks);
drm_add_display_info(edid, connector); drm_add_display_info(connector, edid);
if (quirks & EDID_QUIRK_FORCE_6BPC) if (quirks & EDID_QUIRK_FORCE_6BPC)
connector->display_info.bpc = 6; connector->display_info.bpc = 6;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment