There are many bugs open on fd.o regarding missing modes that are supported on Windows and other closed source drivers. >From EDID spec we can (might?) infer modes using GTF and CVT when monitor allows it trough range limited flag... obviously limiting by the range. >From our code: * EDID spec says modes should be preferred in this order: * - preferred detailed mode * - other detailed modes from base block * - detailed modes from extension blocks * - CVT 3-byte code modes * - standard timing codes * - established timing codes * - modes inferred from GTF or CVT range information * * We get this pretty much right. Not actually so right... We were inferring just using GTF... not CVT or even GTF2. This patch not just add some common cvt modes but also allows some modes been inferred when using gtf2 as well. Cheers, Rodrigo. >From 4b7a88d0d812583d850ca691d1ac491355230d11 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> Date: Wed, 11 Apr 2012 15:36:31 -0300 Subject: [PATCH] drm/edid: Adding common CVT inferred modes when monitor allows range limited ones trough EDID. Signed-off-by: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> --- drivers/gpu/drm/drm_edid.c | 37 +++++++++++++- drivers/gpu/drm/drm_edid_modes.h | 101 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7ee7be1..3179572 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1020,17 +1020,50 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, return modes; } +static int +drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, + struct detailed_timing *timing) +{ + int i, modes = 0; + struct drm_display_mode *newmode; + struct drm_device *dev = connector->dev; + + for (i = 0; i < drm_num_cvt_inferred_modes; i++) { + if (mode_in_range(drm_cvt_inferred_modes + i, edid, timing)) { + newmode = drm_mode_duplicate(dev, &drm_cvt_inferred_modes[i]); + if (newmode) { + drm_mode_probed_add(connector, newmode); + modes++; + } + } + } + + return modes; +} + static void do_inferred_modes(struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; struct detailed_non_pixel *data = &timing->data.other_data; - int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); + int timing_level = standard_timing_level(closure->edid); - if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE) + if (data->type == EDID_DETAIL_MONITOR_RANGE) + switch (timing_level) { + case LEVEL_DMT: + break; + case LEVEL_GTF: + case LEVEL_GTF2: closure->modes += drm_gtf_modes_for_range(closure->connector, closure->edid, timing); + break; + case LEVEL_CVT: + closure->modes += drm_cvt_modes_for_range(closure->connector, + closure->edid, + timing); + break; + } } static int diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h index a91ffb1..7e14a32 100644 --- a/drivers/gpu/drm/drm_edid_modes.h +++ b/drivers/gpu/drm/drm_edid_modes.h @@ -266,6 +266,107 @@ static const struct drm_display_mode drm_dmt_modes[] = { static const int drm_num_dmt_modes = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); +static const struct drm_display_mode drm_cvt_inferred_modes[] = { + /* 640x480@60Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 23750 640, 664, + 720, 800, 0, 480, 483, 487, 500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 800x600@60Hz */ + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 38250, 800, 832, + 912, 1024, 0, 600, 603, 607, 624, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 900x600@60Hz */ + { DRM_MODE("900x600", DRM_MODE_TYPE_DRIVER, 45250, 960, 992, + 1088, 1216, 0, 600, 603, 609, 624, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1024x576@60Hz */ + { DRM_MODE("1024x576", DRM_MODE_TYPE_DRIVER, 46500, 1024, 1064, + 1160, 1296, 0, 576, 579, 584, 599, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1024x768@60Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 63500, 1024, 1072, + 1176, 1328, 0, 768, 771, 775, 798, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1152x864@60Hz */ + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 81750, 1152, 1216, + 1336, 1520, 0, 864, 867, 871, 897, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1280x720@60Hz */ + { DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74500, 1280, 1344, + 1472, 1664, 0, 720, 723, 728, 748, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1280x768@60Hz */ + { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, + 1472, 1664, 0, 768, 771, 781, 798, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1280x800@60Hz */ + { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, + 1480, 1680, 0, 800, 803, 809, 831, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1280x1024@60Hz */ + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 109000, 1280, 1368, + 1496, 1712, 0, 1024, 1027, 1034, 1063, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1360x768@60Hz */ + { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 84750, 1360, 1432, + 1568, 1776, 0, 768, 771, 781, 798, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1366x768@60Hz */ + { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 85250, 1368, 1440, + 1576, 1784, 0, 768, 771, 781, 798, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1440x900@60Hz */ + { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1528, + 1672, 1904, 0, 900, 903, 909, 934, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1400x1050@60Hz */ + { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, + 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1600x900@60Hz */ + { DRM_MODE("1600x900", DRM_MODE_TYPE_DRIVER, 118250, 1600, 1696, + 1856, 2112, 0, 900, 903, 908, 934, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1600x1200@60Hz */ + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 161000, 1600, 1712, + 1880, 2160, 0, 1200, 1203, 1207, 1245, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1680x945@60Hz */ + { DRM_MODE("1680x945", DRM_MODE_TYPE_DRIVER, 130750, 1680, 1776, + 1952, 2224, 0, 945, 948, 953, 981, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1680x1050@60Hz */ + { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, + 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1920x1080@60Hz */ + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 73000, 1920, 2048, + 2248, 2576, 0, 1080, 1083, 1088, 1120, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1920x1200@60Hz */ + { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, + 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1920x1440@60Hz */ + { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 233500, 1920, 2064, + 2264, 2608, 0, 1440, 1443, 1447, 1493, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 2048x1152@60Hz */ + { DRM_MODE("2048x1152", DRM_MODE_TYPE_DRIVER, 197000, 2048, 2184, + 2400, 2752, 0, 1152, 1155, 1160, 1195, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 2048x1536@60Hz */ + { DRM_MODE("2048x1536", DRM_MODE_TYPE_DRIVER, 272000, 2048, 2208, + 2424, 2800, 0, 1563, 1566, 1576, 1620, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 2560x1600@60Hz */ + { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2760, + 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, +}; +static const int drm_num_cvt_inferred_modes = + sizeof(drm_cvt_inferred_modes) / sizeof(struct drm_display_mode); + static const struct drm_display_mode edid_est_modes[] = { { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, -- 1.7.7.6 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel