aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-12-03 17:44:38 -0500
committerDave Airlie <airlied@redhat.com>2009-12-03 17:53:32 -0500
commit07a5e6324abacad56a8e7bcb44dd404e84f75f57 (patch)
tree7284321ed859e29ecacb4ce1a8a6a58a4abb1942 /drivers/gpu/drm/drm_edid.c
parent7ac96a9cb4982140e206bf3b58236efb2498ab3f (diff)
drm/edid: Add DMT modes to the pool if the monitor is GTF-capable
See also: http://bugzilla.redhat.com/539785 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.c69
1 files changed, 65 insertions, 4 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 999571ab0b69..cc8e69682714 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -491,16 +491,17 @@ static struct drm_display_mode drm_dmt_modes[] = {
491 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, 491 3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
492 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, 492 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
493}; 493};
494static const int drm_num_dmt_modes =
495 sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
494 496
495static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, 497static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
496 int hsize, int vsize, int fresh) 498 int hsize, int vsize, int fresh)
497{ 499{
498 int i, count; 500 int i;
499 struct drm_display_mode *ptr, *mode; 501 struct drm_display_mode *ptr, *mode;
500 502
501 count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
502 mode = NULL; 503 mode = NULL;
503 for (i = 0; i < count; i++) { 504 for (i = 0; i < drm_num_dmt_modes; i++) {
504 ptr = &drm_dmt_modes[i]; 505 ptr = &drm_dmt_modes[i];
505 if (hsize == ptr->hdisplay && 506 if (hsize == ptr->hdisplay &&
506 vsize == ptr->vdisplay && 507 vsize == ptr->vdisplay &&
@@ -838,6 +839,64 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
838 return modes; 839 return modes;
839} 840}
840 841
842/*
843 * XXX fix this for:
844 * - GTF secondary curve formula
845 * - EDID 1.4 range offsets
846 * - CVT extended bits
847 */
848static bool
849mode_in_range(struct drm_display_mode *mode, struct detailed_timing *timing)
850{
851 struct detailed_data_monitor_range *range;
852 int hsync, vrefresh;
853
854 range = &timing->data.other_data.data.range;
855
856 hsync = drm_mode_hsync(mode);
857 vrefresh = drm_mode_vrefresh(mode);
858
859 if (hsync < range->min_hfreq_khz || hsync > range->max_hfreq_khz)
860 return false;
861
862 if (vrefresh < range->min_vfreq || vrefresh > range->max_vfreq)
863 return false;
864
865 if (range->pixel_clock_mhz && range->pixel_clock_mhz != 0xff) {
866 /* be forgiving since it's in units of 10MHz */
867 int max_clock = range->pixel_clock_mhz * 10 + 9;
868 max_clock *= 1000;
869 if (mode->clock > max_clock)
870 return false;
871 }
872
873 return true;
874}
875
876/*
877 * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will
878 * need to account for them.
879 */
880static int drm_gtf_modes_for_range(struct drm_connector *connector,
881 struct detailed_timing *timing)
882{
883 int i, modes = 0;
884 struct drm_display_mode *newmode;
885 struct drm_device *dev = connector->dev;
886
887 for (i = 0; i < drm_num_dmt_modes; i++) {
888 if (mode_in_range(drm_dmt_modes + i, timing)) {
889 newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]);
890 if (newmode) {
891 drm_mode_probed_add(connector, newmode);
892 modes++;
893 }
894 }
895 }
896
897 return modes;
898}
899
841static int add_detailed_modes(struct drm_connector *connector, 900static int add_detailed_modes(struct drm_connector *connector,
842 struct detailed_timing *timing, 901 struct detailed_timing *timing,
843 struct edid *edid, u32 quirks, int preferred) 902 struct edid *edid, u32 quirks, int preferred)
@@ -845,6 +904,7 @@ static int add_detailed_modes(struct drm_connector *connector,
845 int i, modes = 0; 904 int i, modes = 0;
846 struct detailed_non_pixel *data = &timing->data.other_data; 905 struct detailed_non_pixel *data = &timing->data.other_data;
847 int timing_level = standard_timing_level(edid); 906 int timing_level = standard_timing_level(edid);
907 int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
848 struct drm_display_mode *newmode; 908 struct drm_display_mode *newmode;
849 struct drm_device *dev = connector->dev; 909 struct drm_device *dev = connector->dev;
850 910
@@ -863,7 +923,8 @@ static int add_detailed_modes(struct drm_connector *connector,
863 /* other timing types */ 923 /* other timing types */
864 switch (data->type) { 924 switch (data->type) {
865 case EDID_DETAIL_MONITOR_RANGE: 925 case EDID_DETAIL_MONITOR_RANGE:
866 /* Get monitor range data */ 926 if (gtf)
927 modes += drm_gtf_modes_for_range(connector, timing);
867 break; 928 break;
868 case EDID_DETAIL_STD_MODES: 929 case EDID_DETAIL_STD_MODES:
869 /* Six modes per detailed section */ 930 /* Six modes per detailed section */