aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-03-29 17:43:29 -0400
committerDave Airlie <airlied@redhat.com>2010-04-05 20:40:24 -0400
commit7ca6adb37918db21d076a489c6c39490fb34264e (patch)
tree936aecb1509343a47a05b567b584c2b039c6a35b /drivers/gpu/drm/drm_edid.c
parenta0910c8e37c3bede089e9f9dee63a7eaf9601a43 (diff)
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>
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)
733 * Take the standard timing params (in this case width, aspect, and refresh) 733 * Take the standard timing params (in this case width, aspect, and refresh)
734 * and convert them into a real mode using CVT/GTF/DMT. 734 * and convert them into a real mode using CVT/GTF/DMT.
735 */ 735 */
736struct drm_display_mode *drm_mode_std(struct drm_device *dev, 736static struct drm_display_mode *
737 struct std_timing *t, 737drm_mode_std(struct drm_connector *connector, struct std_timing *t,
738 int revision, 738 int revision, int timing_level)
739 int timing_level)
740{ 739{
741 struct drm_display_mode *mode; 740 struct drm_device *dev = connector->dev;
741 struct drm_display_mode *m, *mode = NULL;
742 int hsize, vsize; 742 int hsize, vsize;
743 int vrefresh_rate; 743 int vrefresh_rate;
744 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) 744 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,
774 vsize = 768; 774 vsize = 768;
775 } 775 }
776 776
777 /*
778 * If this connector already has a mode for this size and refresh
779 * rate (because it came from detailed or CVT info), use that
780 * instead. This way we don't have to guess at interlace or
781 * reduced blanking.
782 */
783 list_for_each_entry(m, &connector->modes, head)
784 if (m->hdisplay == hsize && m->vdisplay == vsize &&
785 drm_mode_vrefresh(m) == vrefresh_rate)
786 return NULL;
787
777 /* HDTV hack, part 2 */ 788 /* HDTV hack, part 2 */
778 if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { 789 if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) {
779 mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, 790 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,
784 return mode; 795 return mode;
785 } 796 }
786 797
787 mode = NULL;
788 /* check whether it can be found in default mode table */ 798 /* check whether it can be found in default mode table */
789 mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate); 799 mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate);
790 if (mode) 800 if (mode)
@@ -1055,17 +1065,15 @@ static int standard_timing_level(struct edid *edid)
1055 */ 1065 */
1056static int add_standard_modes(struct drm_connector *connector, struct edid *edid) 1066static int add_standard_modes(struct drm_connector *connector, struct edid *edid)
1057{ 1067{
1058 struct drm_device *dev = connector->dev;
1059 int i, modes = 0; 1068 int i, modes = 0;
1060 int timing_level; 1069 int timing_level;
1061 1070
1062 timing_level = standard_timing_level(edid); 1071 timing_level = standard_timing_level(edid);
1063 1072
1064 for (i = 0; i < EDID_STD_TIMINGS; i++) { 1073 for (i = 0; i < EDID_STD_TIMINGS; i++) {
1065 struct std_timing *t = &edid->standard_timings[i];
1066 struct drm_display_mode *newmode; 1074 struct drm_display_mode *newmode;
1067 1075
1068 newmode = drm_mode_std(dev, &edid->standard_timings[i], 1076 newmode = drm_mode_std(connector, &edid->standard_timings[i],
1069 edid->revision, timing_level); 1077 edid->revision, timing_level);
1070 if (newmode) { 1078 if (newmode) {
1071 drm_mode_probed_add(connector, newmode); 1079 drm_mode_probed_add(connector, newmode);
@@ -1362,7 +1370,7 @@ static int add_detailed_modes(struct drm_connector *connector,
1362 struct drm_display_mode *newmode; 1370 struct drm_display_mode *newmode;
1363 1371
1364 std = &data->data.timings[i]; 1372 std = &data->data.timings[i];
1365 newmode = drm_mode_std(dev, std, edid->revision, 1373 newmode = drm_mode_std(connector, std, edid->revision,
1366 timing_level); 1374 timing_level);
1367 if (newmode) { 1375 if (newmode) {
1368 drm_mode_probed_add(connector, newmode); 1376 drm_mode_probed_add(connector, newmode);