aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5dfe14763871..524eace3d460 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3398,6 +3398,7 @@ static int
3398do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len, 3398do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
3399 const u8 *video_db, u8 video_len) 3399 const u8 *video_db, u8 video_len)
3400{ 3400{
3401 struct drm_display_info *info = &connector->display_info;
3401 int modes = 0, offset = 0, i, multi_present = 0, multi_len; 3402 int modes = 0, offset = 0, i, multi_present = 0, multi_len;
3402 u8 vic_len, hdmi_3d_len = 0; 3403 u8 vic_len, hdmi_3d_len = 0;
3403 u16 mask; 3404 u16 mask;
@@ -3525,6 +3526,8 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
3525 } 3526 }
3526 3527
3527out: 3528out:
3529 if (modes > 0)
3530 info->has_hdmi_infoframe = true;
3528 return modes; 3531 return modes;
3529} 3532}
3530 3533
@@ -3761,8 +3764,8 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
3761{ 3764{
3762 u8 len = cea_db_payload_len(db); 3765 u8 len = cea_db_payload_len(db);
3763 3766
3764 if (len >= 6) 3767 if (len >= 6 && (db[6] & (1 << 7)))
3765 connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */ 3768 connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_SUPPORTS_AI;
3766 if (len >= 8) { 3769 if (len >= 8) {
3767 connector->latency_present[0] = db[8] >> 7; 3770 connector->latency_present[0] = db[8] >> 7;
3768 connector->latency_present[1] = (db[8] >> 6) & 1; 3771 connector->latency_present[1] = (db[8] >> 6) & 1;
@@ -3834,16 +3837,27 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
3834} 3837}
3835EXPORT_SYMBOL(drm_edid_get_monitor_name); 3838EXPORT_SYMBOL(drm_edid_get_monitor_name);
3836 3839
3837/** 3840static void clear_eld(struct drm_connector *connector)
3841{
3842 memset(connector->eld, 0, sizeof(connector->eld));
3843
3844 connector->latency_present[0] = false;
3845 connector->latency_present[1] = false;
3846 connector->video_latency[0] = 0;
3847 connector->audio_latency[0] = 0;
3848 connector->video_latency[1] = 0;
3849 connector->audio_latency[1] = 0;
3850}
3851
3852/*
3838 * drm_edid_to_eld - build ELD from EDID 3853 * drm_edid_to_eld - build ELD from EDID
3839 * @connector: connector corresponding to the HDMI/DP sink 3854 * @connector: connector corresponding to the HDMI/DP sink
3840 * @edid: EDID to parse 3855 * @edid: EDID to parse
3841 * 3856 *
3842 * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The 3857 * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
3843 * Conn_Type, HDCP and Port_ID ELD fields are left for the graphics driver to 3858 * HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
3844 * fill in.
3845 */ 3859 */
3846void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) 3860static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3847{ 3861{
3848 uint8_t *eld = connector->eld; 3862 uint8_t *eld = connector->eld;
3849 u8 *cea; 3863 u8 *cea;
@@ -3852,14 +3866,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3852 int mnl; 3866 int mnl;
3853 int dbl; 3867 int dbl;
3854 3868
3855 memset(eld, 0, sizeof(connector->eld)); 3869 clear_eld(connector);
3856
3857 connector->latency_present[0] = false;
3858 connector->latency_present[1] = false;
3859 connector->video_latency[0] = 0;
3860 connector->audio_latency[0] = 0;
3861 connector->video_latency[1] = 0;
3862 connector->audio_latency[1] = 0;
3863 3870
3864 if (!edid) 3871 if (!edid)
3865 return; 3872 return;
@@ -3870,17 +3877,18 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3870 return; 3877 return;
3871 } 3878 }
3872 3879
3873 mnl = get_monitor_name(edid, eld + 20); 3880 mnl = get_monitor_name(edid, &eld[DRM_ELD_MONITOR_NAME_STRING]);
3881 DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
3874 3882
3875 eld[4] = (cea[1] << 5) | mnl; 3883 eld[DRM_ELD_CEA_EDID_VER_MNL] = cea[1] << DRM_ELD_CEA_EDID_VER_SHIFT;
3876 DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20); 3884 eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
3877 3885
3878 eld[0] = 2 << 3; /* ELD version: 2 */ 3886 eld[DRM_ELD_VER] = DRM_ELD_VER_CEA861D;
3879 3887
3880 eld[16] = edid->mfg_id[0]; 3888 eld[DRM_ELD_MANUFACTURER_NAME0] = edid->mfg_id[0];
3881 eld[17] = edid->mfg_id[1]; 3889 eld[DRM_ELD_MANUFACTURER_NAME1] = edid->mfg_id[1];
3882 eld[18] = edid->prod_code[0]; 3890 eld[DRM_ELD_PRODUCT_CODE0] = edid->prod_code[0];
3883 eld[19] = edid->prod_code[1]; 3891 eld[DRM_ELD_PRODUCT_CODE1] = edid->prod_code[1];
3884 3892
3885 if (cea_revision(cea) >= 3) { 3893 if (cea_revision(cea) >= 3) {
3886 int i, start, end; 3894 int i, start, end;
@@ -3901,14 +3909,14 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3901 /* Audio Data Block, contains SADs */ 3909 /* Audio Data Block, contains SADs */
3902 sad_count = min(dbl / 3, 15 - total_sad_count); 3910 sad_count = min(dbl / 3, 15 - total_sad_count);
3903 if (sad_count >= 1) 3911 if (sad_count >= 1)
3904 memcpy(eld + 20 + mnl + total_sad_count * 3, 3912 memcpy(&eld[DRM_ELD_CEA_SAD(mnl, total_sad_count)],
3905 &db[1], sad_count * 3); 3913 &db[1], sad_count * 3);
3906 total_sad_count += sad_count; 3914 total_sad_count += sad_count;
3907 break; 3915 break;
3908 case SPEAKER_BLOCK: 3916 case SPEAKER_BLOCK:
3909 /* Speaker Allocation Data Block */ 3917 /* Speaker Allocation Data Block */
3910 if (dbl >= 1) 3918 if (dbl >= 1)
3911 eld[7] = db[1]; 3919 eld[DRM_ELD_SPEAKER] = db[1];
3912 break; 3920 break;
3913 case VENDOR_BLOCK: 3921 case VENDOR_BLOCK:
3914 /* HDMI Vendor-Specific Data Block */ 3922 /* HDMI Vendor-Specific Data Block */
@@ -3920,7 +3928,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3920 } 3928 }
3921 } 3929 }
3922 } 3930 }
3923 eld[5] |= total_sad_count << 4; 3931 eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= total_sad_count << DRM_ELD_SAD_COUNT_SHIFT;
3932
3933 if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
3934 connector->connector_type == DRM_MODE_CONNECTOR_eDP)
3935 eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_DP;
3936 else
3937 eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= DRM_ELD_CONN_TYPE_HDMI;
3924 3938
3925 eld[DRM_ELD_BASELINE_ELD_LEN] = 3939 eld[DRM_ELD_BASELINE_ELD_LEN] =
3926 DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4); 3940 DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
@@ -3928,7 +3942,6 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
3928 DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", 3942 DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
3929 drm_eld_size(eld), total_sad_count); 3943 drm_eld_size(eld), total_sad_count);
3930} 3944}
3931EXPORT_SYMBOL(drm_edid_to_eld);
3932 3945
3933/** 3946/**
3934 * drm_edid_to_sad - extracts SADs from EDID 3947 * drm_edid_to_sad - extracts SADs from EDID
@@ -4238,6 +4251,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
4238 struct drm_display_info *display = &connector->display_info; 4251 struct drm_display_info *display = &connector->display_info;
4239 struct drm_hdmi_info *hdmi = &display->hdmi; 4252 struct drm_hdmi_info *hdmi = &display->hdmi;
4240 4253
4254 display->has_hdmi_infoframe = true;
4255
4241 if (hf_vsdb[6] & 0x80) { 4256 if (hf_vsdb[6] & 0x80) {
4242 hdmi->scdc.supported = true; 4257 hdmi->scdc.supported = true;
4243 if (hf_vsdb[6] & 0x40) 4258 if (hf_vsdb[6] & 0x40)
@@ -4411,6 +4426,7 @@ static void drm_add_display_info(struct drm_connector *connector,
4411 info->cea_rev = 0; 4426 info->cea_rev = 0;
4412 info->max_tmds_clock = 0; 4427 info->max_tmds_clock = 0;
4413 info->dvi_dual = false; 4428 info->dvi_dual = false;
4429 info->has_hdmi_infoframe = false;
4414 4430
4415 info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); 4431 info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
4416 4432
@@ -4608,8 +4624,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
4608 * @edid: EDID data 4624 * @edid: EDID data
4609 * 4625 *
4610 * Add the specified modes to the connector's mode list. Also fills out the 4626 * Add the specified modes to the connector's mode list. Also fills out the
4611 * &drm_display_info structure in @connector with any information which can be 4627 * &drm_display_info structure and ELD in @connector with any information which
4612 * derived from the edid. 4628 * can be derived from the edid.
4613 * 4629 *
4614 * Return: The number of modes added or 0 if we couldn't find any. 4630 * Return: The number of modes added or 0 if we couldn't find any.
4615 */ 4631 */
@@ -4619,9 +4635,11 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
4619 u32 quirks; 4635 u32 quirks;
4620 4636
4621 if (edid == NULL) { 4637 if (edid == NULL) {
4638 clear_eld(connector);
4622 return 0; 4639 return 0;
4623 } 4640 }
4624 if (!drm_edid_is_valid(edid)) { 4641 if (!drm_edid_is_valid(edid)) {
4642 clear_eld(connector);
4625 dev_warn(connector->dev->dev, "%s: EDID invalid.\n", 4643 dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
4626 connector->name); 4644 connector->name);
4627 return 0; 4645 return 0;
@@ -4629,6 +4647,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
4629 4647
4630 quirks = edid_get_quirks(edid); 4648 quirks = edid_get_quirks(edid);
4631 4649
4650 drm_edid_to_eld(connector, edid);
4651
4632 /* 4652 /*
4633 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. 4653 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
4634 * To avoid multiple parsing of same block, lets parse that map 4654 * To avoid multiple parsing of same block, lets parse that map
@@ -4904,6 +4924,7 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
4904 * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with 4924 * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
4905 * data from a DRM display mode 4925 * data from a DRM display mode
4906 * @frame: HDMI vendor infoframe 4926 * @frame: HDMI vendor infoframe
4927 * @connector: the connector
4907 * @mode: DRM display mode 4928 * @mode: DRM display mode
4908 * 4929 *
4909 * Note that there's is a need to send HDMI vendor infoframes only when using a 4930 * Note that there's is a need to send HDMI vendor infoframes only when using a
@@ -4914,8 +4935,15 @@ s3d_structure_from_display_mode(const struct drm_display_mode *mode)
4914 */ 4935 */
4915int 4936int
4916drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, 4937drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
4938 struct drm_connector *connector,
4917 const struct drm_display_mode *mode) 4939 const struct drm_display_mode *mode)
4918{ 4940{
4941 /*
4942 * FIXME: sil-sii8620 doesn't have a connector around when
4943 * we need one, so we have to be prepared for a NULL connector.
4944 */
4945 bool has_hdmi_infoframe = connector ?
4946 connector->display_info.has_hdmi_infoframe : false;
4919 int err; 4947 int err;
4920 u32 s3d_flags; 4948 u32 s3d_flags;
4921 u8 vic; 4949 u8 vic;
@@ -4923,11 +4951,21 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
4923 if (!frame || !mode) 4951 if (!frame || !mode)
4924 return -EINVAL; 4952 return -EINVAL;
4925 4953
4954 if (!has_hdmi_infoframe)
4955 return -EINVAL;
4956
4926 vic = drm_match_hdmi_mode(mode); 4957 vic = drm_match_hdmi_mode(mode);
4927 s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK; 4958 s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
4928 4959
4929 if (!vic && !s3d_flags) 4960 /*
4930 return -EINVAL; 4961 * Even if it's not absolutely necessary to send the infoframe
4962 * (ie.vic==0 and s3d_struct==0) we will still send it if we
4963 * know that the sink can handle it. This is based on a
4964 * suggestion in HDMI 2.0 Appendix F. Apparently some sinks
4965 * have trouble realizing that they shuld switch from 3D to 2D
4966 * mode if the source simply stops sending the infoframe when
4967 * it wants to switch from 3D to 2D.
4968 */
4931 4969
4932 if (vic && s3d_flags) 4970 if (vic && s3d_flags)
4933 return -EINVAL; 4971 return -EINVAL;
@@ -4936,10 +4974,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
4936 if (err < 0) 4974 if (err < 0)
4937 return err; 4975 return err;
4938 4976
4939 if (vic) 4977 frame->vic = vic;
4940 frame->vic = vic; 4978 frame->s3d_struct = s3d_structure_from_display_mode(mode);
4941 else
4942 frame->s3d_struct = s3d_structure_from_display_mode(mode);
4943 4979
4944 return 0; 4980 return 0;
4945} 4981}