Skip to content

Commit c7943bb

Browse files
committed
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 Cc: [email protected] Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6519 References: https://gitlab.freedesktop.org/drm/intel/-/issues/6484 Reviewed-by: Jani Nikula <[email protected]> Signed-off-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Reviewed-by: Manasi Navare <[email protected]>
1 parent a3f7c10 commit c7943bb

File tree

4 files changed

+27
-10
lines changed

4 files changed

+27
-10
lines changed

drivers/gpu/drm/drm_debugfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ static int vrr_range_show(struct seq_file *m, void *data)
377377
if (connector->status != connector_status_connected)
378378
return -ENODEV;
379379

380-
seq_printf(m, "Min: %u\n", (u8)connector->display_info.monitor_range.min_vfreq);
381-
seq_printf(m, "Max: %u\n", (u8)connector->display_info.monitor_range.max_vfreq);
380+
seq_printf(m, "Min: %u\n", connector->display_info.monitor_range.min_vfreq);
381+
seq_printf(m, "Max: %u\n", connector->display_info.monitor_range.max_vfreq);
382382

383383
return 0;
384384
}

drivers/gpu/drm/drm_edid.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5971,12 +5971,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
59715971
}
59725972

59735973
static
5974-
void get_monitor_range(const struct detailed_timing *timing,
5975-
void *info_monitor_range)
5974+
void get_monitor_range(const struct detailed_timing *timing, void *c)
59765975
{
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;
59785979
const struct detailed_non_pixel *data = &timing->data.other_data;
59795980
const struct detailed_data_monitor_range *range = &data->data.range;
5981+
const struct edid *edid = closure->drm_edid->edid;
59805982

59815983
if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE))
59825984
return;
@@ -5992,18 +5994,28 @@ void get_monitor_range(const struct detailed_timing *timing,
59925994

59935995
monitor_range->min_vfreq = range->min_vfreq;
59945996
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+
}
59956004
}
59966005

59976006
static void drm_get_monitor_range(struct drm_connector *connector,
59986007
const struct drm_edid *drm_edid)
59996008
{
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+
};
60016014

60026015
if (!version_greater(drm_edid, 1, 1))
60036016
return;
60046017

6005-
drm_for_each_detailed_block(drm_edid, get_monitor_range,
6006-
&info->monitor_range);
6018+
drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
60076019

60086020
DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
60096021
info->monitor_range.min_vfreq,

include/drm/drm_connector.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,8 @@ enum drm_panel_orientation {
319319
* EDID's detailed monitor range
320320
*/
321321
struct drm_monitor_range_info {
322-
u8 min_vfreq;
323-
u8 max_vfreq;
322+
u16 min_vfreq;
323+
u16 max_vfreq;
324324
};
325325

326326
/**

include/drm/drm_edid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ struct detailed_data_string {
9292
u8 str[13];
9393
} __attribute__((packed));
9494

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+
95100
#define DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG 0x00
96101
#define DRM_EDID_RANGE_LIMITS_ONLY_FLAG 0x01
97102
#define DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG 0x02

0 commit comments

Comments
 (0)