diff --git a/dix/globals.c b/dix/globals.c index fc77ca793..f86c6026d 100644 --- a/dix/globals.c +++ b/dix/globals.c @@ -105,7 +105,7 @@ int ScreenSaverAllowExposures; # define DEFAULT_OFF_TIME DEFAULT_SCREEN_SAVER_TIME * 4 # endif # ifndef DEFAULT_DPMS_ENABLED -# define DEFAULT_DPMS_ENABLED FALSE +# define DEFAULT_DPMS_ENABLED TRUE # endif CARD32 defaultDPMSStandbyTime = DEFAULT_STANDBY_TIME; CARD32 defaultDPMSSuspendTime = DEFAULT_SUSPEND_TIME; diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c index 4dcc997c1..4f6a98aef 100644 --- a/hw/xfree86/common/xf86AutoConfig.c +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -48,6 +48,9 @@ "\tLoad\t\"dbe\"\n" \ "\tLoad\t\"glx\"\n" \ "\tLoad\t\"freetype\"\n" \ + "\tLoad\t\"type1\"\n" \ + "\tLoad\t\"record\"\n" \ + "\tLoad\t\"dri\"\n" \ "EndSection\n\n" #define BUILTIN_DEVICE_NAME \ diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 4138eb16c..57f929b58 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -63,7 +63,7 @@ #include "xf86Config.h" #include "xf86Priv.h" #include "xf86_OSlib.h" - +#include "configProcs.h" #include "globals.h" #include "extension.h" @@ -280,9 +280,21 @@ xf86ModulelistFromConfig(pointer **optlist) count++; modp = (XF86LoadPtr) modp->list.next; } + } else { + xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec)); + } + + if (count == 0) { + XF86ConfModulePtr ptr = xf86configptr->conf_modules; + ptr = xf86addNewLoadDirective(ptr, "extmod", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "dbe", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "glx", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "freetype", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "type1", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "record", XF86_LOAD_MODULE, NULL); + ptr = xf86addNewLoadDirective(ptr, "dri", XF86_LOAD_MODULE, NULL); + count = 7; } - if (count == 0) - return NULL; /* * allocate the memory and walk the list again to fill in the pointers @@ -1132,12 +1144,13 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) IDevPtr corePointer = NULL, coreKeyboard = NULL; Bool foundPointer = FALSE, foundKeyboard = FALSE; const char *pointerMsg = NULL, *keyboardMsg = NULL; - IDevPtr indp; + IDevPtr indp, i; IDevRec Pointer, Keyboard; XF86ConfInputPtr confInput; XF86ConfInputRec defPtr, defKbd; int count = 0; MessageType from = X_DEFAULT; + int found = 0; /* * First check if a core pointer or core keyboard have been specified @@ -1289,6 +1302,35 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) return FALSE; } + /* + * always synthesize a 'mouse' section configured to send core + * events, unless a 'void' section is found, in which case the user + * probably wants to run footless. + */ + for (i = servlayoutp->inputs; i->driver; i++) { + if (!strcmp(i->driver, "void") || !strcmp(i->driver, "mouse")) { + found = 1; break; + } + } + if (!found) { + xf86Msg(X_INFO, "No default mouse found, adding one\n"); + bzero(&defPtr, sizeof(defPtr)); + defPtr.inp_identifier = ""; + defPtr.inp_driver = "mouse"; + confInput = &defPtr; + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + indp = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(IDevRec)); + indp[count - 1] = Pointer; + indp[count - 1].extraOptions = + xf86addNewOption(NULL, "AlwaysCore", NULL); + indp[count].identifier = NULL; + servlayoutp->inputs = indp; + } + } + confInput = NULL; /* 1. Check for the -keyboard command line option. */ @@ -1889,6 +1931,7 @@ configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor) monitorp->widthmm = conf_monitor->mon_width; monitorp->heightmm = conf_monitor->mon_height; monitorp->reducedblanking = FALSE; + monitorp->maxPixClock = 0; monitorp->options = conf_monitor->mon_option_lst; /* diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index d7fc43731..09c08d2c6 100644 --- a/hw/xfree86/common/xf86Helper.c +++ b/hw/xfree86/common/xf86Helper.c @@ -456,11 +456,11 @@ xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad) #define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32)) #ifndef GLOBAL_DEFAULT_DEPTH -#define GLOBAL_DEFAULT_DEPTH 16 +#define GLOBAL_DEFAULT_DEPTH 24 #endif #ifndef GLOBAL_DEFAULT_FBBPP -#define GLOBAL_DEFAULT_FBBPP 16 +#define GLOBAL_DEFAULT_FBBPP 32 #endif _X_EXPORT Bool @@ -1661,6 +1661,8 @@ xf86MatchPciInstances(const char *driverName, int vendorID, *foundEntities = NULL; + if (!xf86PciVideoInfo) + return 0; /* Each PCI device will contribute at least one entry. Each device * section can contribute at most one entry. The sum of the two is diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c index cd57e9916..456331d3f 100644 --- a/hw/xfree86/common/xf86Mode.c +++ b/hw/xfree86/common/xf86Mode.c @@ -45,7 +45,7 @@ #include "globals.h" #include "xf86.h" #include "xf86Priv.h" -#include "xf86DDC.h" +#include "edid.h" static void printModeRejectMessage(int index, DisplayModePtr p, int status) @@ -56,6 +56,8 @@ printModeRejectMessage(int index, DisplayModePtr p, int status) type = "built-in "; else if (p->type & M_T_DEFAULT) type = "default "; + else if (p->type & M_T_DRIVER) + type = "driver "; else type = ""; @@ -443,6 +445,17 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, ModeStatus status = MODE_NOMODE; Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; Bool haveBuiltin; + int n; + const int types[] = { + M_T_BUILTIN | M_T_PREFERRED, + M_T_BUILTIN, + M_T_USERDEF | M_T_PREFERRED, + M_T_USERDEF, + M_T_DRIVER | M_T_PREFERRED, + M_T_DRIVER, + 0 + }; + const int ntypes = sizeof(types) / sizeof(int); strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES); @@ -462,143 +475,141 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, cp->ClockMulFactor = max(1, cp->ClockMulFactor); } - haveBuiltin = FALSE; /* Scan the mode pool for matching names */ - for (p = scrp->modePool; p != NULL; p = p->next) { - if (strcmp(p->name, modep->name) == 0) { - /* - * Requested mode is a built-in mode. Don't let the user - * override it. - * Since built-in modes always come before user specified - * modes it will always be found first. - */ - if (p->type & M_T_BUILTIN) { - haveBuiltin = TRUE; - } + for (n = 0; n < ntypes; n++) { + int type = types[n]; + for (p = scrp->modePool; p != NULL; p = p->next) { - if (haveBuiltin && !(p->type & M_T_BUILTIN)) + /* scan through the modes in the sort order above */ + if ((p->type & type) != type) continue; - /* Skip over previously rejected modes */ - if (p->status != MODE_OK) { - if (!found) - status = p->status; - continue; - } - - /* Skip over previously considered modes */ - if (p->prev) - continue; + if (strcmp(p->name, modep->name) == 0) { - if (p->type & M_T_BUILTIN) { - return xf86HandleBuiltinMode(scrp, p,modep, clockRanges, - allowDiv2); - } + /* Skip over previously rejected modes */ + if (p->status != MODE_OK) { + if (!found) + status = p->status; + continue; + } + + /* Skip over previously considered modes */ + if (p->prev) + continue; + + if (p->type & M_T_BUILTIN) { + return xf86HandleBuiltinMode(scrp, p,modep, clockRanges, + allowDiv2); + } + + /* Check clock is in range */ + cp = xf86FindClockRangeForMode(clockRanges, p); + if (cp == NULL) { + /* + * XXX Could do more here to provide a more detailed + * reason for not finding a mode. + */ + p->status = MODE_CLOCK_RANGE; + if (!found) + status = MODE_CLOCK_RANGE; + continue; + } - /* Check clock is in range */ - cp = xf86FindClockRangeForMode(clockRanges, p); - if (cp == NULL) { /* - * XXX Could do more here to provide a more detailed - * reason for not finding a mode. + * If programmable clock and strategy is not + * LOOKUP_BEST_REFRESH, the required mode has been found, + * otherwise record the refresh and continue looking. */ - p->status = MODE_CLOCK_RANGE; - if (!found) - status = MODE_CLOCK_RANGE; - continue; - } + if (scrp->progClock) { + found = TRUE; + if (strategy != LOOKUP_BEST_REFRESH) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + break; + } + refresh = ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + bestRefresh = refresh; + } + continue; + } - /* - * If programmable clock and strategy is not LOOKUP_BEST_REFRESH, - * the required mode has been found, otherwise record the refresh - * and continue looking. - */ - if (scrp->progClock) { + /* + * Clock is in range, so if it is not a programmable clock, find + * a matching clock. + */ + + i = xf86GetNearestClock(scrp, p->Clock, allowDiv2, + cp->ClockDivFactor, cp->ClockMulFactor, &k); + /* + * If the clock is too far from the requested clock, this + * mode is no good. + */ + if (k & V_CLKDIV2) + gap = abs((p->Clock * 2) - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + else + gap = abs(p->Clock - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + if (gap > minimumGap) { + p->status = MODE_NOCLOCK; + if (!found) + status = MODE_NOCLOCK; + continue; + } found = TRUE; - if (strategy != LOOKUP_BEST_REFRESH) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - break; - } - refresh = ModeVRefresh(p); - if (p->Flags & V_INTERLACE) - refresh /= INTERLACE_REFRESH_WEIGHT; - if (refresh > bestRefresh) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - bestRefresh = refresh; - } - continue; - } - /* - * Clock is in range, so if it is not a programmable clock, find - * a matching clock. - */ - - i = xf86GetNearestClock(scrp, p->Clock, allowDiv2, - cp->ClockDivFactor, cp->ClockMulFactor, &k); - /* - * If the clock is too far from the requested clock, this - * mode is no good. - */ - if (k & V_CLKDIV2) - gap = abs((p->Clock * 2) - - ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor)); - else - gap = abs(p->Clock - - ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor)); - if (gap > minimumGap) { - p->status = MODE_NOCLOCK; - if (!found) - status = MODE_NOCLOCK; - continue; - } - found = TRUE; - - if (strategy == LOOKUP_BEST_REFRESH) { - refresh = ModeVRefresh(p); - if (p->Flags & V_INTERLACE) - refresh /= INTERLACE_REFRESH_WEIGHT; - if (refresh > bestRefresh) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - bestRefresh = refresh; + if (strategy == LOOKUP_BEST_REFRESH) { + refresh = ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + bestRefresh = refresh; + } + continue; } - continue; - } - if (strategy == LOOKUP_CLOSEST_CLOCK) { - if (gap < minimumGap) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - minimumGap = gap; + if (strategy == LOOKUP_CLOSEST_CLOCK) { + if (gap < minimumGap) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + minimumGap = gap; + } + continue; } - continue; + /* + * If strategy is neither LOOKUP_BEST_REFRESH or + * LOOKUP_CLOSEST_CLOCK the required mode has been found. + */ + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + break; } - /* - * If strategy is neither LOOKUP_BEST_REFRESH or - * LOOKUP_CLOSEST_CLOCK the required mode has been found. - */ - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - break; } + if (found) break; } if (!found || bestMode == NULL) return status; @@ -609,7 +620,8 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, modep->ClockIndex = -1; modep->SynthClock = (modep->Clock * MulFactor) / DivFactor; } else { - modep->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor; + modep->Clock = (scrp->clock[clockIndex] * DivFactor) / + MulFactor; modep->ClockIndex = clockIndex; modep->SynthClock = scrp->clock[clockIndex]; if (extraFlags & V_CLKDIV2) { @@ -766,31 +778,6 @@ xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) mode, mode->name, monitor, monitor->id); #endif - if (monitor->DDC) { - xf86MonPtr DDC = (xf86MonPtr)(monitor->DDC); - struct detailed_monitor_section* detMon; - struct monitor_ranges *mon_range; - int i; - - mon_range = NULL; - for (i = 0; i < 4; i++) { - detMon = &DDC->det_mon[i]; - if(detMon->type == DS_RANGES) { - mon_range = &detMon->section.ranges; - } - } - if (mon_range) { - /* mode->Clock in kHz, DDC in MHz */ - if (mon_range->max_clock < 2550 && - mode->Clock / 1000.0 > mon_range->max_clock) { - xf86Msg(X_WARNING, - "(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", - mode->name, monitor->id, - mode->Clock/1000.0, mon_range->max_clock); - } - } - } - /* Some basic mode validity checks */ if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) @@ -845,11 +832,14 @@ xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) ((mode->HSyncEnd - mode->HDisplay) == 80) && ((mode->HSyncEnd - mode->HSyncStart) == 32) && ((mode->VSyncStart - mode->VDisplay) == 3)) { - if (!monitor->reducedblanking) + if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER)) return MODE_NO_REDUCED; } } + if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock)) + return MODE_CLOCK_HIGH; + return MODE_OK; } @@ -1200,6 +1190,58 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) return MODE_OK; } +static int +inferVirtualSize(ScrnInfoPtr scrp, DisplayModePtr modes, int *vx, int *vy) +{ + float aspect = 0.0; + MonPtr mon = scrp->monitor; + int x = 0, y = 0; + DisplayModePtr mode; + + if (!mon) return 0; + + /* + * technically this triggers if _either_ is zero, which is not what EDID + * says, but if only one is zero this is best effort. also we don't + * know that all projectors are 4:3, but we certainly suspect it. + */ + if (!mon->widthmm || !mon->heightmm) + aspect = 4.0/3.0; + else + aspect = (float)mon->widthmm / (float)mon->heightmm; + + /* find the largest M_T_DRIVER mode with that aspect ratio */ + for (mode = modes; mode; mode = mode->next) { + float mode_aspect, metaspect; + if (!(mode->type & (M_T_DRIVER|M_T_USERDEF))) + continue; + mode_aspect = (float)mode->HDisplay / (float)mode->VDisplay; + metaspect = aspect / mode_aspect; + /* 5% slop or so, since we only get size in centimeters */ + if (fabs(1.0 - metaspect) < 0.05) { + if ((mode->HDisplay > x) && (mode->VDisplay > y)) { + x = mode->HDisplay; + y = mode->VDisplay; + } + } + } + + if (!x || !y) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Unable to estimate virtual size\n"); + return 0; + } + + *vx = x; + *vy = y; + + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Estimated virtual size for aspect ratio %.4f is %dx%d\n", + aspect, *vx, *vy); + + return 1; +} + /* * xf86ValidateModes * @@ -1267,11 +1309,11 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, PixmapFormatRec *BankFormat; ClockRangePtr cp; ClockRangesPtr storeClockRanges; - struct monitor_ranges *mon_range = NULL; double targetRefresh = 0.0; int numTimings = 0; range hsync[MAX_HSYNC]; range vrefresh[MAX_VREFRESH]; + Bool inferred_virtual = FALSE; #ifdef DEBUG ErrorF("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n", @@ -1301,166 +1343,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, return -1; } - /* - * Probe monitor so that we can enforce/warn about its limits. - * If one or more DS_RANGES descriptions are present, use the parameters - * that they provide. Otherwise, deduce limits based on the modes that - * are shown as supported via standard and detailed timings. - * - * XXX The full potential of the DDC/EDID data still isn't being tapped. - */ - if (scrp->monitor->DDC) { - MonPtr monitor = scrp->monitor; - xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC); - int i, j; - float hmin = 1e6, hmax = 0.0, vmin = 1e6, vmax = 0.0; - float h; - struct std_timings *t; - struct detailed_timings *dt; - - numTimings = 0; - for (i = 0; i < DET_TIMINGS; i++) { - switch (DDC->det_mon[i].type) { - case DS_RANGES: - mon_range = &DDC->det_mon[i].section.ranges; - hsync[numTimings].lo = mon_range->min_h; - hsync[numTimings].hi = mon_range->max_h; - vrefresh[numTimings].lo = mon_range->min_v; - vrefresh[numTimings].hi = mon_range->max_v; - numTimings++; - break; - - case DS_STD_TIMINGS: - t = DDC->det_mon[i].section.std_t; - for (j = 0; j < 5; j++) { - if (t[j].hsize > 256) { /* sanity check */ - if (t[j].refresh < vmin) - vmin = t[i].refresh; - if (t[j].refresh > vmax) - vmax = t[i].refresh; - /* - * For typical modes this is a reasonable estimate - * of the horizontal sync rate. - */ - h = t[j].refresh * 1.07 * t[j].vsize / 1000.0; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - } - break; - - case DT: - dt = &DDC->det_mon[i].section.d_timings; - if (dt->clock > 15000000) { /* sanity check */ - float v; - h = (float)dt->clock / (dt->h_active + dt->h_blanking); - v = h / (dt->v_active + dt->v_blanking); - h /= 1000.0; - if (dt->interlaced) - v /= 2.0; - - if (v < vmin) - vmin = v; - if (v > vmax) - vmax = v; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - break; - } - - if (numTimings > MAX_HSYNC) - break; - } - - if (numTimings == 0) { - t = DDC->timings2; - for (i = 0; i < STD_TIMINGS; i++) { - if (t[i].hsize > 256) { /* sanity check */ - if (t[i].refresh < vmin) - vmin = t[i].refresh; - if (t[i].refresh > vmax) - vmax = t[i].refresh; - /* - * For typical modes this is a reasonable estimate - * of the horizontal sync rate. - */ - h = t[i].refresh * 1.07 * t[i].vsize / 1000.0; - if (h < hmin) - hmin = h; - if (h > hmax) - hmax = h; - } - } - - if (hmax > 0.0) { - hsync[numTimings].lo = hmin; - hsync[numTimings].hi = hmax; - vrefresh[numTimings].lo = vmin; - vrefresh[numTimings].hi = vmax; - numTimings++; - } - } - - if (numTimings > 0) { - -#ifdef DEBUG - for (i = 0; i < numTimings; i++) { - ErrorF("DDC - Hsync %.1f-%.1f kHz - Vrefresh %.1f-%.1f Hz\n", - hsync[i].lo, hsync[i].hi, - vrefresh[i].lo, vrefresh[i].hi); - } -#endif - -#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE - if (monitor->nHsync > 0) { - for (i = 0; i < monitor->nHsync; i++) { - Bool good = FALSE; - for (j = 0; j < numTimings; j++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * hsync[j].lo <= - monitor->hsync[i].lo && - (1.0 + DDC_SYNC_TOLERANCE) * hsync[j].hi >= - monitor->hsync[i].hi) { - good = TRUE; - break; - } - } - if (!good) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "config file hsync range %g-%gkHz not within DDC " - "hsync ranges.\n", - monitor->hsync[i].lo, monitor->hsync[i].hi); - } - } - } - - if (monitor->nVrefresh > 0) { - for (i = 0; i < monitor->nVrefresh; i++) { - Bool good = FALSE; - for (j = 0; j < numTimings; j++) { - if ((1.0 - DDC_SYNC_TOLERANCE) * vrefresh[j].lo <= - monitor->vrefresh[0].lo && - (1.0 + DDC_SYNC_TOLERANCE) * vrefresh[j].hi >= - monitor->vrefresh[0].hi) { - good = TRUE; - break; - } - } - if (!good) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "config file vrefresh range %g-%gHz not within DDC " - "vrefresh ranges.\n", - monitor->vrefresh[i].lo, monitor->vrefresh[i].hi); - } - } - } - } - } - /* * If requested by the driver, allow missing hsync and/or vrefresh ranges * in the monitor section. @@ -1478,8 +1360,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, scrp->monitor->hsync[i].hi = hsync[i].hi; } } else { - scrp->monitor->hsync[0].lo = 28; - scrp->monitor->hsync[0].hi = 33; + scrp->monitor->hsync[0].lo = 31.5; + scrp->monitor->hsync[0].hi = 37.9; scrp->monitor->nHsync = 1; } type = "default "; @@ -1507,8 +1389,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, scrp->monitor->vrefresh[i].hi = vrefresh[i].hi; } } else { - scrp->monitor->vrefresh[0].lo = 43; - scrp->monitor->vrefresh[0].hi = 72; + scrp->monitor->vrefresh[0].lo = 50; + scrp->monitor->vrefresh[0].hi = 70; scrp->monitor->nVrefresh = 1; } type = "default "; @@ -1624,6 +1506,13 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, virtX = virtualX; virtY = virtualY; scrp->virtualFrom = X_CONFIG; + } else if (!modeNames || !*modeNames) { + /* No virtual size given in the config, try to infer */ + /* XXX this doesn't take m{in,ax}Pitch into account; oh well */ + inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY); + if (inferred_virtual) + linePitch = miScanLineWidth(virtX, virtY, minPitch, apertureSize, + BankFormat, pitchInc); } /* Print clock ranges and scaled clocks */ @@ -1640,7 +1529,7 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, for (p = availModes; p != NULL; p = p->next) { status = xf86InitialCheckModeForDriver(scrp, p, clockRanges, strategy, maxPitch, - virtualX, virtualY); + virtX, virtY); if (status == MODE_OK) { status = xf86CheckModeForMonitor(p, scrp->monitor); @@ -1917,6 +1806,30 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, #undef _VIRTUALX + /* + * If we estimated the virtual size above, we may have filtered away all + * the modes that maximally match that size; scan again to find out and + * fix up if so. + */ + if (inferred_virtual) { + int vx = 0, vy = 0; + for (p = scrp->modes; p; p = p->next) { + if (p->HDisplay > vx && p->VDisplay > vy) { + vx = p->HDisplay; + vy = p->VDisplay; + } + } + if (vx < virtX || vy < virtY) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Shrinking virtual size estimate from %dx%d to %dx%d\n", + virtX, virtY, vx, vy); + virtX = vx; + virtY = vy; + linePitch = miScanLineWidth(vx, vy, linePitch, apertureSize, + BankFormat, pitchInc); + } + } + /* Update the ScrnInfoRec parameters */ scrp->virtualX = virtX; @@ -2139,6 +2052,8 @@ xf86PrintModes(ScrnInfoPtr scrp) prefix = "Built-in mode"; else if (p->type & M_T_DEFAULT) prefix = "Default mode"; + else if (p->type & M_T_DRIVER) + prefix = "Driver mode"; else prefix = "Mode"; if (p->type & M_T_USERDEF) diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h index ae9d9aef4..6e62e52ff 100644 --- a/hw/xfree86/common/xf86str.h +++ b/hw/xfree86/common/xf86str.h @@ -213,6 +213,7 @@ typedef struct { pointer options; pointer DDC; Bool reducedblanking; /* Allow CVT reduced blanking modes? */ + int maxPixClock; /* in kHz, like mode->Clock */ } MonRec, *MonPtr; /* the list of clock ranges */ diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c index 22deca687..a1650bc03 100644 --- a/hw/xfree86/ddc/ddcProperty.c +++ b/hw/xfree86/ddc/ddcProperty.c @@ -1,159 +1,514 @@ -/* ddcProperty.c: Make the DDC monitor information available to clients - * as properties on the root window - * - * Copyright 1999 by Andrew C Aitchison +/* + * Copyright 2006 Luc Verhaegen. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_XORG_CONFIG_H #include #endif -#include -#include "misc.h" #include "xf86.h" -/* #include "xf86_OSproc.h" */ +#include "xf86DDC.h" #include #include "property.h" #include "propertyst.h" #include "xf86DDC.h" +/* + * xf86Mode.c should have a some more DisplayModePtr list handling. + */ +static DisplayModePtr +xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) +{ + if (!Modes) { + if (Additions) + return Additions; + else + return NULL; + } + + if (Additions) { + DisplayModePtr Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + Mode->next = Additions; + Additions->prev = Mode; + } + + return Modes; +} + +static DisplayModePtr +xf86ModeCopy(DisplayModePtr Mode) +{ + DisplayModePtr New; + + if (!Mode) + return NULL; + + New = xnfalloc(sizeof(DisplayModeRec)); + + memcpy(New, Mode, sizeof(DisplayModeRec)); + + New->name = xnfalloc(strlen(Mode->name) + 1); + memcpy(New->name, Mode->name, strlen(Mode->name) + 1); + + /* We ignore privates as DDC code doesn't use it currently */ + return New; +} + +/* + * Temporary. + */ +static void +add(char **p, char *new) +{ + *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); + strcat(*p, " "); + strcat(*p, new); +} + +static void +PrintModeline(int scrnIndex,DisplayModePtr mode) +{ + char tmp[256]; + char *flags = xnfcalloc(1, 1); + + if (mode->HSkew) { + snprintf(tmp, 256, "hskew %i", mode->HSkew); + add(&flags, tmp); + } + if (mode->VScan) { + snprintf(tmp, 256, "vscan %i", mode->VScan); + add(&flags, tmp); + } + if (mode->Flags & V_INTERLACE) add(&flags, "interlace"); + if (mode->Flags & V_CSYNC) add(&flags, "composite"); + if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan"); + if (mode->Flags & V_BCAST) add(&flags, "bcast"); + if (mode->Flags & V_PHSYNC) add(&flags, "+hsync"); + if (mode->Flags & V_NHSYNC) add(&flags, "-hsync"); + if (mode->Flags & V_PVSYNC) add(&flags, "+vsync"); + if (mode->Flags & V_NVSYNC) add(&flags, "-vsync"); + if (mode->Flags & V_PCSYNC) add(&flags, "+csync"); + if (mode->Flags & V_NCSYNC) add(&flags, "-csync"); +#if 0 + if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); +#endif + xf86DrvMsgVerb(scrnIndex, X_INFO, 3, + "Modeline \"%s\" %6.2f %i %i %i %i %i %i %i %i%s\n", + mode->name, mode->Clock/1000., mode->HDisplay, + mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, + mode->VTotal, flags); + xfree(flags); +} + +/* + * TODO: + * - for those with access to the VESA DMT standard; review please. + */ +#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER +#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 + +DisplayModeRec DDCEstablishedModes[17] = { + { MODEPREFIX("800x600"), 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ + { MODEPREFIX("800x600"), 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ + { MODEPREFIX("640x480"), 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ + { MODEPREFIX("640x480"), 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX("640x480"), 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */ + { MODEPREFIX("640x480"), 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX("720x400"), 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */ + { MODEPREFIX("720x400"), 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */ + { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ + { MODEPREFIX("1024x768"), 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX("1024x768"), 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ + { MODEPREFIX("1024x768"), 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ + { MODEPREFIX("1024x768"), 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ + { MODEPREFIX("832x624"), 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */ + { MODEPREFIX("800x600"), 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ + { MODEPREFIX("800x600"), 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ + { MODEPREFIX("1152x864"), 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ +}; + +static DisplayModePtr +DDCModesFromEstablished(int scrnIndex, struct established_timings *timing) +{ + DisplayModePtr Modes = NULL, Mode = NULL; + CARD32 bits = (timing->t1) | (timing->t2 << 8) | + ((timing->t_manu & 0x80) << 9); + int i; + + for (i = 0; i < 17; i++) + if (bits & (0x01 << i)) { + Mode = xf86ModeCopy(&(DDCEstablishedModes[i])); + Modes = xf86ModesAdd(Modes, Mode); + } + + return Modes; +} + +/* + * + */ +static DisplayModePtr +DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing) +{ + 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); + Mode->type = M_T_DRIVER; + Modes = xf86ModesAdd(Modes, Mode); + } + + return Modes; +} + +/* + * + */ +static DisplayModePtr +DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, + int preferred) +{ + DisplayModePtr Mode; + + /* We don't do stereo */ + if (timing->stereo) { + xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We don't handle stereo.\n", + __func__); + return NULL; + } + + /* We only do seperate sync currently */ + if (timing->sync != 0x03) { + xf86DrvMsg(scrnIndex, X_INFO, "%s: %dx%d Warning: We only handle seperate" + " sync.\n", __func__, timing->h_active, timing->v_active); + } + + Mode = xnfalloc(sizeof(DisplayModeRec)); + memset(Mode, 0, sizeof(DisplayModeRec)); + + Mode->name = xnfalloc(10); /* "1234x1234" */ + xf86snprintf(Mode->name, 20, "%dx%d", timing->h_active, + timing->v_active); + + Mode->type = M_T_DRIVER; + if (preferred) + Mode->type |= M_T_PREFERRED; + + Mode->Clock = timing->clock / 1000.0; + + Mode->HDisplay = timing->h_active; + Mode->HSyncStart = timing->h_active + timing->h_sync_off; + Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width; + Mode->HTotal = timing->h_active + timing->h_blanking; + + Mode->VDisplay = timing->v_active; + Mode->VSyncStart = timing->v_active + timing->v_sync_off; + Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width; + Mode->VTotal = timing->v_active + timing->v_blanking; + + /* We ignore h/v_size and h/v_border for now. */ + + if (timing->interlaced) + Mode->Flags |= V_INTERLACE; + + if (timing->misc & 0x02) + Mode->Flags |= V_PHSYNC; + else + Mode->Flags |= V_NHSYNC; + + if (timing->misc & 0x01) + Mode->Flags |= V_PVSYNC; + else + Mode->Flags |= V_NVSYNC; + + return Mode; +} + +/* + * + */ +static void +DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) +{ + DisplayModePtr Mode = Modes; + + if (!Monitor || !Modes) + return; + + /* set up the ranges for scanning through the modes */ + Monitor->nHsync = 1; + Monitor->hsync[0].lo = 1024.0; + Monitor->hsync[0].hi = 0.0; + + Monitor->nVrefresh = 1; + Monitor->vrefresh[0].lo = 1024.0; + Monitor->vrefresh[0].hi = 0.0; + + while (Mode) { + if (!Mode->HSync) + Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); + + if (!Mode->VRefresh) + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); + + if (Mode->HSync < Monitor->hsync[0].lo) + Monitor->hsync[0].lo = Mode->HSync; + + if (Mode->HSync > Monitor->hsync[0].hi) + Monitor->hsync[0].hi = Mode->HSync; + + if (Mode->VRefresh < Monitor->vrefresh[0].lo) + Monitor->vrefresh[0].lo = Mode->VRefresh; + + if (Mode->VRefresh > Monitor->vrefresh[0].hi) + Monitor->vrefresh[0].hi = Mode->VRefresh; + + Mode = Mode->next; + } +} + +/* + * Fill out MonPtr with xf86MonPtr information. + */ +void +xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) +{ + DisplayModePtr Modes = NULL, Mode; + int i, clock; + Bool have_hsync = FALSE, have_vrefresh = FALSE; + int preferred; + + if (!Monitor || !DDC) + return; + + Monitor->DDC = DDC; + + preferred = PREFERRED_TIMING_MODE(DDC->features.msc); + + Monitor->widthmm = 10 * DDC->features.hsize; + Monitor->heightmm = 10 * DDC->features.vsize; + + /* If this is a digital display, then we can use reduced blanking */ + if (DDC->features.input_type) + Monitor->reducedblanking = TRUE; + /* Allow the user to also enable this through config */ + + /* Add established timings */ + Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1); + Modes = xf86ModesAdd(Modes, Mode); + + /* Add standard timings */ + Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2); + Modes = xf86ModesAdd(Modes, Mode); + + /* Skip EDID ranges if they were specified in the config file */ + have_hsync = (Monitor->nHsync != 0); + have_vrefresh = (Monitor->nVrefresh != 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 (clock > Monitor->maxPixClock) + Monitor->maxPixClock = clock; + + break; + case DT: + Mode = DDCModeFromDetailedTiming(scrnIndex, + &DDC->det_mon[i].section.d_timings, + preferred); + preferred = 0; + Modes = xf86ModesAdd(Modes, Mode); + break; + case DS_STD_TIMINGS: + Mode = DDCModesFromStandardTiming(scrnIndex, + DDC->det_mon[i].section.std_t); + Modes = xf86ModesAdd(Modes, Mode); + break; + default: + break; + } + + if (Modes) { + /* Print Modes */ + xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n"); + + Mode = Modes; + while (Mode) { + PrintModeline(scrnIndex, Mode); + Mode = Mode->next; + } + + /* Do we still need ranges to be filled in? */ + if (!Monitor->nHsync || !Monitor->nVrefresh) + DDCGuessRangesFromModes(scrnIndex, Monitor, Modes); + + /* look for last Mode */ + Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + /* add to MonPtr */ + if (Monitor->Modes) { + Monitor->Last->next = Modes; + Modes->prev = Monitor->Last; + Monitor->Last = Mode; + } else { + Monitor->Modes = Modes; + Monitor->Last = Mode; + } + } +} + #define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" #define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" #define VDIF_ATOM_NAME "XFree86_DDC_VDIF_RAWDATA" -Bool -xf86SetDDCproperties(ScrnInfoPtr pScrnInfo, xf86MonPtr DDC) +static void +addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) { - Atom EDID1Atom=-1, EDID2Atom=-1, VDIFAtom=-1; + Atom EDID1Atom=-1, EDID2Atom=-1; CARD8 *EDID1rawdata = NULL; CARD8 *EDID2rawdata = NULL; - int i, ret; - Bool makeEDID1prop = FALSE; - Bool makeEDID2prop = FALSE; - -#ifdef DEBUG - ErrorF("xf86SetDDCproperties(%p, %p)\n", pScrnInfo, DDC); -#endif - - if (pScrnInfo==NULL || pScrnInfo->monitor==NULL || DDC==NULL) { - return FALSE; - } - -#ifdef DEBUG - ErrorF("pScrnInfo->scrnIndex %d\n", pScrnInfo->scrnIndex); - - ErrorF("pScrnInfo->monitor was %p\n", pScrnInfo->monitor); -#endif - - pScrnInfo->monitor->DDC = DDC; + int i, scrnIndex = pScrn->scrnIndex; + Bool makeEDID1prop = FALSE; + Bool makeEDID2prop = FALSE; if (DDC->ver.version == 1) { - makeEDID1prop = TRUE; + makeEDID1prop = TRUE; } else if (DDC->ver.version == 2) { - int checksum1; - int checksum2; - makeEDID2prop = TRUE; + int checksum1; + int checksum2; + makeEDID2prop = TRUE; - /* Some monitors (eg Panasonic PanaSync4) - * report version==2 because they used EDID v2 spec document, - * although they use EDID v1 data structure :-( - * - * Try using checksum to determine when we have such a monitor. - */ - checksum2 = 0; - for (i=0; i<256; i++) { checksum2 += DDC->rawData[i]; } - if ( (checksum2 % 256) != 0 ) { - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v2 checksum failed\n"); - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); - checksum1 = 0; - for (i=0; i<128; i++) { checksum1 += DDC->rawData[i]; } - if ( (checksum1 % 256) == 0 ) { - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "Monitor EDID v1 checksum passed,\n"); - xf86DrvMsg(pScrnInfo->scrnIndex,X_INFO, "XFree86_DDC_EDID1_RAWDATA property created\n"); - makeEDID1prop = TRUE; + /* Some monitors (eg Panasonic PanaSync4) + * report version==2 because they used EDID v2 spec document, + * although they use EDID v1 data structure :-( + * + * Try using checksum to determine when we have such a monitor. + */ + checksum2 = 0; + for (i = 0; i < 256; i++) + checksum2 += DDC->rawData[i]; + if (checksum2 % 256) { + xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); + checksum1 = 0; + for (i = 0; i < 128; i++) + checksum1 += DDC->rawData[i]; + if (!(checksum1 % 256)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Monitor EDID v1 checksum passed,\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID1_RAWDATA property created\n"); + makeEDID1prop = TRUE; + } } - } } else { - xf86DrvMsg(pScrnInfo->scrnIndex, X_PROBED, - "unexpected EDID version %d revision %d\n", - DDC->ver.version, DDC->ver.revision ); + xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", + DDC->ver.version, DDC->ver.revision); + return; } if (makeEDID1prop) { - if ( (EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL ) { - return FALSE; - } + if ((EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL) + return; - EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME), TRUE); - - - for (i=0; i<128; i++) { - EDID1rawdata[i] = DDC->rawData[i]; - } - -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata ); -#endif - - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - EDID1Atom, XA_INTEGER, 8, - 128, (unsigned char *)EDID1rawdata - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + EDID1Atom = MakeAtom(EDID1_ATOM_NAME, sizeof(EDID1_ATOM_NAME), TRUE); + memcpy(EDID1rawdata, DDC->rawData, 128); + xf86RegisterRootWindowProperty(scrnIndex, EDID1Atom, XA_INTEGER, 8, + 128, (unsigned char *)EDID1rawdata); } if (makeEDID2prop) { - if ( (EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL ) { - return FALSE; - } - for (i=0; i<256; i++) { - EDID2rawdata[i] = DDC->rawData[i]; - } + if ((EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL) + return; - EDID2Atom = MakeAtom(EDID2_ATOM_NAME, sizeof(EDID2_ATOM_NAME), TRUE); - -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - EDID2Atom, XA_INTEGER, 8, - 256, (unsigned char *)EDID2rawdata ); -#endif - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - EDID2Atom, XA_INTEGER, 8, - 256, (unsigned char *)EDID2rawdata - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + memcpy(EDID2rawdata, DDC->rawData, 256); + EDID2Atom = MakeAtom(EDID2_ATOM_NAME, sizeof(EDID2_ATOM_NAME), TRUE); + xf86RegisterRootWindowProperty(scrnIndex, EDID2Atom, XA_INTEGER, 8, + 256, (unsigned char *)EDID2rawdata); } +#if 0 if (DDC->vdif) { #define VDIF_DUMMY_STRING "setting dummy VDIF property - please insert correct values\n" -#ifdef DEBUG - ErrorF("xf86RegisterRootWindowProperty %p(%d,%d,%d,%d,%d,%p)\n", - xf86RegisterRootWindowProperty, - pScrnInfo->scrnIndex, - VDIFAtom, XA_STRING, 8, - strlen(VDIF_DUMMY_STRING), VDIF_DUMMY_STRING - ); -#endif - - VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE); - - ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex, - VDIFAtom, XA_STRING, 8, - strlen(VDIF_DUMMY_STRING), - VDIF_DUMMY_STRING - ); - if (ret != Success) - ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret ); + VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE); + xf86RegisterRootWindowProperty(scrnIndex, VDIFAtom, XA_STRING, 8, + strlen(VDIF_DUMMY_STRING), VDIF_DUMMY_STRING); } +#endif +} + +Bool +xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + if (!pScrn || !pScrn->monitor || !DDC) + return FALSE; + + xf86DDCMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); + + addRootWindowProperties(pScrn, DDC); return TRUE; } diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c index a16055491..c58bb2fe1 100644 --- a/hw/xfree86/ddc/interpret_edid.c +++ b/hw/xfree86/ddc/interpret_edid.c @@ -31,6 +31,41 @@ static void get_whitepoint_section(Uchar *, struct whitePoints *); static void get_detailed_timing_section(Uchar*, struct detailed_timings *); static Bool validate_version(int scrnIndex, struct edid_version *); +static void +handle_edid_quirks(xf86MonPtr m) +{ + int i, j; + struct detailed_timings *preferred_timing; + struct monitor_ranges *ranges; + + /* + * max_clock is only encoded in EDID in tens of MHz, so occasionally we + * find a monitor claiming a max of 160 with a mode requiring 162, or + * similar. Strictly we should refuse to round up too far, but let's + * see how well this works. + */ + for (i = 0; i < 4; i++) { + if (m->det_mon[i].type == DS_RANGES) { + ranges = &m->det_mon[i].section.ranges; + for (j = 0; j < 4; j++) { + if (m->det_mon[j].type == DT) { + preferred_timing = &m->det_mon[j].section.d_timings; + if (!ranges->max_clock) continue; /* zero is legal */ + if (ranges->max_clock * 1000000 < preferred_timing->clock) { + xf86Msg(X_WARNING, + "EDID preferred timing clock %.2fMHz exceeds " + "claimed max %dMHz, fixing\n", + preferred_timing->clock / 1.0e6, + ranges->max_clock); + ranges->max_clock = + (preferred_timing->clock+999999)/1000000; + return; + } + } + } + } + } +} xf86MonPtr xf86InterpretEDID(int scrnIndex, Uchar *block) @@ -53,7 +88,9 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) &m->ver); get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon); m->no_sections = (int)*(char *)SECTION(NO_EDID,block); - + + handle_edid_quirks(m); + return (m); error: diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h index fb1083606..5def97a81 100644 --- a/hw/xfree86/ddc/xf86DDC.h +++ b/hw/xfree86/ddc/xf86DDC.h @@ -47,6 +47,9 @@ extern xf86vdifPtr xf86InterpretVdif( CARD8 *c ); +extern void +xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC); + extern Bool xf86SetDDCproperties( ScrnInfoPtr pScreen, xf86MonPtr DDC