summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-03-29 21:43:29 +0000
committerDave Airlie <airlied@redhat.com>2010-04-06 10:40:24 +1000
commit7ca6adb37918db21d076a489c6c39490fb34264e (patch)
tree936aecb1509343a47a05b567b584c2b039c6a35b
parenta0910c8e37c3bede089e9f9dee63a7eaf9601a43 (diff)
downloadblackbird-op-linux-7ca6adb37918db21d076a489c6c39490fb34264e.tar.gz
blackbird-op-linux-7ca6adb37918db21d076a489c6c39490fb34264e.zip
drm/edid: Strengthen the algorithm for standard mode codes
If you have 1920x1200 in both detailed (probably RB) and standard variants, you probably only want the RB version. But we have no way of guessing that from standard mode parse. So, if a mode already exists for a given w/h/r, skip adding it. Signed-off-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-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