|
@@ -3253,16 +3253,12 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
|
|
+drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
|
|
|
{
|
|
|
u8 len = cea_db_payload_len(db);
|
|
|
|
|
|
- if (len >= 6) {
|
|
|
+ if (len >= 6)
|
|
|
connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */
|
|
|
- connector->dvi_dual = db[6] & 1;
|
|
|
- }
|
|
|
- if (len >= 7)
|
|
|
- connector->max_tmds_clock = db[7] * 5;
|
|
|
if (len >= 8) {
|
|
|
connector->latency_present[0] = db[8] >> 7;
|
|
|
connector->latency_present[1] = (db[8] >> 6) & 1;
|
|
@@ -3276,19 +3272,15 @@ parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
|
|
if (len >= 12)
|
|
|
connector->audio_latency[1] = db[12];
|
|
|
|
|
|
- DRM_DEBUG_KMS("HDMI: DVI dual %d, "
|
|
|
- "max TMDS clock %d, "
|
|
|
- "latency present %d %d, "
|
|
|
- "video latency %d %d, "
|
|
|
- "audio latency %d %d\n",
|
|
|
- connector->dvi_dual,
|
|
|
- connector->max_tmds_clock,
|
|
|
- (int) connector->latency_present[0],
|
|
|
- (int) connector->latency_present[1],
|
|
|
- connector->video_latency[0],
|
|
|
- connector->video_latency[1],
|
|
|
- connector->audio_latency[0],
|
|
|
- connector->audio_latency[1]);
|
|
|
+ DRM_DEBUG_KMS("HDMI: latency present %d %d, "
|
|
|
+ "video latency %d %d, "
|
|
|
+ "audio latency %d %d\n",
|
|
|
+ connector->latency_present[0],
|
|
|
+ connector->latency_present[1],
|
|
|
+ connector->video_latency[0],
|
|
|
+ connector->video_latency[1],
|
|
|
+ connector->audio_latency[0],
|
|
|
+ connector->audio_latency[1]);
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -3358,6 +3350,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|
|
|
|
|
memset(eld, 0, sizeof(connector->eld));
|
|
|
|
|
|
+ connector->latency_present[0] = false;
|
|
|
+ connector->latency_present[1] = false;
|
|
|
+ connector->video_latency[0] = 0;
|
|
|
+ connector->audio_latency[0] = 0;
|
|
|
+ connector->video_latency[1] = 0;
|
|
|
+ connector->audio_latency[1] = 0;
|
|
|
+
|
|
|
cea = drm_find_cea_extension(edid);
|
|
|
if (!cea) {
|
|
|
DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
|
|
@@ -3407,7 +3406,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|
|
case VENDOR_BLOCK:
|
|
|
/* HDMI Vendor-Specific Data Block */
|
|
|
if (cea_db_is_hdmi_vsdb(db))
|
|
|
- parse_hdmi_vsdb(connector, db);
|
|
|
+ drm_parse_hdmi_vsdb_audio(connector, db);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
@@ -3721,105 +3720,127 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
|
|
|
|
|
|
-/*
|
|
|
- * Parse the CEA extension according to CEA-861-B.
|
|
|
- * 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_display_info *info,
|
|
|
- struct drm_connector *connector)
|
|
|
+static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
|
|
|
+ const u8 *hdmi)
|
|
|
{
|
|
|
- u8 *edid_ext, *hdmi;
|
|
|
- int i;
|
|
|
- int start_offset, end_offset;
|
|
|
+ struct drm_display_info *info = &connector->display_info;
|
|
|
unsigned int dc_bpc = 0;
|
|
|
|
|
|
- edid_ext = drm_find_cea_extension(edid);
|
|
|
- if (!edid_ext)
|
|
|
- return false;
|
|
|
+ /* HDMI supports at least 8 bpc */
|
|
|
+ info->bpc = 8;
|
|
|
|
|
|
- if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
|
|
|
- return false;
|
|
|
+ if (cea_db_payload_len(hdmi) < 6)
|
|
|
+ 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,
|
|
|
- * search it from all data blocks of CEA extension.
|
|
|
+ * Deep color support mandates RGB444 support for all video
|
|
|
+ * 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) {
|
|
|
- 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);
|
|
|
- }
|
|
|
+ info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
|
|
|
|
|
- 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);
|
|
|
- }
|
|
|
+ /* 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);
|
|
|
+ }
|
|
|
|
|
|
- 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);
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * 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);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- if (dc_bpc > 0) {
|
|
|
- DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
|
|
|
- connector->name, dc_bpc);
|
|
|
- info->bpc = dc_bpc;
|
|
|
-
|
|
|
- /*
|
|
|
- * 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);
|
|
|
- }
|
|
|
+static void
|
|
|
+drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
|
|
|
+{
|
|
|
+ struct drm_display_info *info = &connector->display_info;
|
|
|
+ u8 len = cea_db_payload_len(db);
|
|
|
|
|
|
- /*
|
|
|
- * 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);
|
|
|
- }
|
|
|
+ if (len >= 6)
|
|
|
+ info->dvi_dual = db[6] & 1;
|
|
|
+ if (len >= 7)
|
|
|
+ info->max_tmds_clock = db[7] * 5000;
|
|
|
|
|
|
- return true;
|
|
|
- }
|
|
|
- else {
|
|
|
- DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
|
|
|
- connector->name);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ DRM_DEBUG_KMS("HDMI: DVI dual %d, "
|
|
|
+ "max TMDS clock %d kHz\n",
|
|
|
+ info->dvi_dual,
|
|
|
+ info->max_tmds_clock);
|
|
|
|
|
|
- return false;
|
|
|
+ drm_parse_hdmi_deep_color_info(connector, db);
|
|
|
}
|
|
|
|
|
|
-static void drm_add_display_info(struct edid *edid,
|
|
|
- struct drm_display_info *info,
|
|
|
- struct drm_connector *connector)
|
|
|
+static void drm_parse_cea_ext(struct drm_connector *connector,
|
|
|
+ struct edid *edid)
|
|
|
{
|
|
|
- u8 *edid_ext;
|
|
|
+ struct drm_display_info *info = &connector->display_info;
|
|
|
+ const u8 *edid_ext;
|
|
|
+ int i, start, end;
|
|
|
+
|
|
|
+ edid_ext = drm_find_cea_extension(edid);
|
|
|
+ if (!edid_ext)
|
|
|
+ return;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ 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))
|
|
|
+ drm_parse_hdmi_vsdb_video(connector, db);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void drm_add_display_info(struct drm_connector *connector,
|
|
|
+ struct edid *edid)
|
|
|
+{
|
|
|
+ struct drm_display_info *info = &connector->display_info;
|
|
|
|
|
|
info->width_mm = edid->width_cm * 10;
|
|
|
info->height_mm = edid->height_cm * 10;
|
|
@@ -3827,6 +3848,9 @@ static void drm_add_display_info(struct edid *edid,
|
|
|
/* driver figures it out in this case */
|
|
|
info->bpc = 0;
|
|
|
info->color_formats = 0;
|
|
|
+ info->cea_rev = 0;
|
|
|
+ info->max_tmds_clock = 0;
|
|
|
+ info->dvi_dual = false;
|
|
|
|
|
|
if (edid->revision < 3)
|
|
|
return;
|
|
@@ -3834,21 +3858,7 @@ static void drm_add_display_info(struct edid *edid,
|
|
|
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
|
|
return;
|
|
|
|
|
|
- /* Get data from CEA blocks if present */
|
|
|
- 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, info, connector);
|
|
|
+ drm_parse_cea_ext(connector, edid);
|
|
|
|
|
|
/*
|
|
|
* Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
|
|
@@ -4084,7 +4094,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))
|
|
|
edid_fixup_preferred(connector, quirks);
|
|
|
|
|
|
- drm_add_display_info(edid, &connector->display_info, connector);
|
|
|
+ drm_add_display_info(connector, edid);
|
|
|
|
|
|
if (quirks & EDID_QUIRK_FORCE_6BPC)
|
|
|
connector->display_info.bpc = 6;
|