@@ -3422,17 +3422,117 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
3422
3422
}
3423
3423
EXPORT_SYMBOL (drm_rgb_quant_range_selectable );
3424
3424
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
+ */
3436
+ static 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
+
3425
3523
/**
3426
3524
* drm_add_display_info - pull display info out if present
3427
3525
* @edid: EDID data
3428
3526
* @info: display info (attached to connector)
3527
+ * @connector: connector whose edid is used to build display info
3429
3528
*
3430
3529
* Grab any available display info and stuff it into the drm_display_info
3431
3530
* structure that's part of the connector. Useful for tracking bpp and
3432
3531
* color spaces.
3433
3532
*/
3434
3533
static 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
3537
u8 * edid_ext ;
3438
3538
@@ -3462,6 +3562,9 @@ static void drm_add_display_info(struct edid *edid,
3462
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
3568
/* Only defined for 1.4 with digital displays */
3466
3569
if (edid -> revision < 4 )
3467
3570
return ;
@@ -3491,6 +3594,9 @@ static void drm_add_display_info(struct edid *edid,
3491
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
3600
info -> color_formats |= DRM_COLOR_FORMAT_RGB444 ;
3495
3601
if (edid -> features & DRM_EDID_FEATURE_RGB_YCRCB444 )
3496
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
3655
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75 ))
3550
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
3660
if (quirks & EDID_QUIRK_FORCE_8BPC )
3555
3661
connector -> display_info .bpc = 8 ;
0 commit comments