diff options
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d7214389c2d6..6e999bd03935 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -733,12 +733,12 @@ bad_std_timing(u8 a, u8 b) * Take the standard timing params (in this case width, aspect, and refresh) * and convert them into a real mode using CVT/GTF/DMT. */ -struct drm_display_mode *drm_mode_std(struct drm_device *dev, - struct std_timing *t, - int revision, - int timing_level) +static struct drm_display_mode * +drm_mode_std(struct drm_connector *connector, struct std_timing *t, + int revision, int timing_level) { - struct drm_display_mode *mode; + struct drm_device *dev = connector->dev; + struct drm_display_mode *m, *mode = NULL; int hsize, vsize; int vrefresh_rate; unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) @@ -774,6 +774,17 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, vsize = 768; } + /* + * If this connector already has a mode for this size and refresh + * rate (because it came from detailed or CVT info), use that + * instead. This way we don't have to guess at interlace or + * reduced blanking. + */ + list_for_each_entry(m, &connector->modes, head) + if (m->hdisplay == hsize && m->vdisplay == vsize && + drm_mode_vrefresh(m) == vrefresh_rate) + return NULL; + /* HDTV hack, part 2 */ if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, @@ -784,7 +795,6 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, return mode; } - mode = NULL; /* check whether it can be found in default mode table */ mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate); if (mode) @@ -1055,17 +1065,15 @@ static int standard_timing_level(struct edid *edid) */ static int add_standard_modes(struct drm_connector *connector, struct edid *edid) { - struct drm_device *dev = connector->dev; int i, modes = 0; int timing_level; timing_level = standard_timing_level(edid); for (i = 0; i < EDID_STD_TIMINGS; i++) { - struct std_timing *t = &edid->standard_timings[i]; struct drm_display_mode *newmode; - newmode = drm_mode_std(dev, &edid->standard_timings[i], + newmode = drm_mode_std(connector, &edid->standard_timings[i], edid->revision, timing_level); if (newmode) { drm_mode_probed_add(connector, newmode); @@ -1362,7 +1370,7 @@ static int add_detailed_modes(struct drm_connector *connector, struct drm_display_mode *newmode; std = &data->data.timings[i]; - newmode = drm_mode_std(dev, std, edid->revision, + newmode = drm_mode_std(connector, std, edid->revision, timing_level); if (newmode) { drm_mode_probed_add(connector, newmode); |