--- xf86-video-vesa-1.3.0/src/vesa.h.validmode 2006-11-30 16:04:02.000000000 -0500
+++ xf86-video-vesa-1.3.0/src/vesa.h 2007-03-20 14:39:31.000000000 -0400
@@ -108,7 +108,7 @@
CARD32 *pal, *savedPal;
CARD8 *fonts;
xf86MonPtr monitor;
- Bool shadowFB, primary;
+ Bool shadowFB, primary, strict_validation;
CARD32 windowAoffset;
/* Don't override the default refresh rate. */
Bool defaultRefresh;
--- xf86-video-vesa-1.3.0/src/vesa.c.validmode 2007-01-24 19:34:19.000000000 -0500
+++ xf86-video-vesa-1.3.0/src/vesa.c 2007-03-20 14:39:31.000000000 -0400
@@ -273,6 +273,88 @@
xf86PrintChipsets(VESA_NAME, "driver for VESA chipsets", VESAChipsets);
}
+static VESAPtr
+VESAGetRec(ScrnInfoPtr pScrn)
+{
+ if (!pScrn->driverPrivate)
+ pScrn->driverPrivate = xcalloc(sizeof(VESARec), 1);
+
+ return ((VESAPtr)pScrn->driverPrivate);
+}
+
+static ModeStatus
+VESAValidMode(int scrn, DisplayModePtr p, Bool flag, int pass)
+{
+ static int warned = 0;
+ int found = 0;
+ ScrnInfoPtr pScrn = xf86Screens[scrn];
+ VESAPtr pVesa = VESAGetRec(pScrn);
+ MonPtr mon = pScrn->monitor, vesamon = pVesa->monitor;
+ ModeStatus ret;
+ DisplayModePtr mode;
+ float v;
+
+ pVesa = VESAGetRec(pScrn);
+
+ if (pass != MODECHECK_FINAL) {
+ if (!warned) {
+ xf86DrvMsg(scrn, X_WARNING, "VESAValidMode called unexpectedly\n");
+ warned = 1;
+ }
+ return MODE_OK;
+ }
+
+ /*
+ * This is suboptimal. We pass in just the barest description of a mode
+ * we can get away with to VBEValidateModes, so it can't really throw
+ * out anything we give it. But we need to filter the list so that we
+ * don't populate the mode list with things the monitor can't do.
+ *
+ * So first off, if this isn't a mode we handed to the server (ie,
+ * M_T_BUILTIN), then we know we can't do it.
+ */
+ if (!(p->type & M_T_BUILTIN))
+ return MODE_NOMODE;
+
+ /*
+ * Next, walk through the mode list from DDC (if any) and look for a
+ * matching resolution. Only do this on the first try though; on the
+ * second VBEValidateModes, let things through if they fit at all.
+ */
+ if (pVesa->strict_validation) {
+ if (pScrn->monitor->DDC) {
+ for (mode = pScrn->monitor->Modes; mode; mode = mode->next) {
+ if (mode->type & M_T_DRIVER &&
+ mode->HDisplay == p->HDisplay &&
+ mode->VDisplay == p->VDisplay) {
+ found = 1;
+ break;
+ }
+ if (mode == pScrn->monitor->Last)
+ break;
+ }
+ if (!found)
+ return MODE_NOMODE;
+ }
+ }
+
+ /*
+ * Finally, walk through the vsync rates 1Hz at a time looking for a mode
+ * that will fit. This is assuredly a terrible way to do this, but
+ * there's no obvious method for computing a mode of a given size that
+ * will pass xf86CheckModeForMonitor.
+ */
+ for (v = mon->vrefresh[0].lo; v <= mon->vrefresh[0].hi; v++) {
+ mode = xf86CVTMode(p->HDisplay, p->VDisplay, v, 0, 0);
+ ret = xf86CheckModeForMonitor(mode, mon);
+ xfree(mode);
+ if (ret == MODE_OK)
+ break;
+ }
+
+ return ret;
+}
+
/*
* This function is called once, at the start of the first server generation to
* do a minimal probe for supported hardware.
@@ -318,6 +400,7 @@
pScrn->PreInit = VESAPreInit;
pScrn->ScreenInit = VESAScreenInit;
pScrn->SwitchMode = VESASwitchMode;
+ pScrn->ValidMode = VESAValidMode;
pScrn->AdjustFrame = VESAAdjustFrame;
pScrn->EnterVT = VESAEnterVT;
pScrn->LeaveVT = VESALeaveVT;
@@ -391,15 +474,6 @@
return (int)CHIP_VESA_GENERIC;
}
-static VESAPtr
-VESAGetRec(ScrnInfoPtr pScrn)
-{
- if (!pScrn->driverPrivate)
- pScrn->driverPrivate = xcalloc(sizeof(VESARec), 1);
-
- return ((VESAPtr)pScrn->driverPrivate);
-}
-
static void
VESAFreeRec(ScrnInfoPtr pScrn)
{
@@ -595,6 +669,7 @@
VBESetModeNames(pScrn->modePool);
+ pVesa->strict_validation = TRUE;
i = VBEValidateModes(pScrn, NULL, pScrn->display->modes,
NULL, NULL, 0, 2048, 1, 0, 2048,
pScrn->display->virtualX,
@@ -602,6 +677,20 @@
pVesa->mapSize, LOOKUP_BEST_REFRESH);
if (i <= 0) {
+ DisplayModePtr mode;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No valid modes left. Trying less strict filter...\n");
+ for (mode = pScrn->monitor->Modes; mode; mode = mode->next)
+ mode->status = MODE_OK;
+ pVesa->strict_validation = FALSE;
+ i = VBEValidateModes(pScrn, NULL, pScrn->display->modes,
+ NULL, NULL, 0, 2048, 1, 0, 2048,
+ pScrn->display->virtualX,
+ pScrn->display->virtualY,
+ pVesa->mapSize, LOOKUP_BEST_REFRESH);
+ }
+
+ if (i <= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n");
vbeFree(pVesa->pVbe);
return (FALSE);