summaryrefslogtreecommitdiffstats
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.c28
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);
OpenPOWER on IntegriCloud