History

drm/edid: Handle EDID 1.4 range descriptor h/vfreq offsets

EDID 1.4 introduced some extra flags in the range descriptor to support min/max h/vfreq >= 255. Consult them to correctly parse the vfreq limits. Note that some combinations of the flags are documented as "reserved" (as are some other values in the descriptor) but explicitly checking for those doesn't seem particularly worthwile since we end up with bogus results whether we decode them or not. v2: Increase the storage to u16 to make it work (Jani) Note the "reserved" values situation (Jani) v3: Document the EDID version number in the defines Drop some bogus (u8) casts

Ville Syrjälä committed 4 years ago

Commit c7943bb1 parent a3f7c104 files · +27 −10Browse files

Unified · Split

4 files
  1. drivers/gpu/drm/drm_debugfs.c +2 −2
  2. drivers/gpu/drm/drm_edid.c +18 −6
  3. include/drm/drm_connector.h +2 −2
  4. include/drm/drm_edid.h +5 −0
drivers/gpu/drm/drm_debugfs.c+2−2
@@ -377,8 +377,8 @@ static int vrr_range_show(struct seq_file *m, void *data) · 376 unmodified lines
377 if (connector->status != connector_status_connected)377 if (connector->status != connector_status_connected)
378 return -ENODEV;378 return -ENODEV;
379 379
380 seq_printf(m, "Min: %u\n", (u8)connector->display_info.monitor_range.min_vfreq);380 seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq);
381 seq_printf(m, "Max: %u\n", (u8)connector->display_info.monitor_range.max_vfreq);381 seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq);
382 382
383 return 0;383 return 0;
384}384}
drivers/gpu/drm/drm_edid.c+18−6
@@ -5971,12 +5971,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector, · 5970 unmodified lines
5971}5971}
5972 5972
5973static5973static
5974void get_monitor_range(const struct detailed_timing *timing,5974void get_monitor_range(const struct detailed_timing *timing, void *c)
5975 void *info_monitor_range)
5976{5975{
5977 struct drm_monitor_range_info *monitor_range = info_monitor_range;5976 struct detailed_mode_closure *closure = c;
5977 struct drm_display_info *info = &closure->connector->display_info;
5978 struct drm_monitor_range_info *monitor_range = &info->monitor_range;
5978 const struct detailed_non_pixel *data = &timing->data.other_data;5979 const struct detailed_non_pixel *data = &timing->data.other_data;
5979 const struct detailed_data_monitor_range *range = &data->data.range;5980 const struct detailed_data_monitor_range *range = &data->data.range;
5981 const struct edid *edid = closure->drm_edid->edid;
5980 5982
5981 if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))5983 if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
5982 return;5984 return;
@@ -5992,18 +5994,28 @@ void get_monitor_range(const struct detailed_timing *timing, · 9 unmodified lines
5992 5994
5993 monitor_range->min_vfreq = range->min_vfreq;5995 monitor_range->min_vfreq = range->min_vfreq;
5994 monitor_range->max_vfreq = range->max_vfreq;5996 monitor_range->max_vfreq = range->max_vfreq;
5997
5998 if (edid->revision >= 4) {
5999 if (data->pad2 & DRM_EDID_RANGE_OFFSET_MIN_VFREQ)
6000 monitor_range->min_vfreq += 255;
6001 if (data->pad2 & DRM_EDID_RANGE_OFFSET_MAX_VFREQ)
6002 monitor_range->max_vfreq += 255;
6003 }
5995}6004}
5996 6005
5997static void drm_get_monitor_range(struct drm_connector *connector,6006static void drm_get_monitor_range(struct drm_connector *connector,
5998 const struct drm_edid *drm_edid)6007 const struct drm_edid *drm_edid)
5999{6008{
6000 struct drm_display_info *info = &connector->display_info;6009 const struct drm_display_info *info = &connector->display_info;
6010 struct detailed_mode_closure closure = {
6011 .connector = connector,
6012 .drm_edid = drm_edid,
6013 };
6001 6014
6002 if (!version_greater(drm_edid, 1, 1))6015 if (!version_greater(drm_edid, 1, 1))
6003 return;6016 return;
6004 6017
6005 drm_for_each_detailed_block(drm_edid, get_monitor_range,6018 drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
6006 &info->monitor_range);
6007 6019
6008 DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",6020 DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
6009 info->monitor_range.min_vfreq,6021 info->monitor_range.min_vfreq,
include/drm/drm_connector.h+2−2
@@ -319,8 +319,8 @@ enum drm_panel_orientation { · 318 unmodified lines
319 * EDID's detailed monitor range319 * EDID's detailed monitor range
320 */320 */
321struct drm_monitor_range_info {321struct drm_monitor_range_info {
322 u8 min_vfreq;322 u16 min_vfreq;
323 u8 max_vfreq;323 u16 max_vfreq;
324};324};
325 325
326/**326/**
include/drm/drm_edid.h+5−0
@@ -92,6 +92,11 @@ struct detailed_data_string { · 91 unmodified lines
92 u8 str[13];92 u8 str[13];
93} __attribute__((packed));93} __attribute__((packed));
94 94
95#define DRM_EDID_RANGE_OFFSET_MIN_VFREQ (1 << 0) /* 1.4 */
96#define DRM_EDID_RANGE_OFFSET_MAX_VFREQ (1 << 1) /* 1.4 */
97#define DRM_EDID_RANGE_OFFSET_MIN_HFREQ (1 << 2) /* 1.4 */
98#define DRM_EDID_RANGE_OFFSET_MAX_HFREQ (1 << 3) /* 1.4 */
99
95#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00100#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00
96#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01101#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01
97#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02102#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02