Fix CVT abuse in DDCModesFromStandardTiming.

CVT is enough different from GTF that it should not be used on monitors
that aren't expecting it.  This brings us closer to what the spec says
the correct behaviour is.
This commit is contained in:
Adam Jackson 2008-01-12 00:30:58 -05:00
parent 26c2e95fa5
commit d1c48955f8
2 changed files with 34 additions and 8 deletions

View File

@ -339,6 +339,8 @@
#define STD_COLOR_SPACE(x) (x & 0x4)
#define PREFERRED_TIMING_MODE(x) (x & 0x2)
#define GFT_SUPPORTED(x) (x & 0x1)
#define GTF_SUPPORTED(x) (x & 0x1)
#define CVT_SUPPORTED(x) (x & 0x1)
/* detailed timing misc */
#define IS_INTERLACED(x) (x)

View File

@ -263,6 +263,22 @@ DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
return Modes;
}
#define LEVEL_DMT 0
#define LEVEL_GTF 1
#define LEVEL_CVT 2
static int
MonitorStandardTimingLevel(xf86MonPtr DDC)
{
if (DDC->ver.revision >= 2) {
if (DDC->ver.revision >= 4 && CVT_SUPPORTED(DDC->features.msc)) {
return LEVEL_CVT;
}
return LEVEL_GTF;
}
return LEVEL_DMT;
}
/*
* This is not really correct. Appendix B of the EDID 1.4 spec defines
* the right thing to do here. If the timing given here matches a mode
@ -282,16 +298,22 @@ DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
* for modes in this section, but does say that CVT is preferred.
*/
static DisplayModePtr
DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
ddc_quirk_t quirks)
DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
int timing_level)
{
DisplayModePtr Modes = NULL, Mode = NULL;
int i;
for (i = 0; i < STD_TIMINGS; i++) {
if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
timing[i].refresh, FALSE, FALSE);
/* XXX check for DMT first, else... */
if (timing_level == LEVEL_CVT)
Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
timing[i].refresh, FALSE, FALSE);
else
Mode = xf86GTFMode(timing[i].hsize, timing[i].vsize,
timing[i].refresh, FALSE, FALSE);
Mode->type = M_T_DRIVER;
Modes = xf86ModesAdd(Modes, Mode);
}
@ -565,6 +587,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
DisplayModePtr Modes = NULL, Mode;
ddc_quirk_t quirks;
Bool preferred;
int timing_level;
xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
DDC->vendor.name, DDC->vendor.prod_id);
@ -579,6 +602,8 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75))
preferred = FALSE;
timing_level = MonitorStandardTimingLevel(DDC);
for (i = 0; i < DET_TIMINGS; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
@ -592,9 +617,8 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
Modes = xf86ModesAdd(Modes, Mode);
break;
case DS_STD_TIMINGS:
Mode = DDCModesFromStandardTiming(scrnIndex,
det_mon->section.std_t,
quirks);
Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
quirks, timing_level);
Modes = xf86ModesAdd(Modes, Mode);
break;
case DS_CVT:
@ -611,7 +635,7 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
Modes = xf86ModesAdd(Modes, Mode);
/* Add standard timings */
Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level);
Modes = xf86ModesAdd(Modes, Mode);
if (quirks & DDC_QUIRK_PREFER_LARGE_60)