From: MaLing <[EMAIL PROTECTED]> --- hw/xfree86/modes/xf86EdidModes.c | 264 +++++++++++++++++++------------------- 1 files changed, 133 insertions(+), 131 deletions(-)
diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c index bea2f7e..5c67c8c 100644 --- a/hw/xfree86/modes/xf86EdidModes.c +++ b/hw/xfree86/modes/xf86EdidModes.c @@ -45,20 +45,24 @@ #include <string.h> #include <math.h> +void static handle_detailed_rblank(struct detailed_monitor_section *det_mon, + void *data) +{ + + if (det_mon->type == DS_RANGES) + if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) + *(Bool*)data = TRUE; +} + static Bool xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) { /* EDID 1.4 explicitly defines RB support */ if (DDC->ver.revision >= 4) { - int i; - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - if (det_mon->type == DS_RANGES) - if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) - return TRUE; - } - - return FALSE; + Bool ret = FALSE; + + xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret); + return ret; } /* For anything older, assume digital means RB support. Boo. */ @@ -72,30 +76,6 @@ xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) * Quirks to work around broken EDID data from various monitors. */ -typedef enum { - DDC_QUIRK_NONE = 0, - /* First detailed mode is bogus, prefer largest mode at 60hz */ - DDC_QUIRK_PREFER_LARGE_60 = 1 << 0, - /* 135MHz clock is too high, drop a bit */ - DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1, - /* Prefer the largest mode at 75 Hz */ - DDC_QUIRK_PREFER_LARGE_75 = 1 << 2, - /* Convert detailed timing's horizontal from units of cm to mm */ - DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3, - /* Convert detailed timing's vertical from units of cm to mm */ - DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4, - /* Detailed timing descriptors have bogus size values, so just take the - * maximum size and use that. - */ - DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5, - /* Monitor forgot to set the first detailed is preferred bit. */ - DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6, - /* use +hsync +vsync for detailed mode */ - DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7, - /* Force single-link DVI bandwidth limit */ - DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8, -} ddc_quirk_t; - static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) { /* Belinea 10 15 55 */ @@ -667,7 +647,7 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) } } -static ddc_quirk_t +ddc_quirk_t xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) { ddc_quirk_t quirks; @@ -693,28 +673,23 @@ xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) * Note that some quirks applying to the mode list are still implemented in * xf86DDCGetModes. */ -void -xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC) +void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, + ddc_quirk_t quirks, + int hsize, int vsize) { - ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE); - int i; - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - - if (det_mon->type != DT) - continue; + if (det_mon->type != DT) + return; - if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) - det_mon->section.d_timings.h_size *= 10; + if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) + det_mon->section.d_timings.h_size *= 10; - if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) - det_mon->section.d_timings.v_size *= 10; + if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) + det_mon->section.d_timings.v_size *= 10; - if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { - det_mon->section.d_timings.h_size = 10 * DDC->features.hsize; - det_mon->section.d_timings.v_size = 10 * DDC->features.vsize; - } + if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + det_mon->section.d_timings.h_size = 10 * hsize; + det_mon->section.d_timings.v_size = 10 * vsize; } } @@ -759,14 +734,61 @@ xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes, best->type |= M_T_PREFERRED; } +struct det_modes_parameter { + xf86MonPtr DDC; + ddc_quirk_t quirks; + DisplayModePtr * Modes; + Bool rb; + Bool preferred; + int timing_level; +}; + +static void handle_detailed_modes(struct detailed_monitor_section *det_mon, + void *data) +{ + DisplayModePtr Mode; + struct det_modes_parameter *p = (struct det_modes_parameter *)data; + + xf86DetTimingApplyQuirks(det_mon,p->quirks, + p->DDC->features.hsize, + p->DDC->features.vsize); + + switch (det_mon->type) { + case DT: + + Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex, + &det_mon->section.d_timings, + p->preferred, + p->quirks); + p->preferred = FALSE; + *p->Modes = xf86ModesAdd(*p->Modes, Mode); + break; + case DS_STD_TIMINGS: + + Mode = DDCModesFromStandardTiming(det_mon->section.std_t, + p->quirks, p->timing_level,p->rb); + *p->Modes = xf86ModesAdd(*p->Modes, Mode); + break; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + case DS_CVT: + + Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt); + *p->Modes = xf86ModesAdd(*p->Modes, Mode); + break; +#endif + default: + break; + } +} + _X_EXPORT DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) { - int i; DisplayModePtr Modes = NULL, Mode; ddc_quirk_t quirks; Bool preferred, rb; int timing_level; + struct det_modes_parameter p; xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", DDC->vendor.name, DDC->vendor.prod_id); @@ -785,34 +807,14 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) timing_level = MonitorStandardTimingLevel(DDC); - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - - switch (det_mon->type) { - case DT: - Mode = DDCModeFromDetailedTiming(scrnIndex, - &det_mon->section.d_timings, - preferred, - quirks); - preferred = FALSE; - Modes = xf86ModesAdd(Modes, Mode); - break; - case DS_STD_TIMINGS: - Mode = DDCModesFromStandardTiming(det_mon->section.std_t, - quirks, timing_level, rb); - Modes = xf86ModesAdd(Modes, Mode); - break; -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - case DS_CVT: - Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt); - Modes = xf86ModesAdd(Modes, Mode); - break; -#endif - default: - break; - } - } - + p.quirks = quirks; + p.DDC = DDC; + p.Modes = &Modes; + p.rb = rb; + p.preferred = preferred; + p.timing_level = timing_level; + xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p); + /* Add established timings */ Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks); Modes = xf86ModesAdd(Modes, Mode); @@ -830,6 +832,56 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) return Modes; } +static void handle_detailed_monset(struct detailed_monitor_section *det_mon, + void *data) +{ + MonPtr Monitor = (MonPtr) data; + int clock; + int scrnIndex = ((xf86MonPtr)(Monitor->DDC))->scrnIndex; + ddc_quirk_t quirks; + + quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE); + switch (det_mon->type) { + case DS_RANGES: + if (Monitor->nHsync == 0) { + if (!Monitor->nHsync) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for horizontal sync\n"); + Monitor->hsync[Monitor->nHsync].lo = + det_mon->section.ranges.min_h; + Monitor->hsync[Monitor->nHsync].hi = + det_mon->section.ranges.max_h; + Monitor->nHsync++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using hsync ranges from config file\n"); + } + + if (Monitor->nVrefresh == 0) { + if (!Monitor->nVrefresh) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for vertical refresh\n"); + Monitor->vrefresh[Monitor->nVrefresh].lo = + det_mon->section.ranges.min_v; + Monitor->vrefresh[Monitor->nVrefresh].hi = + det_mon->section.ranges.max_v; + Monitor->nVrefresh++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using vrefresh ranges from config file\n"); + } + + clock = det_mon->section.ranges.max_clock * 1000; + if (quirks & DDC_QUIRK_DVI_SINGLE_LINK) + clock = min(clock, 165000); + if (Monitor->maxPixClock == 0 && clock >Monitor->maxPixClock) + Monitor->maxPixClock = clock; + + break; + default: + break; + } +} /* * Fill out MonPtr with xf86MonPtr information. */ @@ -837,17 +889,12 @@ _X_EXPORT void xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) { DisplayModePtr Modes = NULL, Mode; - int i, clock; - Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE; - ddc_quirk_t quirks; if (!Monitor || !DDC) return; Monitor->DDC = DDC; - quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE); - if (Monitor->widthmm <= 0 && Monitor->heightmm <= 0) { Monitor->widthmm = 10 * DDC->features.hsize; Monitor->heightmm = 10 * DDC->features.vsize; @@ -857,54 +904,9 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) Modes = xf86DDCGetModes(scrnIndex, DDC); - /* Skip EDID ranges if they were specified in the config file */ - have_hsync = (Monitor->nHsync != 0); - have_vrefresh = (Monitor->nVrefresh != 0); - have_maxpixclock = (Monitor->maxPixClock != 0); /* Go through the detailed monitor sections */ - for (i = 0; i < DET_TIMINGS; i++) { - switch (DDC->det_mon[i].type) { - case DS_RANGES: - if (!have_hsync) { - if (!Monitor->nHsync) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for horizontal sync\n"); - Monitor->hsync[Monitor->nHsync].lo = - DDC->det_mon[i].section.ranges.min_h; - Monitor->hsync[Monitor->nHsync].hi = - DDC->det_mon[i].section.ranges.max_h; - Monitor->nHsync++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using hsync ranges from config file\n"); - } - - if (!have_vrefresh) { - if (!Monitor->nVrefresh) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for vertical refresh\n"); - Monitor->vrefresh[Monitor->nVrefresh].lo = - DDC->det_mon[i].section.ranges.min_v; - Monitor->vrefresh[Monitor->nVrefresh].hi = - DDC->det_mon[i].section.ranges.max_v; - Monitor->nVrefresh++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using vrefresh ranges from config file\n"); - } - - clock = DDC->det_mon[i].section.ranges.max_clock * 1000; - if (quirks & DDC_QUIRK_DVI_SINGLE_LINK) - clock = min(clock, 165000); - if (!have_maxpixclock && clock > Monitor->maxPixClock) - Monitor->maxPixClock = clock; - - break; - default: - break; - } - } + xf86ForEachDetailedBlock(DDC, handle_detailed_monset, Monitor); if (Modes) { /* Print Modes */ -- 1.5.4.4 _______________________________________________ xorg mailing list xorg@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xorg