aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2014-03-27 14:59:39 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-06-02 18:37:34 -0400
commitd0c94692e0a360828745a469bcf90b5c4f9273d0 (patch)
tree80cf5a1317b3318b1dfdac117fca60ee28245947 /drivers/gpu/drm/drm_edid.c
parent89b92339c1362ee910b0c73c2db32af11246c250 (diff)
drm/edid: Parse and handle HDMI deep color modes.
Check the HDMI cea block for deep color mode bits. If available, assign the highest supported bpc for a hdmi display, corresponding to the given deep color modes. Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c110
1 files changed, 108 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d74239fec291..3989c185579f 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3423,16 +3423,116 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
3423EXPORT_SYMBOL(drm_rgb_quant_range_selectable); 3423EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
3424 3424
3425/** 3425/**
3426 * drm_assign_hdmi_deep_color_info - detect whether monitor supports
3427 * hdmi deep color modes and update drm_display_info if so.
3428 *
3429 * @edid: monitor EDID information
3430 * @info: Updated with maximum supported deep color bpc and color format
3431 * if deep color supported.
3432 *
3433 * Parse the CEA extension according to CEA-861-B.
3434 * Return true if HDMI deep color supported, false if not or unknown.
3435 */
3436static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
3437 struct drm_display_info *info,
3438 struct drm_connector *connector)
3439{
3440 u8 *edid_ext, *hdmi;
3441 int i;
3442 int start_offset, end_offset;
3443 unsigned int dc_bpc = 0;
3444
3445 edid_ext = drm_find_cea_extension(edid);
3446 if (!edid_ext)
3447 return false;
3448
3449 if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
3450 return false;
3451
3452 /*
3453 * Because HDMI identifier is in Vendor Specific Block,
3454 * search it from all data blocks of CEA extension.
3455 */
3456 for_each_cea_db(edid_ext, i, start_offset, end_offset) {
3457 if (cea_db_is_hdmi_vsdb(&edid_ext[i])) {
3458 /* HDMI supports at least 8 bpc */
3459 info->bpc = 8;
3460
3461 hdmi = &edid_ext[i];
3462 if (cea_db_payload_len(hdmi) < 6)
3463 return false;
3464
3465 if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
3466 dc_bpc = 10;
3467 DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
3468 drm_get_connector_name(connector));
3469 }
3470
3471 if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
3472 dc_bpc = 12;
3473 DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
3474 drm_get_connector_name(connector));
3475 }
3476
3477 if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
3478 dc_bpc = 16;
3479 DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
3480 drm_get_connector_name(connector));
3481 }
3482
3483 if (dc_bpc > 0) {
3484 DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
3485 drm_get_connector_name(connector), dc_bpc);
3486 info->bpc = dc_bpc;
3487
3488 /*
3489 * Deep color support mandates RGB444 support for all video
3490 * modes and forbids YCRCB422 support for all video modes per
3491 * HDMI 1.3 spec.
3492 */
3493 info->color_formats = DRM_COLOR_FORMAT_RGB444;
3494
3495 /* YCRCB444 is optional according to spec. */
3496 if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
3497 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
3498 DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
3499 drm_get_connector_name(connector));
3500 }
3501
3502 /*
3503 * Spec says that if any deep color mode is supported at all,
3504 * then deep color 36 bit must be supported.
3505 */
3506 if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
3507 DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
3508 drm_get_connector_name(connector));
3509 }
3510
3511 return true;
3512 }
3513 else {
3514 DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
3515 drm_get_connector_name(connector));
3516 }
3517 }
3518 }
3519
3520 return false;
3521}
3522
3523/**
3426 * drm_add_display_info - pull display info out if present 3524 * drm_add_display_info - pull display info out if present
3427 * @edid: EDID data 3525 * @edid: EDID data
3428 * @info: display info (attached to connector) 3526 * @info: display info (attached to connector)
3527 * @connector: connector whose edid is used to build display info
3429 * 3528 *
3430 * Grab any available display info and stuff it into the drm_display_info 3529 * Grab any available display info and stuff it into the drm_display_info
3431 * structure that's part of the connector. Useful for tracking bpp and 3530 * structure that's part of the connector. Useful for tracking bpp and
3432 * color spaces. 3531 * color spaces.
3433 */ 3532 */
3434static void drm_add_display_info(struct edid *edid, 3533static void drm_add_display_info(struct edid *edid,
3435 struct drm_display_info *info) 3534 struct drm_display_info *info,
3535 struct drm_connector *connector)
3436{ 3536{
3437 u8 *edid_ext; 3537 u8 *edid_ext;
3438 3538
@@ -3462,6 +3562,9 @@ static void drm_add_display_info(struct edid *edid,
3462 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; 3562 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
3463 } 3563 }
3464 3564
3565 /* HDMI deep color modes supported? Assign to info, if so */
3566 drm_assign_hdmi_deep_color_info(edid, info, connector);
3567
3465 /* Only defined for 1.4 with digital displays */ 3568 /* Only defined for 1.4 with digital displays */
3466 if (edid->revision < 4) 3569 if (edid->revision < 4)
3467 return; 3570 return;
@@ -3491,6 +3594,9 @@ static void drm_add_display_info(struct edid *edid,
3491 break; 3594 break;
3492 } 3595 }
3493 3596
3597 DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
3598 drm_get_connector_name(connector), info->bpc);
3599
3494 info->color_formats |= DRM_COLOR_FORMAT_RGB444; 3600 info->color_formats |= DRM_COLOR_FORMAT_RGB444;
3495 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) 3601 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
3496 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; 3602 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
@@ -3549,7 +3655,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
3549 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 3655 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
3550 edid_fixup_preferred(connector, quirks); 3656 edid_fixup_preferred(connector, quirks);
3551 3657
3552 drm_add_display_info(edid, &connector->display_info); 3658 drm_add_display_info(edid, &connector->display_info, connector);
3553 3659
3554 if (quirks & EDID_QUIRK_FORCE_8BPC) 3660 if (quirks & EDID_QUIRK_FORCE_8BPC)
3555 connector->display_info.bpc = 8; 3661 connector->display_info.bpc = 8;