drm: edid: Don't add inferred modes with higher resolution
When a monitor EDID doesn't give the preferred bit, driver assumes that the mode with the higest resolution and rate is the preferred mode. Meanwhile the recent changes for allowing more modes in the GFT/CVT ranges give actually more modes, and some modes may be over the native size. Thus such a mode would be picked up as the preferred mode although it's no native resolution. For avoiding such a problem, this patch limits the addition of inferred modes by checking not to be greater than other modes. Also, it checks the duplicated mode entry at the same time. Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
1ef5325b23
commit
7b668ebe2f
|
@ -1039,6 +1039,24 @@ mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool valid_inferred_mode(const struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_display_mode *m;
|
||||
bool ok = false;
|
||||
|
||||
list_for_each_entry(m, &connector->probed_modes, head) {
|
||||
if (mode->hdisplay == m->hdisplay &&
|
||||
mode->vdisplay == m->vdisplay &&
|
||||
drm_mode_vrefresh(mode) == drm_mode_vrefresh(m))
|
||||
return false; /* duplicated */
|
||||
if (mode->hdisplay <= m->hdisplay &&
|
||||
mode->vdisplay <= m->vdisplay)
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
||||
struct detailed_timing *timing)
|
||||
|
@ -1048,7 +1066,8 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
|||
struct drm_device *dev = connector->dev;
|
||||
|
||||
for (i = 0; i < drm_num_dmt_modes; i++) {
|
||||
if (mode_in_range(drm_dmt_modes + i, edid, timing)) {
|
||||
if (mode_in_range(drm_dmt_modes + i, edid, timing) &&
|
||||
valid_inferred_mode(connector, drm_dmt_modes + i)) {
|
||||
newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
|
||||
if (newmode) {
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
|
@ -1088,7 +1107,8 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
|||
return modes;
|
||||
|
||||
fixup_mode_1366x768(newmode);
|
||||
if (!mode_in_range(newmode, edid, timing)) {
|
||||
if (!mode_in_range(newmode, edid, timing) ||
|
||||
!valid_inferred_mode(connector, newmode)) {
|
||||
drm_mode_destroy(dev, newmode);
|
||||
continue;
|
||||
}
|
||||
|
@ -1116,7 +1136,8 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
|||
return modes;
|
||||
|
||||
fixup_mode_1366x768(newmode);
|
||||
if (!mode_in_range(newmode, edid, timing)) {
|
||||
if (!mode_in_range(newmode, edid, timing) ||
|
||||
!valid_inferred_mode(connector, newmode)) {
|
||||
drm_mode_destroy(dev, newmode);
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue