xserver: Branch 'master' - 17 commits

Adam Jackson ajax at kemper.freedesktop.org
Wed Nov 8 01:47:26 EET 2006


 dix/globals.c                      |    2 
 hw/xfree86/common/xf86AutoConfig.c |    3 
 hw/xfree86/common/xf86Config.c     |   51 ++-
 hw/xfree86/common/xf86Helper.c     |    6 
 hw/xfree86/common/xf86Mode.c       |  545 ++++++++++++++--------------------
 hw/xfree86/common/xf86str.h        |    1 
 hw/xfree86/ddc/ddcProperty.c       |  585 +++++++++++++++++++++++++++++--------
 hw/xfree86/ddc/interpret_edid.c    |   39 ++
 hw/xfree86/ddc/xf86DDC.h           |    3 
 9 files changed, 797 insertions(+), 438 deletions(-)

New commits:
diff-tree 05f1c302460a14c8fa9a943a12d69adcd3c30d58 (from parents)
Merge: 3e7e0e35094d09e0e764818ed125314be75be01a 46af6d1e953f1eefb6edbba3d29fb9700e42c2bb
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Tue Nov 7 18:42:54 2006 -0500

    Merge branch 'autoconfig-for-7.2'

diff-tree 46af6d1e953f1eefb6edbba3d29fb9700e42c2bb (from 63acf18b7e4ce3a9f7deab3a9088a1c41cab0191)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:28:44 2006 -0400

    Always believe the monitor when it reports a reduced-blanking mode.
    
    CVT reduced blanking modes are typically only seen on digital connections to
    LCDs, but there are some monitors that report them as supported over the
    VGA connector too, which is perfectly legitimate, electrically speaking.

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index ac3fb8c..456331d 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -832,7 +832,7 @@ xf86CheckModeForMonitor(DisplayModePtr m
             ((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;
         }
     }
diff-tree 63acf18b7e4ce3a9f7deab3a9088a1c41cab0191 (from a8f9936f55c5364bb02e8c3187507eb1f70e2ef2)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:26:37 2006 -0400

    In xf86MatchPciInstances, fail gracefully when there's no PCI device at all.
    
    This allows the autoconfig logic to fall through sanely on non-PCI machines,
    which importantly includes Xen virtual machines.

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 851a345..c226bf2 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1635,6 +1635,8 @@ xf86MatchPciInstances(const char *driver
 
     *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-tree a8f9936f55c5364bb02e8c3187507eb1f70e2ef2 (from 81ef1b6d6063c20db4963abf7b7848e235aa4ebb)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:24:41 2006 -0400

    Prefer driver-provided modes when matching name strings to modelines.
    
    Well, kinda.  Strictly we prefer M_T_BUILTIN strongest since those are modes
    where the driver has said it absolutely can't do anything else (VBE).  Then
    we look for user-defined modes, ie, modelines from the config file.  Then
    we consider modes reported by the monitor via EDID.  Finally if nothing has
    matched yet we consider the default mode pool.
    
    Within each of the above-mentioned classes, modes with the M_T_PREFERRED bit
    take priority over other modes in the same class.
    
    This logic ensures that the timings sent to the monitor exactly match the
    timings it reported as supported, which occasionally don't match the numbers
    you might get for that mode from CVT or GTF.

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index a3ef420..ac3fb8c 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -445,6 +445,17 @@ xf86LookupMode(ScrnInfoPtr scrp, Display
     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);
 
@@ -464,143 +475,141 @@ xf86LookupMode(ScrnInfoPtr scrp, Display
 	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;
+		}
 
-	    /* 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;
-	    }
+		/* Skip over previously considered modes */
+		if (p->prev)
+		    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) {
-		found = TRUE;
-		if (strategy != LOOKUP_BEST_REFRESH) {
-		    bestMode = p;
-		    DivFactor = cp->ClockDivFactor;
-		    MulFactor = cp->ClockMulFactor;
-		    ModePrivFlags = cp->PrivFlags;
-		    break;
+		if (p->type & M_T_BUILTIN) {
+		    return xf86HandleBuiltinMode(scrp, p,modep, clockRanges,
+			    allowDiv2);
 		}
-		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;
+
+		/* 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;
 		}
-		continue;
-	    }
 
-	    /*
-	     * Clock is in range, so if it is not a programmable clock, find
-	     * a matching clock.
-	     */
+		/*
+		 * 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) {
+		    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;
+		}
 
-	    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;
+		/*
+		 * Clock is in range, so if it is not a programmable clock, find
+		 * a matching clock.
+		 */
 
-	    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;
+		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;
 		}
-		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;
+		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;
+		    }
+		    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;
+		    }
+		    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;
@@ -611,7 +620,8 @@ xf86LookupMode(ScrnInfoPtr scrp, Display
 	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) {
diff-tree 81ef1b6d6063c20db4963abf7b7848e235aa4ebb (from 43d9edd31e31b33b9da4a50d8ab05004881c8d5a)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:18:58 2006 -0400

    Mark EDID modes as driver modes.  Infer virtual size from driver modes.
    
    This allows the server to guess an appropriate initial virtual size and
    resolution.  The heuristic is to select the largest driver-reported mode
    that matches the monitor's physical aspect ratio.  We revalidate this
    estimate after mode validation, since we may have filtered away all
    modes that would fill that size.
    
    Also, the EDID preferred timing is now marked as M_T_PREFERRED as well.

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index c66a3fb..a3ef420 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -45,6 +45,7 @@
 #include "globals.h"
 #include "xf86.h"
 #include "xf86Priv.h"
+#include "edid.h"
 
 static void
 printModeRejectMessage(int index, DisplayModePtr p, int status)
@@ -55,6 +56,8 @@ printModeRejectMessage(int index, Displa
 	type = "built-in ";
     else if (p->type & M_T_DEFAULT)
 	type = "default ";
+    else if (p->type & M_T_DRIVER)
+	type = "driver ";
     else
 	type = "";
 
@@ -1177,6 +1180,58 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp,
     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
  *
@@ -1248,6 +1303,7 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
     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",
@@ -1440,6 +1496,13 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
 	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 */
@@ -1456,7 +1519,7 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
 	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);
@@ -1733,6 +1796,30 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
 
 #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;
@@ -1955,6 +2042,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/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index 59873fa..a1650bc 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -127,9 +127,8 @@ PrintModeline(int scrnIndex,DisplayModeP
 /*
  * TODO:
  *  - for those with access to the VESA DMT standard; review please.
- *  - swap M_T_DEFAULT for M_T_EDID_...
  */
-#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DEFAULT
+#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] = {
@@ -182,6 +181,7 @@ DDCModesFromStandardTiming(int scrnIndex
         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);
         }
 
@@ -192,7 +192,8 @@ DDCModesFromStandardTiming(int scrnIndex
  *
  */
 static DisplayModePtr
-DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing)
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
+			  int preferred)
 {
     DisplayModePtr Mode;
 
@@ -205,9 +206,8 @@ DDCModeFromDetailedTiming(int scrnIndex,
     
     /* We only do seperate sync currently */
     if (timing->sync != 0x03) {
-         xf86DrvMsg(scrnIndex, X_INFO, "%s: Ignoring: We only handle seperate"
-                    " sync.\n", __func__);
-         return NULL;
+         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));
@@ -217,7 +217,9 @@ DDCModeFromDetailedTiming(int scrnIndex,
     xf86snprintf(Mode->name, 20, "%dx%d", timing->h_active,
                  timing->v_active);
     
-    Mode->type = M_T_DEFAULT; /* get ourselves a nice type of our own */
+    Mode->type = M_T_DRIVER;
+    if (preferred)
+	Mode->type |= M_T_PREFERRED;
     
     Mode->Clock = timing->clock / 1000.0;
     
@@ -302,12 +304,15 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
     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;
     
@@ -367,7 +372,9 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
             break;
         case DT:
             Mode = DDCModeFromDetailedTiming(scrnIndex, 
-                                             &DDC->det_mon[i].section.d_timings);
+                                             &DDC->det_mon[i].section.d_timings,
+					     preferred);
+	    preferred = 0;
             Modes = xf86ModesAdd(Modes, Mode);
             break;
         case DS_STD_TIMINGS:
diff-tree 43d9edd31e31b33b9da4a50d8ab05004881c8d5a (from 739224d05eb4f356c9cab9dcb8a44a8d78287765)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:09:02 2006 -0400

    Attempt to add the 'mouse' driver in more situations.
    
    Always add a mouse driver instance configured to send core events, unless
    a core pointer already exists using either the mouse or void drivers.  This
    handles the laptop case where the config file only specifies, say,
    synaptics, which causes the touchpad to work but not the pointing stick.
    We don't double-instantiate the mouse driver to avoid the mouse moving twice
    as fast, and we skip this logic when the user asked for a void core pointer
    since that probably means they want to run with no pointer at all.

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index fe55c8c..dbe158e 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -1450,12 +1450,13 @@ checkCoreInputDevices(serverLayoutPtr se
     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
@@ -1607,6 +1608,35 @@ checkCoreInputDevices(serverLayoutPtr se
 	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 = "<default pointer>";
+	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. */
diff-tree 739224d05eb4f356c9cab9dcb8a44a8d78287765 (from beac2bf1e48e6b77dbf7d95f086abc5abcd90cf0)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:03:32 2006 -0400

    Load the default module set when no Module section is given in the config.
    
    Also, synchronize that list with the list for the pseudoconfig file used
    when starting with no config file.  These really need to be better unified.

diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index 4dcc997..4f6a98a 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 f89db67..fe55c8c 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 **optli
 	        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
diff-tree beac2bf1e48e6b77dbf7d95f086abc5abcd90cf0 (from 71a15a7d5721073eccb3a275f353b3aa584c0d68)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:01:13 2006 -0400

    Expand the default sync ranges to be large enough for 800x600 at 60.

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index c3b016f..c66a3fb 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -1294,8 +1294,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
 		    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 ";
@@ -1323,8 +1323,8 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
 		    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 ";
diff-tree 71a15a7d5721073eccb3a275f353b3aa584c0d68 (from 7939c8dfb7c7bed4febcdc12922fb2e17619ea36)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 19:00:10 2006 -0400

    Publish the raw EDID block as a property on the root window.
    
    This was removed in the patch for bug #5386, but is still useful.

diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index c76afbc..59873fa 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -27,6 +27,10 @@
 
 #include "xf86.h"
 #include "xf86DDC.h"
+#include <X11/Xatom.h>
+#include "property.h"
+#include "propertyst.h"
+#include "xf86DDC.h"
 
 /*
  * xf86Mode.c should have a some more DisplayModePtr list handling.
@@ -407,9 +411,88 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
     }
 }
 
-/*
- * Empty shell that keeps most drivers happy.
- */
+#define EDID1_ATOM_NAME         "XFree86_DDC_EDID1_RAWDATA"
+#define EDID2_ATOM_NAME         "XFree86_DDC_EDID2_RAWDATA"
+#define VDIF_ATOM_NAME          "XFree86_DDC_VDIF_RAWDATA"
+
+static void
+addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC)
+{
+    Atom EDID1Atom=-1, EDID2Atom=-1;
+    CARD8 *EDID1rawdata = NULL;
+    CARD8 *EDID2rawdata = NULL;
+    int i, scrnIndex = pScrn->scrnIndex;
+    Bool makeEDID1prop = FALSE;
+    Bool makeEDID2prop = FALSE;
+
+    if (DDC->ver.version == 1) {
+	makeEDID1prop = TRUE;
+    } else if (DDC->ver.version == 2) {
+	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) {
+	    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(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;
+
+	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;
+
+	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"
+
+	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)
 {
@@ -418,5 +501,7 @@ xf86SetDDCproperties(ScrnInfoPtr pScrn, 
 
     xf86DDCMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC);
 
+    addRootWindowProperties(pScrn, DDC);
+
     return TRUE;
 }
diff-tree 7939c8dfb7c7bed4febcdc12922fb2e17619ea36 (from 72af975f9c8de0ff6796f1ce4b76dcf841d21e99)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:57:57 2006 -0400

    Bump the default pixel depth to 24, and default bpp to 32.

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index c7d3fae..851a345 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -430,11 +430,11 @@ xf86AddPixFormat(ScrnInfoPtr pScrn, int 
 #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
diff-tree 72af975f9c8de0ff6796f1ce4b76dcf841d21e99 (from d05e0a97bb704a4986cf638487205da759c4ce17)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:56:34 2006 -0400

    Fix up EDID blocks where the max pixclock exceeds the preferred mode clock.
    
    Base EDID only lets you specify the maximum dotclock in tens of MHz, which
    is too fuzzy for some monitors.  1600x1200 at 60 is just over 160MHz, but if
    the monitor really can't handle any mode at 170MHz, then 160 is more
    correct.  Fix up the EDID block before the driver can see it in this case,
    so we don't spuriously reject modes.

diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index a160554..c58bb2f 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
 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 *
 			   &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-tree d05e0a97bb704a4986cf638487205da759c4ce17 (from 334f7db9f653113d5d46236911d7de2ec4173f28)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:49:12 2006 -0400

    Enable DPMS by default.

diff --git a/dix/globals.c b/dix/globals.c
index fc77ca7..f86c602 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-tree 334f7db9f653113d5d46236911d7de2ec4173f28 (from ced46e17777b635df9371c4cfaec3f8968b4dbcf)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:46:10 2006 -0400

    Allow hsync and vsync ranges to be overridden independently again.

diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index 7f078ec..c76afbc 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -297,6 +297,7 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
 {
     DisplayModePtr Modes = NULL, Mode;
     int i, clock;
+    Bool have_hsync = FALSE, have_vrefresh = FALSE;
     
     if (!Monitor || !DDC)
         return;
@@ -319,25 +320,41 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
     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 (Monitor->nHsync && Monitor->nVrefresh) {
-                xf86DrvMsg(scrnIndex, X_INFO, "Ignoring EDID Ranges. Using"
-                           " configured ranges.\n");
-                break;
-            }
-
-            xf86DrvMsg(scrnIndex, X_INFO, "Using EDID ranges info for Monitor"
-                       " timing.\n");
-            Monitor->nHsync = 1;
-            Monitor->hsync[0].lo = DDC->det_mon[i].section.ranges.min_h;
-            Monitor->hsync[0].hi = DDC->det_mon[i].section.ranges.max_h;
-            
-            Monitor->nVrefresh = 1;
-            Monitor->vrefresh[0].lo = DDC->det_mon[i].section.ranges.min_v;
-            Monitor->vrefresh[0].hi = DDC->det_mon[i].section.ranges.max_v;
+	    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)
diff-tree ced46e17777b635df9371c4cfaec3f8968b4dbcf (from d89fee68d0e49211871cd9eb3893ed55c1d478a6)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:41:59 2006 -0400

    Record all standard timings from EDID as modes, instead of just the first five.

diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index ba8aaf8..7f078ec 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -174,7 +174,7 @@ DDCModesFromStandardTiming(int scrnIndex
     DisplayModePtr Modes = NULL, Mode = NULL;
     int i;
     
-    for (i = 0; i < 5; 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);
diff-tree d89fee68d0e49211871cd9eb3893ed55c1d478a6 (from fa8ef7166839a7435e0017683f3e3c7f7904b285)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:41:15 2006 -0400

    Record the maximum dot clock of the monitor, and filter by it.

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 87b8a0b..f89db67 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -2201,6 +2201,7 @@ configMonitor(MonPtr monitorp, XF86ConfM
     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/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index ff04583..c3b016f 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -824,6 +824,9 @@ xf86CheckModeForMonitor(DisplayModePtr m
         }
     }
 
+    if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock))
+	return MODE_CLOCK_HIGH;
+
     return MODE_OK;
 }
 
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index ae9d9ae..6e62e52 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 a4f4f4e..ba8aaf8 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -296,7 +296,7 @@ void
 xf86DDCMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
 {
     DisplayModePtr Modes = NULL, Mode;
-    int i;
+    int i, clock;
     
     if (!Monitor || !DDC)
         return;
@@ -339,6 +339,10 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
             Monitor->vrefresh[0].lo = DDC->det_mon[i].section.ranges.min_v;
             Monitor->vrefresh[0].hi = DDC->det_mon[i].section.ranges.max_v;
 
+	    clock = DDC->det_mon[i].section.ranges.max_clock * 1000;
+	    if (clock > Monitor->maxPixClock)
+		Monitor->maxPixClock = clock;
+
             break;
         case DT:
             Mode = DDCModeFromDetailedTiming(scrnIndex, 
diff-tree fa8ef7166839a7435e0017683f3e3c7f7904b285 (from 511c60bc7399b07c267d686a969880e5ec92408a)
Author: Adam Jackson <ajax at benzedrine.nwnk.net>
Date:   Thu Sep 14 18:33:00 2006 -0400

    Don't translate monitor gamma to X gamma.
    
    The X gamma is used to set the output ramp of the card.  Setting a 2.2 output
    gamma going into a 2.2 monitor gives an effective gamma of 4.84, which is
    very much not what you want.

diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index ed7fb16..a4f4f4e 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -303,12 +303,6 @@ xf86DDCMonitorSet(int scrnIndex, MonPtr 
 
     Monitor->DDC = DDC;
 
-    if (DDC->features.gamma > 0.0) {
-        Monitor->gamma.red = DDC->features.gamma;
-        Monitor->gamma.green = DDC->features.gamma;
-        Monitor->gamma.blue = DDC->features.gamma;
-    }
-
     Monitor->widthmm = 10 * DDC->features.hsize;
     Monitor->heightmm = 10 * DDC->features.vsize;
     
diff-tree 511c60bc7399b07c267d686a969880e5ec92408a (from 05231e336db8f959c15dda518641976f061df1a6)
Author: Luc Verhaegen <libv at skynet.be>
Date:   Thu Sep 14 18:30:36 2006 -0400

    Bug #5386: Synthesize modelines from EDID data.

diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index cd57e99..ff04583 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -45,7 +45,6 @@
 #include "globals.h"
 #include "xf86.h"
 #include "xf86Priv.h"
-#include "xf86DDC.h"
 
 static void
 printModeRejectMessage(int index, DisplayModePtr p, int status)
@@ -766,31 +765,6 @@ xf86CheckModeForMonitor(DisplayModePtr m
 	   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)
@@ -1267,7 +1241,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
     PixmapFormatRec *BankFormat;
     ClockRangePtr cp;
     ClockRangesPtr storeClockRanges;
-    struct monitor_ranges *mon_range = NULL;
     double targetRefresh = 0.0;
     int numTimings = 0;
     range hsync[MAX_HSYNC];
@@ -1302,166 +1275,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, Disp
     }
 
     /*
-     * 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.
      */
diff --git a/hw/xfree86/ddc/ddcProperty.c b/hw/xfree86/ddc/ddcProperty.c
index 22deca6..ed7fb16 100644
--- a/hw/xfree86/ddc/ddcProperty.c
+++ b/hw/xfree86/ddc/ddcProperty.c
@@ -1,159 +1,407 @@
-/* ddcProperty.c: Make the DDC monitor information available to clients
- * as properties on the root window
- * 
- * Copyright 1999 by Andrew C Aitchison <A.C.Aitchison at dpmms.cam.ac.uk>
+/*
+ * 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 <xorg-config.h>
 #endif
 
-#include <string.h>
-#include "misc.h"
 #include "xf86.h"
-/* #include "xf86_OSproc.h" */
-#include <X11/Xatom.h>
-#include "property.h"
-#include "propertyst.h"
 #include "xf86DDC.h"
 
-#define EDID1_ATOM_NAME         "XFree86_DDC_EDID1_RAWDATA"
-#define EDID2_ATOM_NAME         "XFree86_DDC_EDID2_RAWDATA"
-#define VDIF_ATOM_NAME          "XFree86_DDC_VDIF_RAWDATA"
+/*
+ * 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;
+    }
 
-Bool
-xf86SetDDCproperties(ScrnInfoPtr pScrnInfo, xf86MonPtr DDC)
+    if (Additions) {
+        DisplayModePtr Mode = Modes;
+
+        while (Mode->next)
+            Mode = Mode->next;
+        
+        Mode->next = Additions;
+        Additions->prev = Mode;
+    }
+
+    return Modes;
+}
+
+static DisplayModePtr
+xf86ModeCopy(DisplayModePtr Mode)
 {
-    Atom EDID1Atom=-1, EDID2Atom=-1, VDIFAtom=-1;
-    CARD8 *EDID1rawdata = NULL;
-    CARD8 *EDID2rawdata = NULL;
-    int  i, ret;
-    Bool  makeEDID1prop = FALSE;
-    Bool  makeEDID2prop = FALSE;
+    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);
 
-#ifdef DEBUG
-    ErrorF("xf86SetDDCproperties(%p, %p)\n", pScrnInfo, DDC);
+    /* 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);
+}
 
-    if (pScrnInfo==NULL || pScrnInfo->monitor==NULL || DDC==NULL) {
-      return FALSE;
+/*
+ * TODO:
+ *  - for those with access to the VESA DMT standard; review please.
+ *  - swap M_T_DEFAULT for M_T_EDID_...
+ */
+#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DEFAULT
+#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 at 60Hz */
+    { MODEPREFIX("800x600"),    36000,  800,  824,  896, 1024, 0,  600,  601,  603,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 56Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  656,  720,  840, 0,  480,  481,  484,  500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 75Hz */
+    { MODEPREFIX("640x480"),    31500,  640,  664,  704,  832, 0,  480,  489,  491,  520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 72Hz */
+    { MODEPREFIX("640x480"),    30240,  640,  704,  768,  864, 0,  480,  483,  486,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 67Hz */
+    { MODEPREFIX("640x480"),    25200,  640,  656,  752,  800, 0,  480,  490,  492,  525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480 at 60Hz */
+    { MODEPREFIX("720x400"),    35500,  720,  738,  846,  900, 0,  400,  421,  423,  449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400 at 88Hz */
+    { MODEPREFIX("720x400"),    28320,  720,  738,  846,  900, 0,  400,  412,  414,  449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400 at 70Hz */
+    { MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024 at 75Hz */
+    { MODEPREFIX("1024x768"),   78800, 1024, 1040, 1136, 1312, 0,  768,  769,  772,  800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768 at 75Hz */
+    { MODEPREFIX("1024x768"),   75000, 1024, 1048, 1184, 1328, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 70Hz */
+    { MODEPREFIX("1024x768"),   65000, 1024, 1048, 1184, 1344, 0,  768,  771,  777,  806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768 at 60Hz */
+    { MODEPREFIX("1024x768"),   44900, 1024, 1032, 1208, 1264, 0,  768,  768,  776,  817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768 at 43Hz */
+    { MODEPREFIX("832x624"),    57284,  832,  864,  928, 1152, 0,  624,  625,  628,  667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624 at 75Hz */
+    { MODEPREFIX("800x600"),    49500,  800,  816,  896, 1056, 0,  600,  601,  604,  625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 75Hz */
+    { MODEPREFIX("800x600"),    50000,  800,  856,  976, 1040, 0,  600,  637,  643,  666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600 at 72Hz */
+    { MODEPREFIX("1152x864"),  108000, 1152, 1216, 1344, 1600, 0,  864,  865,  868,  900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864 at 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 < 5; i++)
+        if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
+            Mode =  xf86CVTMode(timing[i].hsize, timing[i].vsize,
+                                timing[i].refresh, FALSE, FALSE);
+            Modes = xf86ModesAdd(Modes, Mode);
+        }
+
+    return Modes;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing)
+{
+    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: Ignoring: We only handle seperate"
+                    " sync.\n", __func__);
+         return NULL;
     }
+    
+    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_DEFAULT; /* get ourselves a nice type of our own */
+    
+    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;
+}
 
-#ifdef DEBUG
-    ErrorF("pScrnInfo->scrnIndex %d\n", pScrnInfo->scrnIndex);
+/*
+ *
+ */
+static void
+DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
+{
+    DisplayModePtr Mode = Modes;
 
-    ErrorF("pScrnInfo->monitor was %p\n", pScrnInfo->monitor);
-#endif
+    if (!Monitor || !Modes)
+        return;
 
-    pScrnInfo->monitor->DDC = DDC;
+    /* set up the ranges for scanning through the modes */
+    Monitor->nHsync = 1;
+    Monitor->hsync[0].lo = 1024.0;
+    Monitor->hsync[0].hi = 0.0;
 
-    if (DDC->ver.version == 1) {
-      makeEDID1prop = TRUE;
-    } else if (DDC->ver.version == 2) {
-      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;
-	}
-      }
-    } else {
-     xf86DrvMsg(pScrnInfo->scrnIndex, X_PROBED,
-		"unexpected EDID version %d revision %d\n",
-		DDC->ver.version, DDC->ver.revision );      
-    }
-
-    if (makeEDID1prop) {
-      if ( (EDID1rawdata = xalloc(128*sizeof(CARD8)))==NULL ) {
-	return FALSE;
-      }
-
-      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
+    Monitor->nVrefresh = 1;
+    Monitor->vrefresh[0].lo = 1024.0;
+    Monitor->vrefresh[0].hi = 0.0;
 
-      ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex,
-					   EDID1Atom, XA_INTEGER, 8, 
-					   128, (unsigned char *)EDID1rawdata
-					   );
-      if (ret != Success)
-      ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret );
-    } 
-
-    if (makeEDID2prop) {
-      if ( (EDID2rawdata = xalloc(256*sizeof(CARD8)))==NULL ) {
-	return FALSE;
-      }
-      for (i=0; i<256; i++) {
-	EDID2rawdata[i] = DDC->rawData[i];
-      }
-
-      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 );
-    }
-
-    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
+    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));
 
-      VDIFAtom = MakeAtom(VDIF_ATOM_NAME, sizeof(VDIF_ATOM_NAME), TRUE);
+        if (Mode->HSync < Monitor->hsync[0].lo)
+            Monitor->hsync[0].lo = Mode->HSync;
 
-      ret = xf86RegisterRootWindowProperty(pScrnInfo->scrnIndex,
-					   VDIFAtom, XA_STRING, 8, 
-					   strlen(VDIF_DUMMY_STRING),
-					   VDIF_DUMMY_STRING 
-					   );
-      if (ret != Success)
-      ErrorF("xf86RegisterRootWindowProperty returns %d\n", ret );
+        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;
+    
+    if (!Monitor || !DDC)
+        return;
+
+    Monitor->DDC = DDC;
+
+    if (DDC->features.gamma > 0.0) {
+        Monitor->gamma.red = DDC->features.gamma;
+        Monitor->gamma.green = DDC->features.gamma;
+        Monitor->gamma.blue = DDC->features.gamma;
     }
 
+    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);
+
+    /* Go through the detailed monitor sections */
+    for (i = 0; i < DET_TIMINGS; i++)
+        switch (DDC->det_mon[i].type) {
+        case DS_RANGES:
+            if (Monitor->nHsync && Monitor->nVrefresh) {
+                xf86DrvMsg(scrnIndex, X_INFO, "Ignoring EDID Ranges. Using"
+                           " configured ranges.\n");
+                break;
+            }
+
+            xf86DrvMsg(scrnIndex, X_INFO, "Using EDID ranges info for Monitor"
+                       " timing.\n");
+            Monitor->nHsync = 1;
+            Monitor->hsync[0].lo = DDC->det_mon[i].section.ranges.min_h;
+            Monitor->hsync[0].hi = DDC->det_mon[i].section.ranges.max_h;
+            
+            Monitor->nVrefresh = 1;
+            Monitor->vrefresh[0].lo = DDC->det_mon[i].section.ranges.min_v;
+            Monitor->vrefresh[0].hi = DDC->det_mon[i].section.ranges.max_v;
+
+            break;
+        case DT:
+            Mode = DDCModeFromDetailedTiming(scrnIndex, 
+                                             &DDC->det_mon[i].section.d_timings);
+            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;
+        }
+    }
+}
+
+/*
+ * Empty shell that keeps most drivers happy.
+ */
+Bool
+xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC)
+{
+    if (!pScrn || !pScrn->monitor || !DDC)
+        return FALSE;
+
+    xf86DDCMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC);
+
     return TRUE;
 }
diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h
index fb10836..5def97a 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



More information about the xorg-commit mailing list