aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2016-09-28 09:51:39 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2016-10-04 02:23:11 -0400
commit1cea146a806ae1f34cb1b5e3206ff63a2bb90782 (patch)
tree5d21e1c8041692d7941edc393dd1f3d59a8cb8a3
parent1826750f5775fa17909d02755bc872dfcfc6685e (diff)
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: Ville Syrjälä <ville.syrjala@linux.intel.com> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/1475070703-6435-7-git-send-email-ville.syrjala@linux.intel.com
-rw-r--r--drivers/gpu/drm/drm_edid.c185
1 files changed, 88 insertions, 97 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index caa84a056779..ef8ae691f7aa 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3733,105 +3733,110 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
3733} 3733}
3734EXPORT_SYMBOL(drm_rgb_quant_range_selectable); 3734EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
3735 3735
3736/* 3736static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
3737 * Parse the CEA extension according to CEA-861-B. 3737 const u8 *hdmi)
3738 * Return true if HDMI deep color supported, false if not or unknown.
3739 */
3740static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
3741 struct drm_connector *connector)
3742{ 3738{
3743 struct drm_display_info *info = &connector->display_info; 3739 struct drm_display_info *info = &connector->display_info;
3744 u8 *edid_ext, *hdmi;
3745 int i;
3746 int start_offset, end_offset;
3747 unsigned int dc_bpc = 0; 3740 unsigned int dc_bpc = 0;
3748 3741
3749 edid_ext = drm_find_cea_extension(edid); 3742 /* HDMI supports at least 8 bpc */
3750 if (!edid_ext) 3743 info->bpc = 8;
3751 return false;
3752 3744
3753 if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) 3745 if (cea_db_payload_len(hdmi) < 6)
3754 return false; 3746 return;
3747
3748 if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
3749 dc_bpc = 10;
3750 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
3751 DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
3752 connector->name);
3753 }
3754
3755 if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
3756 dc_bpc = 12;
3757 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;
3758 DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
3759 connector->name);
3760 }
3761
3762 if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
3763 dc_bpc = 16;
3764 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;
3765 DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
3766 connector->name);
3767 }
3768
3769 if (dc_bpc == 0) {
3770 DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
3771 connector->name);
3772 return;
3773 }
3774
3775 DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
3776 connector->name, dc_bpc);
3777 info->bpc = dc_bpc;
3755 3778
3756 /* 3779 /*
3757 * Because HDMI identifier is in Vendor Specific Block, 3780 * Deep color support mandates RGB444 support for all video
3758 * search it from all data blocks of CEA extension. 3781 * modes and forbids YCRCB422 support for all video modes per
3782 * HDMI 1.3 spec.
3759 */ 3783 */
3760 for_each_cea_db(edid_ext, i, start_offset, end_offset) { 3784 info->color_formats = DRM_COLOR_FORMAT_RGB444;
3761 if (cea_db_is_hdmi_vsdb(&edid_ext[i])) {
3762 /* HDMI supports at least 8 bpc */
3763 info->bpc = 8;
3764
3765 hdmi = &edid_ext[i];
3766 if (cea_db_payload_len(hdmi) < 6)
3767 return false;
3768
3769 if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
3770 dc_bpc = 10;
3771 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
3772 DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
3773 connector->name);
3774 }
3775 3785
3776 if (hdmi[6] & DRM_EDID_HDMI_DC_36) { 3786 /* YCRCB444 is optional according to spec. */
3777 dc_bpc = 12; 3787 if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
3778 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36; 3788 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
3779 DRM_DEBUG("%s: HDMI sink does deep color 36.\n", 3789 DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
3780 connector->name); 3790 connector->name);
3781 } 3791 }
3782 3792
3783 if (hdmi[6] & DRM_EDID_HDMI_DC_48) { 3793 /*
3784 dc_bpc = 16; 3794 * Spec says that if any deep color mode is supported at all,
3785 info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48; 3795 * then deep color 36 bit must be supported.
3786 DRM_DEBUG("%s: HDMI sink does deep color 48.\n", 3796 */
3787 connector->name); 3797 if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
3788 } 3798 DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
3799 connector->name);
3800 }
3801}
3789 3802
3790 if (dc_bpc > 0) { 3803static void drm_parse_cea_ext(struct drm_connector *connector,
3791 DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n", 3804 struct edid *edid)
3792 connector->name, dc_bpc); 3805{
3793 info->bpc = dc_bpc; 3806 struct drm_display_info *info = &connector->display_info;
3794 3807 const u8 *edid_ext;
3795 /* 3808 int i, start, end;
3796 * Deep color support mandates RGB444 support for all video
3797 * modes and forbids YCRCB422 support for all video modes per
3798 * HDMI 1.3 spec.
3799 */
3800 info->color_formats = DRM_COLOR_FORMAT_RGB444;
3801
3802 /* YCRCB444 is optional according to spec. */
3803 if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
3804 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
3805 DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
3806 connector->name);
3807 }
3808 3809
3809 /* 3810 edid_ext = drm_find_cea_extension(edid);
3810 * Spec says that if any deep color mode is supported at all, 3811 if (!edid_ext)
3811 * then deep color 36 bit must be supported. 3812 return;
3812 */
3813 if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
3814 DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
3815 connector->name);
3816 }
3817 3813
3818 return true; 3814 info->cea_rev = edid_ext[1];
3819 }
3820 else {
3821 DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
3822 connector->name);
3823 }
3824 }
3825 }
3826 3815
3827 return false; 3816 /* The existence of a CEA block should imply RGB support */
3817 info->color_formats = DRM_COLOR_FORMAT_RGB444;
3818 if (edid_ext[3] & EDID_CEA_YCRCB444)
3819 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
3820 if (edid_ext[3] & EDID_CEA_YCRCB422)
3821 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
3822
3823 if (cea_db_offsets(edid_ext, &start, &end))
3824 return;
3825
3826 for_each_cea_db(edid_ext, i, start, end) {
3827 const u8 *db = &edid_ext[i];
3828
3829 if (!cea_db_is_hdmi_vsdb(db))
3830 continue;
3831
3832 drm_parse_hdmi_deep_color_info(connector, db);
3833 }
3828} 3834}
3829 3835
3830static void drm_add_display_info(struct edid *edid, 3836static void drm_add_display_info(struct drm_connector *connector,
3831 struct drm_connector *connector) 3837 struct edid *edid)
3832{ 3838{
3833 struct drm_display_info *info = &connector->display_info; 3839 struct drm_display_info *info = &connector->display_info;
3834 u8 *edid_ext;
3835 3840
3836 info->width_mm = edid->width_cm * 10; 3841 info->width_mm = edid->width_cm * 10;
3837 info->height_mm = edid->height_cm * 10; 3842 info->height_mm = edid->height_cm * 10;
@@ -3846,21 +3851,7 @@ static void drm_add_display_info(struct edid *edid,
3846 if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) 3851 if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
3847 return; 3852 return;
3848 3853
3849 /* Get data from CEA blocks if present */ 3854 drm_parse_cea_ext(connector, edid);
3850 edid_ext = drm_find_cea_extension(edid);
3851 if (edid_ext) {
3852 info->cea_rev = edid_ext[1];
3853
3854 /* The existence of a CEA block should imply RGB support */
3855 info->color_formats = DRM_COLOR_FORMAT_RGB444;
3856 if (edid_ext[3] & EDID_CEA_YCRCB444)
3857 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
3858 if (edid_ext[3] & EDID_CEA_YCRCB422)
3859 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
3860 }
3861
3862 /* HDMI deep color modes supported? Assign to info, if so */
3863 drm_assign_hdmi_deep_color_info(edid, connector);
3864 3855
3865 /* 3856 /*
3866 * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? 3857 * 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 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 4087 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
4097 edid_fixup_preferred(connector, quirks); 4088 edid_fixup_preferred(connector, quirks);
4098 4089
4099 drm_add_display_info(edid, connector); 4090 drm_add_display_info(connector, edid);
4100 4091
4101 if (quirks & EDID_QUIRK_FORCE_6BPC) 4092 if (quirks & EDID_QUIRK_FORCE_6BPC)
4102 connector->display_info.bpc = 6; 4093 connector->display_info.bpc = 6;