aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-06-22 01:17:10 -0400
committerDave Airlie <airlied@linux.ie>2009-07-15 02:52:02 -0400
commit5c61259e6c7290082108e93815f7f72f27da14f4 (patch)
tree5762aa9b05f4233d5d23b4c8d3ca1d91edd550c3 /drivers
parent26bbdadad356ec02d33657858d91675f3e9aca94 (diff)
drm/mode: get the modeline for standard timing in EDID by using CVT/GTF
Create the standard timing modeline by using CVT/GFT algorithm while interpreting the EDID. In course of interpreting the EDID, the timing level will be obtained, which is used to determine whether the CVT/GTF algorithm is selected to generate the modeline for the given hdisplay/vdisplay/vrefresh_rate. In the UMS mode firstly it will check whether it can be found in the DMT table. If it can be found, then the modeline is returned. Then the timing_level is used to choose CVT/GTF. As there is no DMT table, no modeline is returned when timing level is DMT. For the other two timing levels, the CVT/GTF will be called to generate the required standard timing modeline. [airlied: fixed up conflicts since EDID rework] Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_edid.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 80cc6d06d61b..bbcb2e22675b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -61,6 +61,10 @@
61/* use +hsync +vsync for detailed mode */ 61/* use +hsync +vsync for detailed mode */
62#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) 62#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
63 63
64#define LEVEL_DMT 0
65#define LEVEL_GTF 1
66#define LEVEL_CVT 2
67
64static struct edid_quirk { 68static struct edid_quirk {
65 char *vendor; 69 char *vendor;
66 int product_id; 70 int product_id;
@@ -240,25 +244,31 @@ static void edid_fixup_preferred(struct drm_connector *connector,
240/** 244/**
241 * drm_mode_std - convert standard mode info (width, height, refresh) into mode 245 * drm_mode_std - convert standard mode info (width, height, refresh) into mode
242 * @t: standard timing params 246 * @t: standard timing params
247 * @timing_level: standard timing level
243 * 248 *
244 * Take the standard timing params (in this case width, aspect, and refresh) 249 * Take the standard timing params (in this case width, aspect, and refresh)
245 * and convert them into a real mode using CVT. 250 * and convert them into a real mode using CVT/GTF/DMT.
246 * 251 *
247 * Punts for now, but should eventually use the FB layer's CVT based mode 252 * Punts for now, but should eventually use the FB layer's CVT based mode
248 * generation code. 253 * generation code.
249 */ 254 */
250struct drm_display_mode *drm_mode_std(struct drm_device *dev, 255struct drm_display_mode *drm_mode_std(struct drm_device *dev,
251 struct std_timing *t) 256 struct std_timing *t,
257 int timing_level)
252{ 258{
253 struct drm_display_mode *mode; 259 struct drm_display_mode *mode;
254 int hsize = t->hsize * 8 + 248, vsize; 260 int hsize, vsize;
261 int vrefresh_rate;
255 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) 262 unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
256 >> EDID_TIMING_ASPECT_SHIFT; 263 >> EDID_TIMING_ASPECT_SHIFT;
257 264 unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
258 mode = drm_mode_create(dev); 265 >> EDID_TIMING_VFREQ_SHIFT;
259 if (!mode) 266
260 return NULL; 267 /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
261 268 hsize = t->hsize * 8 + 248;
269 /* vrefresh_rate = vfreq + 60 */
270 vrefresh_rate = vfreq + 60;
271 /* the vdisplay is calculated based on the aspect ratio */
262 if (aspect_ratio == 0) 272 if (aspect_ratio == 0)
263 vsize = (hsize * 10) / 16; 273 vsize = (hsize * 10) / 16;
264 else if (aspect_ratio == 1) 274 else if (aspect_ratio == 1)
@@ -268,8 +278,23 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
268 else 278 else
269 vsize = (hsize * 9) / 16; 279 vsize = (hsize * 9) / 16;
270 280
271 drm_mode_set_name(mode); 281 mode = NULL;
272 282 switch (timing_level) {
283 case LEVEL_DMT:
284 mode = drm_mode_create(dev);
285 if (mode) {
286 mode->hdisplay = hsize;
287 mode->vdisplay = vsize;
288 drm_mode_set_name(mode);
289 }
290 break;
291 case LEVEL_GTF:
292 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
293 break;
294 case LEVEL_CVT:
295 mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
296 break;
297 }
273 return mode; 298 return mode;
274} 299}
275 300
@@ -451,6 +476,19 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e
451 476
452 return modes; 477 return modes;
453} 478}
479/**
480 * stanard_timing_level - get std. timing level(CVT/GTF/DMT)
481 * @edid: EDID block to scan
482 */
483static int standard_timing_level(struct edid *edid)
484{
485 if (edid->revision >= 2) {
486 if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
487 return LEVEL_CVT;
488 return LEVEL_GTF;
489 }
490 return LEVEL_DMT;
491}
454 492
455/** 493/**
456 * add_standard_modes - get std. modes from EDID and add them 494 * add_standard_modes - get std. modes from EDID and add them
@@ -463,6 +501,9 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
463{ 501{
464 struct drm_device *dev = connector->dev; 502 struct drm_device *dev = connector->dev;
465 int i, modes = 0; 503 int i, modes = 0;
504 int timing_level;
505
506 timing_level = standard_timing_level(edid);
466 507
467 for (i = 0; i < EDID_STD_TIMINGS; i++) { 508 for (i = 0; i < EDID_STD_TIMINGS; i++) {
468 struct std_timing *t = &edid->standard_timings[i]; 509 struct std_timing *t = &edid->standard_timings[i];
@@ -472,7 +513,8 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
472 if (t->hsize == 1 && t->vfreq_aspect == 1) 513 if (t->hsize == 1 && t->vfreq_aspect == 1)
473 continue; 514 continue;
474 515
475 newmode = drm_mode_std(dev, &edid->standard_timings[i]); 516 newmode = drm_mode_std(dev, &edid->standard_timings[i],
517 timing_level);
476 if (newmode) { 518 if (newmode) {
477 drm_mode_probed_add(connector, newmode); 519 drm_mode_probed_add(connector, newmode);
478 modes++; 520 modes++;
@@ -496,6 +538,9 @@ static int add_detailed_info(struct drm_connector *connector,
496{ 538{
497 struct drm_device *dev = connector->dev; 539 struct drm_device *dev = connector->dev;
498 int i, j, modes = 0; 540 int i, j, modes = 0;
541 int timing_level;
542
543 timing_level = standard_timing_level(edid);
499 544
500 for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { 545 for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
501 struct detailed_timing *timing = &edid->detailed_timings[i]; 546 struct detailed_timing *timing = &edid->detailed_timings[i];
@@ -541,7 +586,8 @@ static int add_detailed_info(struct drm_connector *connector,
541 struct drm_display_mode *newmode; 586 struct drm_display_mode *newmode;
542 587
543 std = &data->data.timings[j]; 588 std = &data->data.timings[j];
544 newmode = drm_mode_std(dev, std); 589 newmode = drm_mode_std(dev, std,
590 timing_level);
545 if (newmode) { 591 if (newmode) {
546 drm_mode_probed_add(connector, newmode); 592 drm_mode_probed_add(connector, newmode);
547 modes++; 593 modes++;