1 From 2a0e3188588bce1759d3cef4d190909df2ca07ff Mon Sep 17 00:00:00 2001
2 From: Adam Jackson <ajax@redhat.com>
3 Date: Mon, 25 Aug 2008 12:55:56 -0400
4 Subject: [PATCH] EDID backport from master.
7 hw/xfree86/common/Makefile.am | 3 +-
8 hw/xfree86/common/xf86Mode.c | 14 +--
9 hw/xfree86/ddc/ddcProperty.c | 11 ++-
10 hw/xfree86/ddc/edid.h | 5 +-
11 hw/xfree86/ddc/interpret_edid.c | 14 +++
12 hw/xfree86/ddc/print_edid.c | 28 +++--
13 hw/xfree86/ddc/xf86DDC.c | 241 +++++++++++++++++++++++---------------
14 hw/xfree86/ddc/xf86DDC.h | 6 +
15 hw/xfree86/loader/xf86sym.c | 1 +
16 hw/xfree86/modes/xf86Crtc.c | 11 +-
17 hw/xfree86/modes/xf86EdidModes.c | 228 +++++++++++++++++++++++++++++++-----
18 hw/xfree86/modes/xf86Modes.c | 12 ++
19 hw/xfree86/modes/xf86Modes.h | 3 +
20 13 files changed, 422 insertions(+), 155 deletions(-)
22 diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
23 index 0f44075..8aa3adc 100644
24 --- a/hw/xfree86/common/Makefile.am
25 +++ b/hw/xfree86/common/Makefile.am
26 @@ -45,7 +45,8 @@ libinit_a_SOURCES = xf86Build.h xf86Init.c
27 INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \
28 -I$(srcdir)/../loader -I$(srcdir)/../rac -I$(srcdir)/../parser \
29 -I$(srcdir)/../vbe -I$(srcdir)/../int10 \
30 - -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod
31 + -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod \
32 + -I$(srcdir)/../modes
34 sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \
35 xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86Resources.h \
36 diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
37 index c1b0a5f..24a431d 100644
38 --- a/hw/xfree86/common/xf86Mode.c
39 +++ b/hw/xfree86/common/xf86Mode.c
44 +#include "xf86Modes.h"
48 @@ -705,16 +706,9 @@ xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor)
52 - /* Is the horizontal blanking a bit lowish? */
53 - if (((mode->HDisplay * 5 / 4) & ~0x07) > mode->HTotal) {
54 - /* is this a cvt -r mode, and only a cvt -r mode? */
55 - if (((mode->HTotal - mode->HDisplay) == 160) &&
56 - ((mode->HSyncEnd - mode->HDisplay) == 80) &&
57 - ((mode->HSyncEnd - mode->HSyncStart) == 32) &&
58 - ((mode->VSyncStart - mode->VDisplay) == 3)) {
59 - if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER))
60 - return MODE_NO_REDUCED;
62 + if (xf86ModeIsReduced(mode)) {
63 + if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER))
64 + return MODE_NO_REDUCED;
67 if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock))
68 diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
69 index 02125df..a4384f1 100644
70 --- a/hw/xfree86/ddc/ddcProperty.c
71 +++ b/hw/xfree86/ddc/ddcProperty.c
72 @@ -83,13 +83,18 @@ addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC)
76 - if ((EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL)
79 + if (DDC->flags & EDID_COMPLETE_RAWDATA)
80 + size += DDC->no_sections * 128;
82 + if ((EDID1rawdata = xalloc(size*sizeof(CARD8)))==NULL)
85 EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME) - 1, TRUE);
86 - memcpy(EDID1rawdata, DDC->rawData, 128);
87 + memcpy(EDID1rawdata, DDC->rawData, size);
88 xf86RegisterRootWindowProperty(scrnIndex, EDID1Atom, XA_INTEGER, 8,
89 - 128, (unsigned char *)EDID1rawdata);
90 + size, (unsigned char *)EDID1rawdata);
94 diff --git a/hw/xfree86/ddc/edid.h b/hw/xfree86/ddc/edid.h
95 index a4e79da..45caf6e 100644
96 --- a/hw/xfree86/ddc/edid.h
97 +++ b/hw/xfree86/ddc/edid.h
98 @@ -531,6 +531,9 @@ struct detailed_monitor_section {
99 } section; /* max: 80 */
103 +#define EDID_COMPLETE_RAWDATA 0x1
107 struct vendor vendor;
108 @@ -539,7 +542,7 @@ typedef struct {
109 struct established_timings timings1;
110 struct std_timings timings2[8];
111 struct detailed_monitor_section det_mon[4];
112 - void *vdif; /* unused */
113 + unsigned long flags;
116 } xf86Monitor, *xf86MonPtr;
117 diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
118 index 21391dd..d293861 100644
119 --- a/hw/xfree86/ddc/interpret_edid.c
120 +++ b/hw/xfree86/ddc/interpret_edid.c
121 @@ -118,6 +118,20 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
126 +xf86InterpretEEDID(int scrnIndex, Uchar *block)
130 + m = xf86InterpretEDID(scrnIndex, block);
134 + /* extension parse */
140 get_vendor_section(Uchar *c, struct vendor *r)
142 diff --git a/hw/xfree86/ddc/print_edid.c b/hw/xfree86/ddc/print_edid.c
143 index f5442ad..5e89b40 100644
144 --- a/hw/xfree86/ddc/print_edid.c
145 +++ b/hw/xfree86/ddc/print_edid.c
146 @@ -462,22 +462,28 @@ print_number_sections(int scrnIndex, int num)
148 xf86PrintEDID(xf86MonPtr m)
152 char buf[EDID_WIDTH * 2 + 1];
154 - if (!(m)) return NULL;
155 + if (!m) return NULL;
157 - print_vendor(m->scrnIndex,&m->vendor);
158 - print_version(m->scrnIndex,&m->ver);
159 - print_display(m->scrnIndex,&m->features, &m->ver);
160 - print_established_timings(m->scrnIndex,&m->timings1);
161 - print_std_timings(m->scrnIndex,m->timings2);
162 - print_detailed_monitor_section(m->scrnIndex,m->det_mon);
163 - print_number_sections(m->scrnIndex,m->no_sections);
164 + print_vendor(m->scrnIndex, &m->vendor);
165 + print_version(m->scrnIndex, &m->ver);
166 + print_display(m->scrnIndex, &m->features, &m->ver);
167 + print_established_timings(m->scrnIndex, &m->timings1);
168 + print_std_timings(m->scrnIndex, m->timings2);
169 + print_detailed_monitor_section(m->scrnIndex, m->det_mon);
170 + print_number_sections(m->scrnIndex, m->no_sections);
172 + /* extension block section stuff */
174 xf86DrvMsg(m->scrnIndex, X_INFO, "EDID (in hex):\n");
176 - for (i = 0; i < 128; i += j) {
179 + if (m->flags & EDID_COMPLETE_RAWDATA)
180 + n += m->no_sections * 128;
182 + for (i = 0; i < n; i += j) {
183 for (j = 0; j < EDID_WIDTH; ++j) {
184 sprintf(&buf[j * 2], "%02x", m->rawData[i + j]);
186 diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
187 index 28e2ead..0d86776 100644
188 --- a/hw/xfree86/ddc/xf86DDC.c
189 +++ b/hw/xfree86/ddc/xf86DDC.c
192 * Copyright 1998,1999 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
196 + * Note that DDC1 does not define any method for returning blocks beyond
197 + * the first. DDC2 does, but the original implementation would only ever
198 + * read the first block. If you want to read and parse all blocks, use
202 #ifdef HAVE_XORG_CONFIG_H
203 #include <xorg-config.h>
205 @@ -31,18 +39,6 @@ static unsigned int *FetchEDID_DDC1(
206 register unsigned int (*)(ScrnInfoPtr)
209 -static unsigned char* EDID1Read_DDC2(
214 -static unsigned char * DDCRead_DDC2(
224 @@ -107,10 +103,102 @@ xf86DoEDID_DDC1(
229 +DDC2MakeDevice(I2CBusPtr pBus, int address, char *name)
231 + I2CDevPtr dev = NULL;
233 + if (!(dev = xf86I2CFindDev(pBus, address))) {
234 + dev = xf86CreateI2CDevRec();
235 + dev->DevName = name;
236 + dev->SlaveAddr = address;
237 + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
238 + dev->StartTimeout = 550;
239 + dev->BitTimeout = 40;
240 + dev->AcknTimeout = 40;
242 + dev->pI2CBus = pBus;
243 + if (!xf86I2CDevInit(dev)) {
244 + xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n");
253 +DDC2Init(int scrnIndex, I2CBusPtr pBus)
255 + I2CDevPtr dev = NULL;
258 + * Slow down the bus so that older monitors don't
261 + pBus->RiseFallTime = 20;
263 + DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register");
264 + dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2");
269 +/* Mmmm, smell the hacks */
271 +EEDIDStop(I2CDevPtr d)
275 +/* block is the EDID block number. a segment is two blocks. */
277 +DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer)
279 + unsigned char W_Buffer[1];
282 + void (*stop)(I2CDevPtr);
284 + for (i = 0; i < RETRIES; i++) {
285 + /* Stop bits reset the segment pointer to 0, so be careful here. */
286 + segment = block >> 1;
290 + if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060)))
293 + W_Buffer[0] = segment;
295 + stop = dev->pI2CBus->I2CStop;
296 + dev->pI2CBus->I2CStop = EEDIDStop;
298 + b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0);
300 + dev->pI2CBus->I2CStop = stop;
302 + dev->pI2CBus->I2CStop(dev);
307 + W_Buffer[0] = (block & 0x01) * EDID1_LEN;
309 + if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) {
310 + if (!DDC_checksum(R_Buffer, EDID1_LEN))
319 * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
320 * unset. EDID information blocks are interpreted and the results returned in
322 + * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return
323 + * the complete EDID data, including all extension blocks, if the 'complete'
324 + * parameter is TRUE;
326 * This function does not affect the list of modes used by drivers -- it is up
327 * to the driver to decide policy on what to do with EDID information.
328 @@ -119,46 +207,72 @@ xf86DoEDID_DDC1(
329 * @return NULL if no monitor attached or failure to interpret the EDID.
332 -xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
333 +xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete)
335 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
336 unsigned char *EDID_block = NULL;
337 xf86MonPtr tmp = NULL;
338 + I2CDevPtr dev = NULL;
339 /* Default DDC and DDC2 to enabled. */
340 Bool noddc = FALSE, noddc2 = FALSE;
341 OptionInfoPtr options;
343 - options = xnfalloc(sizeof(DDCOptions));
344 - (void)memcpy(options, DDCOptions, sizeof(DDCOptions));
345 + options = xalloc(sizeof(DDCOptions));
348 + memcpy(options, DDCOptions, sizeof(DDCOptions));
349 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
351 xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
352 xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2);
359 - EDID_block = EDID1Read_DDC2(scrnIndex,pBus);
360 + if (!(dev = DDC2Init(scrnIndex, pBus)))
364 - tmp = xf86InterpretEDID(scrnIndex,EDID_block);
367 - ErrorF("No EDID block returned\n");
369 + EDID_block = xcalloc(1, EDID1_LEN);
373 + if (DDC2Read(dev, 0, EDID_block)) {
374 + int i, n = EDID_block[0x7e];
376 + if (complete && n) {
377 + EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n));
379 + for (i = 0; i < n; i++)
380 + DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i)));
383 + tmp = xf86InterpretEEDID(scrnIndex, EDID_block);
387 - ErrorF("Cannot interpret EDID block\n");
389 - ErrorF("Sections to follow: %i\n",tmp->no_sections);
393 + if (tmp && complete)
394 + tmp->flags |= EDID_COMPLETE_RAWDATA;
400 + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
401 + * unset. EDID information blocks are interpreted and the results returned in
404 + * This function does not affect the list of modes used by drivers -- it is up
405 + * to the driver to decide policy on what to do with EDID information.
407 + * @return pointer to a new xf86MonPtr containing the EDID information.
408 + * @return NULL if no monitor attached or failure to interpret the EDID.
411 +xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
413 + return xf86DoEEDID(scrnIndex, pBus, FALSE);
417 * read EDID record , pass it to callback function to interpret.
418 * callback function will store it for further use by calling
419 @@ -225,68 +339,3 @@ FetchEDID_DDC1(register ScrnInfoPtr pScrn,
424 -static unsigned char*
425 -EDID1Read_DDC2(int scrnIndex, I2CBusPtr pBus)
427 - return DDCRead_DDC2(scrnIndex, pBus, 0, EDID1_LEN);
430 -static unsigned char *
431 -DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len)
434 - unsigned char W_Buffer[2];
436 - unsigned char *R_Buffer;
440 - * Slow down the bus so that older monitors don't
443 - pBus->RiseFallTime = 20;
445 - if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
446 - dev = xf86CreateI2CDevRec();
447 - dev->DevName = "ddc2";
448 - dev->SlaveAddr = 0xA0;
449 - dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
450 - dev->StartTimeout = 550;
451 - dev->BitTimeout = 40;
452 - dev->AcknTimeout = 40;
454 - dev->pI2CBus = pBus;
455 - if (!xf86I2CDevInit(dev)) {
456 - xf86DrvMsg(scrnIndex, X_PROBED, "No DDC2 device\n");
460 - if (start < 0x100) {
462 - W_Buffer[0] = start;
465 - W_Buffer[0] = start & 0xFF;
466 - W_Buffer[1] = (start & 0xFF00) >> 8;
468 - R_Buffer = xcalloc(1,sizeof(unsigned char)
470 - for (i=0; i<RETRIES; i++) {
471 - if (xf86I2CWriteRead(dev, W_Buffer,w_bytes, R_Buffer,len)) {
472 - if (!DDC_checksum(R_Buffer,len))
476 - else ErrorF("Checksum error in EDID block\n");
480 - else ErrorF("Error reading EDID block\n");
484 - xf86DestroyI2CDevRec(dev,TRUE);
488 diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h
489 index 3b072dd..42d9ce6 100644
490 --- a/hw/xfree86/ddc/xf86DDC.h
491 +++ b/hw/xfree86/ddc/xf86DDC.h
492 @@ -35,6 +35,8 @@ extern xf86MonPtr xf86DoEDID_DDC2(
496 +extern xf86MonPtr xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool);
498 extern xf86MonPtr xf86PrintEDID(
501 @@ -43,6 +45,10 @@ extern xf86MonPtr xf86InterpretEDID(
502 int screenIndex, Uchar *block
505 +extern xf86MonPtr xf86InterpretEEDID(
506 + int screenIndex, Uchar *block
510 xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC);
512 diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
513 index 24fc44c..77d7d45 100644
514 --- a/hw/xfree86/loader/xf86sym.c
515 +++ b/hw/xfree86/loader/xf86sym.c
516 @@ -1009,6 +1009,7 @@ _X_HIDDEN void *xfree86LookupTab[] = {
517 SYMFUNC(xf86DoEDID_DDC2)
518 SYMFUNC(xf86InterpretEDID)
519 SYMFUNC(xf86PrintEDID)
520 + SYMFUNC(xf86DoEEDID)
521 SYMFUNC(xf86DDCMonitorSet)
522 SYMFUNC(xf86SetDDCproperties)
524 diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
525 index 91ba1b7..2941b8b 100644
526 --- a/hw/xfree86/modes/xf86Crtc.c
527 +++ b/hw/xfree86/modes/xf86Crtc.c
528 @@ -2575,9 +2575,11 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
532 - if (edid_mon->ver.version == 1)
533 + if (edid_mon->ver.version == 1) {
535 - else if (edid_mon->ver.version == 2)
536 + if (edid_mon->flags & EDID_COMPLETE_RAWDATA)
537 + size += edid_mon->no_sections * 128;
538 + } else if (edid_mon->ver.version == 2)
541 xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);
542 @@ -2622,15 +2624,16 @@ xf86OutputGetEDIDModes (xf86OutputPtr output)
543 return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
546 +/* maybe we should care about DDC1? meh. */
548 xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
550 ScrnInfoPtr scrn = output->scrn;
553 - mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
554 + mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE);
556 - xf86DDCApplyQuirks (scrn->scrnIndex, mon);
557 + xf86DDCApplyQuirks(scrn->scrnIndex, mon);
561 diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
562 index bf0ea3f..7e80601 100644
563 --- a/hw/xfree86/modes/xf86EdidModes.c
564 +++ b/hw/xfree86/modes/xf86EdidModes.c
567 * Copyright 2006 Luc Verhaegen.
568 + * Copyright 2008 Red Hat, Inc.
570 * Permission is hereby granted, free of charge, to any person obtaining a
571 * copy of this software and associated documentation files (the "Software"),
576 +#define _PARSE_EDID_
579 #include <X11/Xatom.h>
580 #include "property.h"
581 #include "propertyst.h"
582 -#include "xf86DDC.h"
583 #include "xf86Crtc.h"
588 +xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
590 + /* EDID 1.4 explicitly defines RB support */
591 + if (DDC->ver.revision >= 4) {
593 + for (i = 0; i < DET_TIMINGS; i++) {
594 + struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
595 + if (det_mon->type == DS_RANGES)
596 + if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
603 + /* For anything older, assume digital means RB support. Boo. */
604 + if (DDC->features.input_type)
611 * Quirks to work around broken EDID data from various monitors.
613 @@ -68,6 +92,8 @@ typedef enum {
614 DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6,
615 /* use +hsync +vsync for detailed mode */
616 DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7,
617 + /* Force single-link DVI bandwidth limit */
618 + DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8,
621 static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
622 @@ -181,6 +207,16 @@ static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC)
626 +/* This should probably be made more generic */
627 +static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC)
629 + /* Red Hat bug #453106: Apple 23" Cinema Display */
630 + if (memcmp (DDC->vendor.name, "APL", 4) == 0 &&
631 + DDC->vendor.prod_id == 0x921c)
637 Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
639 @@ -220,6 +256,10 @@ static const ddc_quirk_map_t ddc_quirks[] = {
640 quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP,
641 "Use +hsync +vsync for detailed timing."
644 + quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK,
645 + "Forcing maximum pixel clock to single DVI link."
648 NULL, DDC_QUIRK_NONE,
650 @@ -227,8 +267,13 @@ static const ddc_quirk_map_t ddc_quirks[] = {
655 - * - for those with access to the VESA DMT standard; review please.
656 + * These more or less come from the DMT spec. The 720x400 modes are
657 + * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75
658 + * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode
659 + * should be 1152x870, again for the Mac, but instead we use the x864 DMT
662 + * The DMT modes have been fact-checked; the rest are mild guesses.
664 #define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER
665 #define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
666 @@ -237,16 +282,16 @@ static const DisplayModeRec DDCEstablishedModes[17] = {
667 { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
668 { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
669 { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
670 - { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
671 + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
672 { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
673 - { MODEPREFIX, 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
674 + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
675 { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
676 { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
677 { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
678 - { MODEPREFIX, 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
679 + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
680 { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
681 { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
682 - { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
683 + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
684 { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
685 { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
686 { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
687 @@ -272,6 +317,90 @@ DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
691 +/* Autogenerated from the DMT spec */
692 +static const DisplayModeRec DMTModes[] = {
693 + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */
694 + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */
695 + { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */
696 + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
697 + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
698 + { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
699 + { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */
700 + { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
701 + { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
702 + { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
703 + { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
704 + { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */
705 + { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */
706 + { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */
707 + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */
708 + { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
709 + { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
710 + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
711 + { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */
712 + { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */
713 + { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
714 + { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */
715 + { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */
716 + { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */
717 + { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */
718 + { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */
719 + { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */
720 + { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */
721 + { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */
722 + { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */
723 + { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */
724 + { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */
725 + { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */
726 + { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */
727 + { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */
728 + { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
729 + { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */
730 + { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */
731 + { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */
732 + { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */
733 + { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */
734 + { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */
735 + { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */
736 + { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */
737 + { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */
738 + { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */
739 + { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */
740 + { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */
741 + { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */
742 + { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */
743 + { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */
744 + { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */
745 + { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */
746 + { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */
747 + { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */
748 + { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */
749 + { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */
750 + { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */
751 + { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */
752 + { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */
753 + { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */
754 + { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */
755 + { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */
756 + { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */
757 + { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */
758 + { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */
759 + { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */
760 + { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */
761 + { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */
762 + { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */
763 + { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */
764 + { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */
765 + { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */
766 + { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */
767 + { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */
768 + { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */
769 + { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */
770 + { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */
771 + { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */
772 + { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */
778 @@ -288,12 +417,43 @@ MonitorStandardTimingLevel(xf86MonPtr DDC)
783 +ModeRefresh(DisplayModePtr mode)
785 + return (int)(xf86ModeVRefresh(mode) + 0.5);
789 - * This is not really correct. Appendix B of the EDID 1.4 spec defines
790 - * the right thing to do here. If the timing given here matches a mode
791 - * defined in the VESA DMT standard, we _must_ use that. If the device
792 - * supports CVT modes, then we should generate a CVT timing. If both
793 - * of the above fail, use GTF.
794 + * If rb is not set, then we'll not consider reduced-blanking modes as
795 + * part of the DMT pool. For the 'standard' EDID mode descriptor there's
796 + * no way to specify whether the mode should be RB or not.
798 +static DisplayModePtr
799 +FindDMTMode(int hsize, int vsize, int refresh, Bool rb)
802 + DisplayModePtr ret;
804 + for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) {
805 + ret = &DMTModes[i];
807 + if (!rb && xf86ModeIsReduced(ret))
810 + if (ret->HDisplay == hsize &&
811 + ret->VDisplay == vsize &&
812 + refresh == ModeRefresh(ret))
813 + return xf86DuplicateMode(ret);
820 + * Appendix B of the EDID 1.4 spec defines the right thing to do here.
821 + * If the timing given here matches a mode defined in the VESA DMT standard,
822 + * we _must_ use that. If the device supports CVT modes, then we should
823 + * generate a CVT timing. If both of the above fail, use GTF.
825 * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really
826 * "support" GTF, since it wasn't a standard yet; so if they ask for a
827 @@ -308,20 +468,28 @@ MonitorStandardTimingLevel(xf86MonPtr DDC)
829 static DisplayModePtr
830 DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
832 + int timing_level, Bool rb)
834 DisplayModePtr Modes = NULL, Mode = NULL;
837 for (i = 0; i < STD_TIMINGS; i++) {
838 if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
839 - /* XXX check for DMT first, else... */
840 - if (timing_level == LEVEL_CVT)
841 - Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
842 - timing[i].refresh, FALSE, FALSE);
844 - Mode = xf86GTFMode(timing[i].hsize, timing[i].vsize,
845 - timing[i].refresh, FALSE, FALSE);
846 + Mode = FindDMTMode(timing[i].hsize, timing[i].vsize,
847 + timing[i].refresh, rb);
850 + if (timing_level == LEVEL_CVT)
851 + /* pass rb here too? */
852 + Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
853 + timing[i].refresh, FALSE, FALSE);
854 + else if (timing_level == LEVEL_GTF)
855 + Mode = xf86GTFMode(timing[i].hsize, timing[i].vsize,
856 + timing[i].refresh, FALSE, FALSE);
862 Mode->type = M_T_DRIVER;
863 Modes = xf86ModesAdd(Modes, Mode);
864 @@ -595,7 +763,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
866 DisplayModePtr Modes = NULL, Mode;
869 + Bool preferred, rb;
872 xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
873 @@ -611,6 +779,8 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
874 if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75))
877 + rb = xf86MonitorSupportsReducedBlanking(DDC);
879 timing_level = MonitorStandardTimingLevel(DDC);
881 for (i = 0; i < DET_TIMINGS; i++) {
882 @@ -627,7 +797,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
885 Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
886 - quirks, timing_level);
887 + quirks, timing_level, rb);
888 Modes = xf86ModesAdd(Modes, Mode);
891 @@ -644,7 +814,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
892 Modes = xf86ModesAdd(Modes, Mode);
894 /* Add standard timings */
895 - Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level);
896 + Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
897 Modes = xf86ModesAdd(Modes, Mode);
899 if (quirks & DDC_QUIRK_PREFER_LARGE_60)
900 @@ -665,23 +835,21 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
901 DisplayModePtr Modes = NULL, Mode;
903 Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE;
904 + ddc_quirk_t quirks;
906 if (!Monitor || !DDC)
911 + quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE);
913 if (Monitor->widthmm <= 0 && Monitor->heightmm <= 0) {
914 Monitor->widthmm = 10 * DDC->features.hsize;
915 Monitor->heightmm = 10 * DDC->features.vsize;
919 - * If this is a digital display, then we can use reduced blanking.
920 - * XXX This is a 1.3 heuristic. 1.4 explicitly defines rb support.
922 - if (DDC->features.input_type)
923 - Monitor->reducedblanking = TRUE;
924 + Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC);
926 Modes = xf86DDCGetModes(scrnIndex, DDC);
928 @@ -723,6 +891,8 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
931 clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
932 + if (quirks & DDC_QUIRK_DVI_SINGLE_LINK)
933 + clock = min(clock, 165000);
934 if (!have_maxpixclock && clock > Monitor->maxPixClock)
935 Monitor->maxPixClock = clock;
937 diff --git a/hw/xfree86/modes/xf86Modes.c b/hw/xfree86/modes/xf86Modes.c
938 index ea398ad..da25273 100644
939 --- a/hw/xfree86/modes/xf86Modes.c
940 +++ b/hw/xfree86/modes/xf86Modes.c
941 @@ -513,6 +513,18 @@ xf86ValidateModesBandwidth(ScrnInfoPtr pScrn, DisplayModePtr modeList,
946 +xf86ModeIsReduced(DisplayModePtr mode)
948 + if ((((mode->HDisplay * 5 / 4) & ~0x07) > mode->HTotal) &&
949 + ((mode->HTotal - mode->HDisplay) == 160) &&
950 + ((mode->HSyncEnd - mode->HDisplay) == 80) &&
951 + ((mode->HSyncEnd - mode->HSyncStart) == 32) &&
952 + ((mode->VSyncStart - mode->VDisplay) == 3))
958 * Marks as bad any reduced-blanking modes.
960 diff --git a/hw/xfree86/modes/xf86Modes.h b/hw/xfree86/modes/xf86Modes.h
961 index acdea65..af5987b 100644
962 --- a/hw/xfree86/modes/xf86Modes.h
963 +++ b/hw/xfree86/modes/xf86Modes.h
964 @@ -64,6 +64,9 @@ DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
965 Bool Reduced, Bool Interlaced);
966 DisplayModePtr xf86GTFMode(int h_pixels, int v_lines, float freq, int interlaced, int margins);
969 +xf86ModeIsReduced(DisplayModePtr mode);
972 xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,