xf86-video-intel: Branch 'modesetting' - src/i830_crt.c src/i830_display.c src/i830_driver.c src/i830_dvo.c src/i830.h src/i830_lvds.c src/i830_modes.c src/i830_randr.c src/i830_sdvo.c src/i830_tv.c src/i830_xf86Modes.c src/i830_xf86Modes.h

Eric Anholt anholt at kemper.freedesktop.org
Wed Nov 1 22:24:20 EET 2006


 src/i830.h           |    2 
 src/i830_crt.c       |   41 ++
 src/i830_display.c   |   25 +
 src/i830_driver.c    |   64 ----
 src/i830_dvo.c       |    5 
 src/i830_lvds.c      |   39 ++
 src/i830_modes.c     |  766 ++++++++++-----------------------------------------
 src/i830_randr.c     |   19 -
 src/i830_sdvo.c      |   22 +
 src/i830_tv.c        |    2 
 src/i830_xf86Modes.c |   53 +++
 src/i830_xf86Modes.h |    6 
 12 files changed, 332 insertions(+), 712 deletions(-)

New commits:
diff-tree fb94c1210966f7875e5f034f10ea31c06c502c3a (from f30d7f912f36b110c3af7dc795e35456593781ab)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Nov 1 12:23:50 2006 -0800

    Move mode lists from per-pipe to per-output.
    
    This should let RandR do the right thing in exposing the modes to userland.
    
    As a side effect of getting this working, the SDVO pixel clock range code
    was fixed and the mode valid tests for various outputs got extended.  Also,
    LVDS grew a get_modes for the fixed panel mode.
    
    Note that we now no longer do automatic enabling of outputs at xrandr -s 0,
    hotkey, or VT switch.  That will be left to generic RandR code later.  Also,
    generic modes and user-defined modes are once again not validated into the
    lists, so this is a regression there.

diff --git a/src/i830.h b/src/i830.h
index 5915a17..a4dc4ba 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -485,7 +485,6 @@ typedef struct _I830Rec {
    int availablePipes;
    /* [0] is display plane A, [1] is display plane B. */
    int planeEnabled[MAX_DISPLAY_PIPES];
-   MonPtr pipeMon[MAX_DISPLAY_PIPES];
    DisplayModeRec pipeCurMode[MAX_DISPLAY_PIPES];
 
    /* Driver phase/state information */
@@ -694,6 +693,7 @@ DisplayModePtr i830GetGTF(int h_pixels, 
 
 /* i830_modes.c */
 int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
+void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
 DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
 
 /* i830_randr.c */
diff --git a/src/i830_crt.c b/src/i830_crt.c
index bd0099a..407ebe3 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -31,7 +31,7 @@
 
 #include "xf86.h"
 #include "i830.h"
-
+#include "i830_xf86Modes.h"
 static void
 i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
 {
@@ -80,6 +80,12 @@ static int
 i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
 		    DisplayModePtr pMode)
 {
+    if (pMode->Flags & V_DBLSCAN)
+	return MODE_NO_DBLESCAN;
+
+    if (pMode->Clock > 400000 || pMode->Clock < 25000)
+	return MODE_CLOCK_RANGE;
+
     return MODE_OK;
 }
 
@@ -273,6 +279,37 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830O
     return OUTPUT_STATUS_UNKNOWN;
 }
 
+static DisplayModePtr
+i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    DisplayModePtr modes;
+    MonRec fixed_mon;
+
+    modes = i830_ddc_get_modes(pScrn, output);
+    if (modes != NULL)
+	return modes;
+
+    if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED)
+	return NULL;
+
+    /* We've got a potentially-connected monitor that we can't DDC.  Return a
+     * fixed set of VESA plus user modes for a presumed multisync monitor with
+     * some reasonable limits.
+     */
+    fixed_mon.nHsync = 1;
+    fixed_mon.hsync[0].lo = 31.0;
+    fixed_mon.hsync[0].hi = 100.0;
+    fixed_mon.nVrefresh = 1;
+    fixed_mon.vrefresh[0].lo = 50.0;
+    fixed_mon.vrefresh[0].hi = 70.0;
+
+    modes = i830xf86DuplicateModes(pScrn, pScrn->monitor->Modes);
+    i830xf86ValidateModesSync(pScrn, modes, &fixed_mon);
+    i830xf86PruneInvalidModes(pScrn, &modes, TRUE);
+
+    return modes;
+}
+
 void
 i830_crt_init(ScrnInfoPtr pScrn)
 {
@@ -286,7 +323,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
     pI830->output[pI830->num_outputs].detect = i830_crt_detect;
-    pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
+    pI830->output[pI830->num_outputs].get_modes = i830_crt_get_modes;
 
     /* Set up the DDC bus. */
     I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
diff --git a/src/i830_display.c b/src/i830_display.c
index 3151fd1..b3019f8 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -260,8 +260,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
 }
 
 /**
- * In the current world order, there is a list of per-pipe modes, which may or
- * may not include the mode that was asked to be set by XFree86's mode
+ * In the current world order, there are lists of modes per output, which may
+ * or may not include the mode that was asked to be set by XFree86's mode
  * selection.  Find the closest one, in the following preference order:
  *
  * - Equality
@@ -272,21 +272,32 @@ static DisplayModePtr
 i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    DisplayModePtr pBest = NULL, pScan;
+    DisplayModePtr pBest = NULL, pScan = NULL;
+    int i;
+
+    /* Assume that there's only one output connected to the given CRTC. */
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].pipe == pipe &&
+	    !pI830->output[i].disabled &&
+	    pI830->output[i].probed_modes != NULL)
+	{
+	    pScan = pI830->output[i].probed_modes;
+	}
+    }
 
     /* If the pipe doesn't have any detected modes, just let the system try to
      * spam the desired mode in.
      */
-    if (pI830->pipeMon[pipe] == NULL) {
+    if (pScan == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "No pipe mode list for pipe %d,"
 		   "continuing with desired mode\n", pipe);
 	return pMode;
     }
 
-    assert(pScan->VRefresh != 0.0);
-    for (pScan = pI830->pipeMon[pipe]->Modes; pScan != NULL;
-	 pScan = pScan->next) {
+    for (; pScan != NULL; pScan = pScan->next) {
+	assert(pScan->VRefresh != 0.0);
+
 	/* If there's an exact match, we're done. */
 	if (I830ModesEqual(pScan, pMode)) {
 	    pBest = pMode;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2c7eca7..7c15174 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -788,55 +788,6 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
 }
 
 static void
-I830DetectMonitors(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   int i;
-
-   if (!pI830->ddc2)
-      return;
-
-   for (i=0; i<pI830->num_outputs; i++) {
-      switch (pI830->output[i].type) {
-      case I830_OUTPUT_ANALOG:
-      case I830_OUTPUT_LVDS:
-	 /* for an analog/LVDS output, just do DDC */
-	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						    pI830->output[i].pDDCBus);
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC %s %d, %08lX\n",
-		    i830_output_type_names[pI830->output[i].type], i,
-		    pI830->output[i].pDDCBus->DriverPrivate.uval);
-	 xf86PrintEDID(pI830->output[i].MonInfo);
-	 break;
-      case I830_OUTPUT_DVO:
-	 /* check for DDC */
-	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						    pI830->output[i].pDDCBus);
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
-		    pI830->output[i].pDDCBus->DriverPrivate.uval);
-	 xf86PrintEDID(pI830->output[i].MonInfo);
-      break;
-      case I830_OUTPUT_SDVO:
-	 pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,
-						    pI830->output[i].pDDCBus);
-
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08lX\n", i,
-		    pI830->output[i].pDDCBus->DriverPrivate.uval);
-	 xf86PrintEDID(pI830->output[i].MonInfo);
-	 break;
-      case I830_OUTPUT_UNUSED:
-	 break;
-      default:
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Unknown or unhandled output device at %d\n", i);
-	 break;
-      }
-   }
-}
-
-static void
 PreInitCleanup(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1333,21 +1284,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
 
-   I830DetectMonitors(pScrn);
-
-   /* Walk from the end so we'll happen to hit SDVO first, if we found some. An
-    * SDVO device is probably a DFP, and so probably pickier than (say) a CRT
-    * that we might find early in the list.  This hackery will go away when we
-    * start doing independent per-head mode selection.
-    */
-   for (i = pI830->num_outputs - 1; i >= 0; i--) {
-     if (pI830->output[i].MonInfo) {
-       pScrn->monitor->DDC = pI830->output[i].MonInfo;
-       xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
-       break;
-     }
-   }
-
    pI830->MonType1 = PIPE_NONE;
    pI830->MonType2 = PIPE_NONE;
    pI830->specifiedMonitor = FALSE;
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index c788e4f..31fb76b 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -96,6 +96,11 @@ static int
 i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
 		    DisplayModePtr pMode)
 {
+    if (pMode->Flags & V_DBLSCAN)
+	return MODE_NO_DBLESCAN;
+
+    /* XXX: Validate clock range */
+
     if (output->i2c_drv->vid_rec->ModeValid(output->i2c_drv->dev_priv, pMode))
 	return MODE_OK;
     else
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 4b89903..7b9fe63 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -189,6 +189,39 @@ i830_lvds_detect(ScrnInfoPtr pScrn, I830
     return OUTPUT_STATUS_CONNECTED;
 }
 
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static DisplayModePtr
+i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr modes, new;
+    char stmp[32];
+
+    modes = i830_ddc_get_modes(pScrn, output);
+    if (modes != NULL)
+	return modes;
+
+    new             = xnfcalloc(1, sizeof (DisplayModeRec));
+    sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
+    new->name       = xnfalloc(strlen(stmp) + 1);
+    strcpy(new->name, stmp);
+    new->HDisplay   = pI830->PanelXRes;
+    new->VDisplay   = pI830->PanelYRes;
+    new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
+    new->HSyncEnd   = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
+    new->HTotal     = new->HSyncEnd + 1;
+    new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
+    new->VSyncEnd   = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
+    new->VTotal     = new->VSyncEnd + 1;
+    new->Clock      = pI830->panel_fixed_clock;
+
+    new->type       = M_T_PREFERRED;
+
+    return new;
+}
+
 void
 i830_lvds_init(ScrnInfoPtr pScrn)
 {
@@ -235,11 +268,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
     pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
     pI830->output[pI830->num_outputs].detect = i830_lvds_detect;
-    /* This will usually return NULL on laptop panels, which is no good.
-     * We need to construct a mode from the fixed panel info, and return a copy
-     * of that when DDC is unavailable.
-     */
-    pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
+    pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 1ba1def..d6866ad 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -162,27 +162,6 @@ I830PrintModes(ScrnInfoPtr scrp)
     } while (p != NULL && p != scrp->modes);
 }
 
-/**
- * Allocates and returns a copy of pMode, including pointers within pMode.
- */
-static DisplayModePtr
-I830DuplicateMode(DisplayModePtr pMode)
-{
-    DisplayModePtr pNew;
-
-    pNew = xnfalloc(sizeof(DisplayModeRec));
-    *pNew = *pMode;
-    pNew->next = NULL;
-    pNew->prev = NULL;
-    if (pNew->name == NULL) {
-	i830xf86SetModeDefaultName(pMode);
-    } else {
-	pNew->name = xnfstrdup(pMode->name);
-    }
-
-    return pNew;
-}
-
 /* This function will sort all modes according to their resolution.
  * Highest resolution first.
  */
@@ -244,7 +223,7 @@ I830GetVESAEstablishedMode(ScrnInfoPtr p
 	    pMode->VDisplay == est_timings[i].vsize &&
 	    fabs(i830xf86ModeVRefresh(pMode) - est_timings[i].refresh) < 1.0)
 	{
-	    DisplayModePtr pNew = I830DuplicateMode(pMode);
+	    DisplayModePtr pNew = i830xf86DuplicateMode(pMode);
 	    i830xf86SetModeDefaultName(pNew);
 	    pNew->VRefresh = i830xf86ModeVRefresh(pMode);
 	    return pNew;
@@ -391,141 +370,6 @@ i830GetDDCModes(ScrnInfoPtr pScrn, xf86M
     return first;
 }
 
-/**
- * This function returns a default mode for flat panels using the timing
- * information provided by the BIOS.
- */
-static DisplayModePtr
-i830FPNativeMode(ScrnInfoPtr pScrn)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   DisplayModePtr  new;
-   char            stmp[32];
-
-   if (pI830->PanelXRes == 0 || pI830->PanelYRes == 0)
-      return NULL;
-
-   /* Add native panel size */
-   new             = xnfcalloc(1, sizeof (DisplayModeRec));
-   sprintf(stmp, "%dx%d", pI830->PanelXRes, pI830->PanelYRes);
-   new->name       = xnfalloc(strlen(stmp) + 1);
-   strcpy(new->name, stmp);
-   new->HDisplay   = pI830->PanelXRes;
-   new->VDisplay   = pI830->PanelYRes;
-   new->HSyncStart = pI830->panel_fixed_hactive + pI830->panel_fixed_hsyncoff;
-   new->HSyncEnd   = new->HSyncStart + pI830->panel_fixed_hsyncwidth;
-   new->HTotal     = new->HSyncEnd + 1;
-   new->VSyncStart = pI830->panel_fixed_vactive + pI830->panel_fixed_vsyncoff;
-   new->VSyncEnd   = new->VSyncStart + pI830->panel_fixed_vsyncwidth;
-   new->VTotal     = new->VSyncEnd + 1;
-   new->Clock      = pI830->panel_fixed_clock;
-
-   new->type       = M_T_PREFERRED;
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	      "No valid mode specified, force to native mode\n");
-
-   return new;
-}
-
-/**
- * FP automatic modelist creation routine for using panel fitting.
- *
- * Constructs modes for any resolution less than the panel size specified by the
- * user, with the user flag set, plus standard VESA mode sizes without the user
- * flag set (for randr).
- *
- * Modes will be faked to use GTF parameters, even though at the time of being
- * programmed into the LVDS they'll end up being forced to the panel's fixed
- * mode.
- *
- * \return doubly-linked list of modes.
- */
-static DisplayModePtr
-i830GetLVDSModes(ScrnInfoPtr pScrn, char **ppModeName)
-{
-   I830Ptr pI830 = I830PTR(pScrn);
-   DisplayModePtr  last       = NULL;
-   DisplayModePtr  new        = NULL;
-   DisplayModePtr  first      = NULL;
-   DisplayModePtr  p, tmp;
-   int             count      = 0;
-   int             i, width, height;
-
-   /* We have a flat panel connected to the primary display, and we
-    * don't have any DDC info.
-    */
-   for (i = 0; ppModeName[i] != NULL; i++) {
-
-      if (sscanf(ppModeName[i], "%dx%d", &width, &height) != 2)
-	 continue;
-
-      /* Note: We allow all non-standard modes as long as they do not
-       * exceed the native resolution of the panel.  Since these modes
-       * need the internal RMX unit in the video chips (and there is
-       * only one per card), this will only apply to the primary head.
-       */
-      if (width < 320 || width > pI830->PanelXRes ||
-	 height < 200 || height > pI830->PanelYRes) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n",
- 		    ppModeName[i]);
-	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		    "Valid modes must be between 320x200-%dx%d\n",
-		    pI830->PanelXRes, pI830->PanelYRes);
-	 continue;
-      }
-
-      new = i830GetGTF(width, height, 60.0, FALSE, FALSE);
-      new->type |= M_T_DEFAULT;
-
-      new->next       = NULL;
-      new->prev       = last;
-
-      if (last)
-	 last->next = new;
-      last = new;
-      if (!first)
-	 first = new;
-
-      count++;
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		 "Valid mode using panel fitting: %s\n", new->name);
-   }
-
-   /* If the user hasn't specified modes, add the native mode */
-   if (!count) {
-      new = i830FPNativeMode(pScrn);
-      if (new) {
-	 I830xf86SortModes(new, &first, &last);
-	 count = 1;
-      }
-   }
-
-   /* add in all default vesa modes smaller than panel size, used for randr */
-   for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) {
-      if ((p->HDisplay <= pI830->PanelXRes) && (p->VDisplay <= pI830->PanelYRes)) {
-	 tmp = first;
-	 while (tmp) {
-	    if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break;
-	       tmp = tmp->next;
-	 }
-	 if (!tmp) {
-	    new = i830GetGTF(p->HDisplay, p->VDisplay, 60.0, FALSE, FALSE);
-	    new->type |= M_T_DEFAULT;
-
-	    I830xf86SortModes(new, &first, &last);
-
-	    count++;
-	 }
-      }
-   }
-
-   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	      "Total number of valid FP mode(s) found: %d\n", count);
-
-   return first;
-}
-
 static DisplayModePtr
 i830GetModeListTail(DisplayModePtr pModeList)
 {
@@ -562,330 +406,6 @@ i830AppendModes(ScrnInfoPtr pScrn, Displ
 }
 
 /**
- * Duplicates every mode in the given list and returns a pointer to the first
- * mode.
- *
- * \param modeList doubly-linked mode list
- */
-static DisplayModePtr
-i830DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
-{
-    DisplayModePtr first = NULL, last = NULL;
-    DisplayModePtr mode;
-
-    for (mode = modeList; mode != NULL; mode = mode->next) {
-	DisplayModePtr new;
-
-	new = I830DuplicateMode(mode);
-
-	/* Insert pNew into modeList */
-	if (last) {
-	    last->next = new;
-	    new->prev = last;
-	} else {
-	    first = new;
-	    new->prev = NULL;
-	}
-	new->next = NULL;
-	last = new;
-    }
-
-    return first;
-}
-
-static MonPtr
-i830GetDDCMonitor(ScrnInfoPtr pScrn, I2CBusPtr pDDCBus)
-{
-    xf86MonPtr ddc;
-    MonPtr mon;
-    DisplayModePtr userModes;
-    int i;
-
-    ddc = xf86DoEDID_DDC2(pScrn->scrnIndex, pDDCBus);
-
-    if (ddc == NULL)
-	return NULL;
-
-    mon = xnfcalloc(1, sizeof(*mon));
-    mon->Modes = i830GetDDCModes(pScrn, ddc);
-    mon->DDC = ddc;
-
-    for (i = 0; i < DET_TIMINGS; i++) {
-	struct detailed_monitor_section *det_mon = &ddc->det_mon[i];
-
-	switch (ddc->det_mon[i].type) {
-	case DS_RANGES:
-	    mon->hsync[mon->nHsync].lo = det_mon->section.ranges.min_h;
-	    mon->hsync[mon->nHsync].hi = det_mon->section.ranges.max_h;
-	    mon->nHsync++;
-	    mon->vrefresh[mon->nVrefresh].lo = det_mon->section.ranges.min_v;
-	    mon->vrefresh[mon->nVrefresh].hi = det_mon->section.ranges.max_v;
-	    mon->nVrefresh++;
-	    break;
-	default:
-	    /* We probably don't care about trying to contruct ranges around
-	     * modes specified by DDC.
-	     */
-	    break;
-	}
-    }
-
-    /* Add in VESA standard and user modelines, and do additional validation
-     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
-     */
-    userModes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
-
-    i830xf86ValidateModesSync(pScrn, userModes, mon);
-    i830xf86PruneInvalidModes(pScrn, &userModes, TRUE);
-
-    i830AppendModes(pScrn, &mon->Modes, userModes);
-
-    mon->Last = i830GetModeListTail(mon->Modes);
-
-    return mon;
-}
-
-static MonPtr
-i830GetLVDSMonitor(ScrnInfoPtr pScrn)
-{
-    MonPtr mon;
-    DisplayModePtr  mode;
-
-    mon = xnfcalloc(1, sizeof(*mon));
-    mon->Modes = i830GetLVDSModes(pScrn, pScrn->display->modes);
-    mon->Last = i830GetModeListTail(mon->Modes);
-    /*
-     * Find the preferred mode, use the display resolution to compute
-     * the effective monitor size
-     */
-    for (mode = mon->Modes; mode; mode = mode->next)
-	if (mode->type & M_T_PREFERRED)
-	    break;
-    if (!mode)
-	mode = mon->Modes;
-    if (mode)
-    {
-#define MMPERINCH 25.4
-	mon->widthmm = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH;
-	mon->heightmm = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH;
-    }
-	
-    return mon;
-}
-
-static MonPtr
-i830GetConfiguredMonitor(ScrnInfoPtr pScrn)
-{
-    MonPtr mon;
-
-    mon = xnfcalloc(1, sizeof(*mon));
-    memcpy(mon, pScrn->monitor, sizeof(*mon));
-
-    if (pScrn->monitor->id != NULL)
-	mon->id = xnfstrdup(pScrn->monitor->id);
-    if (pScrn->monitor->vendor != NULL)
-	mon->vendor = xnfstrdup(pScrn->monitor->vendor);
-    if (pScrn->monitor->model != NULL)
-	mon->model = xnfstrdup(pScrn->monitor->model);
-
-    /* Use VESA standard and user modelines, and do additional validation
-     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
-     */
-    mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
-    i830xf86ValidateModesSync(pScrn, mon->Modes, mon);
-    i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE);
-    mon->Last = i830GetModeListTail(mon->Modes);
-
-    return mon;
-}
-
-static MonPtr
-i830GetDefaultMonitor(ScrnInfoPtr pScrn)
-{
-    MonPtr mon;
-
-    mon = xnfcalloc(1, sizeof(*mon));
-
-    mon->id = xnfstrdup("Unknown Id");
-    mon->vendor = xnfstrdup("Unknown Vendor");
-    mon->model = xnfstrdup("Unknown Model");
-
-    mon->nHsync = 1;
-    mon->hsync[0].lo = 31.0;
-    mon->hsync[0].hi = 100.0;
-    mon->nVrefresh = 1;
-    mon->vrefresh[0].lo = 50.0;
-    mon->vrefresh[0].hi = 70.0;
-    mon->widthmm = 400;
-    mon->heightmm = 300;
-    /* Use VESA standard and user modelines, and do additional validation
-     * on them beyond what pipe config will do (x/y/pitch, clocks, flags)
-     */
-    mon->Modes = i830DuplicateModes(pScrn, pScrn->monitor->Modes);
-    i830xf86ValidateModesSync(pScrn, mon->Modes, mon);
-    i830xf86PruneInvalidModes(pScrn, &mon->Modes, TRUE);
-    mon->Last = i830GetModeListTail(mon->Modes);
-
-    return mon;
-}
-
-static void
-i830FreeMonitor(ScrnInfoPtr pScrn, MonPtr mon)
-{
-    while (mon->Modes != NULL)
-	xf86DeleteMode(&mon->Modes, mon->Modes);
-    xfree(mon->id);
-    xfree(mon->vendor);
-    xfree(mon->model);
-    xfree(mon->DDC);
-    xfree(mon);
-}
-
-/**
- * Performs probing of modes available on the output connected to the given
- * pipe.
- *
- * We do not support multiple outputs per pipe (since the cases for that are
- * sufficiently rare we can't imagine the complexity being worth it), so
- * the pipe is a sufficient specifier.
- */
-static void
-I830ReprobePipeModeList(ScrnInfoPtr pScrn, int pipe)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    int output_index = -1;
-    int i;
-    int outputs;
-    DisplayModePtr pMode;
-    MonPtr old_mon = pI830->pipeMon[pipe];
-
-    if (pipe == 0)
-	outputs = pI830->operatingDevices & 0xff;
-    else
-	outputs = (pI830->operatingDevices >> 8) & 0xff;
-
-    for (i = 0; i < pI830->num_outputs; i++) {
-	switch (pI830->output[i].type) {
-	case I830_OUTPUT_ANALOG:
-	    if (outputs & PIPE_CRT) {
-		output_index = i;
-	    }
-	    break;
-	case I830_OUTPUT_LVDS:
-	    if (outputs & PIPE_LFP) {
-		output_index = i;
-	    }
-	    break;
-	case I830_OUTPUT_DVO:
-	    if (outputs & PIPE_DFP) {
-		output_index = i;
-	    }
-	    break;
-	case I830_OUTPUT_SDVO:
-	    if (outputs & PIPE_DFP) {
-		output_index = i;
-	    }
-	    break;
-	}
-    }
-    /* XXX: If there's no output associated with the pipe, bail for now. */
-    if (output_index == -1)
-	return;
-
-    if (outputs & PIPE_LFP) {
-	pI830->pipeMon[pipe] = i830GetLVDSMonitor(pScrn);
-    } else if (pI830->output[output_index].pDDCBus != NULL) {
-	pI830->pipeMon[pipe] =
-	    i830GetDDCMonitor(pScrn, pI830->output[output_index].pDDCBus);
-    }
-    /* If DDC didn't work (or the flat panel equivalent), then see if we can
-     * detect if a monitor is at least plugged in.  If we can't tell that one
-     * is plugged in, then assume that it is.
-     */
-    if (pI830->pipeMon[pipe] == NULL) {
-	enum detect_status detect;
-
-	detect = pI830->output[output_index].detect(pScrn,
-		&pI830->output[output_index]);
-
-	switch (pI830->output[output_index].type) {
-	case I830_OUTPUT_SDVO:
-	    if (detect == OUTPUT_STATUS_CONNECTED)
-		pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
-	    break;
-	case I830_OUTPUT_ANALOG:
-	    if (detect == OUTPUT_STATUS_CONNECTED) {
-/*		if (pipe == pI830->pipe)
-		    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
-		else */
-		    pI830->pipeMon[pipe] = i830GetDefaultMonitor(pScrn);
-	    }
-	    break;
-	default:
-	    pI830->pipeMon[pipe] = i830GetConfiguredMonitor(pScrn);
-	    break;
-	}
-    }
-
-#ifdef DEBUG_REPROBE
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing probed modes for pipe %d\n",
-	       pipe);
-#endif
-    if (pI830->pipeMon[pipe] != NULL) {
-	int minclock, maxclock;
-
-	switch (pI830->output[output_index].type) {
-	case I830_OUTPUT_SDVO:
-	    minclock = 25000;
-	    maxclock = 165000;
-	case I830_OUTPUT_LVDS:
-	case I830_OUTPUT_ANALOG:
-	default:
-	    minclock = 25000;
-	    maxclock = 400000;
-	}
-
-	i830xf86ValidateModesFlags(pScrn, pI830->pipeMon[pipe]->Modes,
-				   V_INTERLACE);
-	i830xf86ValidateModesClocks(pScrn, pI830->pipeMon[pipe]->Modes,
-				    &minclock, &maxclock, 1);
-
-	i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, TRUE);
-
-	/* silently prune modes down to ones matching the user's configuration.
-	 */
-	i830xf86ValidateModesUserConfig(pScrn, pI830->pipeMon[pipe]->Modes);
-	i830xf86PruneInvalidModes(pScrn, &pI830->pipeMon[pipe]->Modes, FALSE);
-
-	for (pMode = pI830->pipeMon[pipe]->Modes; pMode != NULL;
-	     pMode = pMode->next)
-	{
-	    /* The code to choose the best mode per pipe later on will require
-	     * VRefresh to be set.
-	     */
-	    pMode->VRefresh = i830xf86ModeVRefresh(pMode);
-	    I830xf86SetModeCrtc(pMode, INTERLACE_HALVE_V);
-#ifdef DEBUG_REPROBE
-	    PrintModeline(pScrn->scrnIndex, pMode);
-#endif
-	}
-    }
-
-    if (old_mon != NULL && pI830->pipeMon[pipe] == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Failed to probe output on pipe %d, disabling output at next "
-		   "mode switch\n", pipe);
-	if (pipe == 0)
-	    pI830->operatingDevices &= ~0x00ff;
-	else
-	    pI830->operatingDevices &= ~0xff00;
-    }
-
-    if (old_mon != NULL)
-	i830FreeMonitor(pScrn, old_mon);
-}
-
-/**
  * This function removes a mode from a list of modes.  It should probably be
  * moved to xf86Mode.c.
  *
@@ -918,28 +438,18 @@ I830xf86DeleteModeFromList(DisplayModePt
 	    mode->next->prev = mode->prev;
     }
 }
-    
-/**
- * Probes for video modes on attached otuputs, and assembles a list to insert
- * into pScrn.
- *
- * \param first_time indicates that the memory layout has already been set up,
- * 	  so displayWidth, virtualX, and virtualY shouldn't be touched.
- *
- * A SetMode must follow this call in order for operatingDevices to match the
- * hardware's state, in case we detect a new output device.  
- */
-int
-I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
+
+void
+i830_reprobe_output_modes(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int pipe, i;
-    DisplayModePtr saved_mode, last;
-    Bool pipes_reconfigured = FALSE;
-    int originalVirtualX, originalVirtualY;
+    Bool properties_set = FALSE;
+    int i;
 
     /* Re-probe the list of modes for each output. */
     for (i = 0; i < pI830->num_outputs; i++) {
+	DisplayModePtr mode;
+
 	while (pI830->output[i].probed_modes != NULL) {
 	    xf86DeleteMode(&pI830->output[i].probed_modes,
 			   pI830->output[i].probed_modes);
@@ -947,103 +457,66 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 
 	pI830->output[i].probed_modes =
 	    pI830->output[i].get_modes(pScrn, &pI830->output[i]);
-    }
-
-    for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
-	I830ReprobePipeModeList(pScrn, pipe);
-    }
 
-    /* If we've got a spare pipe, try to detect if a new CRT has been plugged
-     * in.
-     */
-    if ((pI830->operatingDevices & (PIPE_CRT | (PIPE_CRT << 8))) == 0) {
-	if ((pI830->operatingDevices & 0xff) == PIPE_NONE) {
-	    pI830->operatingDevices |= PIPE_CRT;
-	    I830ReprobePipeModeList(pScrn, 0);
-	    if (pI830->pipeMon[0] == NULL) {
-		/* No new output found. */
-		pI830->operatingDevices &= ~PIPE_CRT;
-	    } else {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Enabled new CRT on pipe A\n");
-		pipes_reconfigured = TRUE;
-		/* Clear the current mode, so we reprogram the pipe for sure. */
-		memset(&pI830->pipeCurMode[0], 0, sizeof(pI830->pipeCurMode[0]));
-	    }
-	} else if (((pI830->operatingDevices >> 8) & 0xff) == PIPE_NONE) {
-	    pI830->operatingDevices |= PIPE_CRT << 8;
-	    I830ReprobePipeModeList(pScrn, 1);
-	    if (pI830->pipeMon[1] == NULL) {
-		/* No new output found. */
-		pI830->operatingDevices &= ~(PIPE_CRT << 8);
-	    } else {
-		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-			   "Enabled new CRT on pipe B\n");
-		pipes_reconfigured = TRUE;
-		/* Clear the current mode, so we reprogram the pipe for sure. */
-		memset(&pI830->pipeCurMode[1], 0, sizeof(pI830->pipeCurMode[1]));
-	    }
-	}
-    }
-
-    if ((pI830->pipeMon[0] == NULL || pI830->pipeMon[0]->Modes == NULL) &&
-	(pI830->pipeMon[1] == NULL || pI830->pipeMon[1]->Modes == NULL))
-    {
-	FatalError("No modes found on either pipe\n");
-    }
-
-    if (first_time) {
-	int maxX = -1, maxY = -1;
-
-	/* Set up a virtual size that will cover any clone mode we'd want to set
-	 * for either of the two pipes.
+	/* Set the DDC properties to whatever first output has DDC information.
 	 */
-	for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
-	    MonPtr mon = pI830->pipeMon[pipe];
-	    DisplayModePtr mode;
-
-	    if (mon == NULL)
-		continue;
-
-	    for (mode = mon->Modes; mode != NULL; mode = mode->next) {
-		if (mode->HDisplay > maxX)
-		    maxX = mode->HDisplay;
-		if (mode->VDisplay > maxY)
-		    maxY = mode->VDisplay;
-	    }
+	if (pI830->output[i].MonInfo != NULL && !properties_set) {
+	    xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
+	    properties_set = TRUE;
 	}
-	/* let the user specify a bigger virtual size if they like */
-	if (pScrn->display->virtualX > maxX)
-	    maxX = pScrn->display->virtualX;
-	if (pScrn->display->virtualY > maxY)
-	    maxY = pScrn->display->virtualY;
-	pScrn->virtualX = maxX;
-	pScrn->virtualY = maxY;
-	pScrn->displayWidth = (maxX + 63) & ~63;
-    }
 
-    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
-
-    /* Disable modes that are larger than the virtual size we decided on
-     * initially.
-     */
-    if (!first_time) {
-	for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
-	    MonPtr mon = pI830->pipeMon[pipe];
-	    DisplayModePtr mode;
+	if (pI830->output[i].probed_modes != NULL) {
+	    /* silently prune modes down to ones matching the user's
+	     * configuration.
+	     */
+	    i830xf86ValidateModesUserConfig(pScrn,
+					    pI830->output[i].probed_modes);
+	    i830xf86PruneInvalidModes(pScrn, &pI830->output[i].probed_modes,
+				      FALSE);
+	}
 
-	    if (mon == NULL)
-		continue;
+#ifdef DEBUG_REPROBE
+	if (pI830->output[i].probed_modes != NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Printing probed modes for output %s\n",
+		       i830_output_type_names[pI830->output[i].type]);
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "No remaining probed modes for output %s\n",
+		       i830_output_type_names[pI830->output[i].type]);
+	}
+#endif
+	for (mode = pI830->output[i].probed_modes; mode != NULL;
+	     mode = mode->next)
+	{
+	    /* The code to choose the best mode per pipe later on will require
+	     * VRefresh to be set.
+	     */
+	    mode->VRefresh = i830xf86ModeVRefresh(mode);
+	    I830xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
 
-	    for (mode = mon->Modes; mode != NULL; mode = mode->next)
-	    {
-		if (mode->HDisplay > originalVirtualX)
-		    mode->status = MODE_VIRTUAL_X;
-		if (mode->VDisplay > originalVirtualY)
-		    mode->status = MODE_VIRTUAL_Y;
-	    }
+#ifdef DEBUG_REPROBE
+	    PrintModeline(pScrn->scrnIndex, mode);
+#endif
 	}
     }
+}
+
+/**
+ * Constructs pScrn->modes from the output mode lists.
+ *
+ * Currently it only takes one output's mode list and stuffs it into the
+ * XFree86 DDX mode list while trimming it for root window size.
+ *
+ * This should be obsoleted by RandR 1.2 hopefully.
+ */
+static void
+i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    DisplayModePtr saved_mode, last;
+    int originalVirtualX, originalVirtualY;
+    int i;
 
     /* Remove the current mode from the modelist if we're re-validating, so we
      * can find a new mode to map ourselves to afterwards.
@@ -1057,30 +530,34 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     while (pScrn->modes != NULL)
 	xf86DeleteMode(&pScrn->modes, pScrn->modes);
 
-    /* Set pScrn->modes to the mode list for the an arbitrary head.
+    /* Set pScrn->modes to the mode list for an arbitrary output.
      * pScrn->modes should only be used for XF86VidMode now, which we don't
      * care about enough to make some sort of unioned list.
      */
-    if (pI830->pipeMon[1] != NULL) {
-	pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[1]->Modes);
-    } else {
-	pScrn->modes = i830DuplicateModes(pScrn, pI830->pipeMon[0]->Modes);
-    }
-    if (pScrn->modes == NULL) {
-	FatalError("No modes found\n");
+    for (i = 0; i < pI830->num_outputs; i++) {
+	if (pI830->output[i].probed_modes != NULL) {
+	    pScrn->modes =
+		i830xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
+	    break;
+	}
     }
 
-    /* Don't let pScrn->modes have modes larger than the max root window size.
-     * We don't really care about the monitors having it, particularly since we
-     * eventually want randr to be able to move to those sizes.
+    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
+
+    /* Disable modes in the XFree86 DDX list that are larger than the current
+     * virtual size.
      */
     i830xf86ValidateModesSize(pScrn, pScrn->modes,
 			      originalVirtualX, originalVirtualY,
 			      pScrn->displayWidth);
 
-    /* Strip out anything bad that we threw out for virtualX. */
+    /* Strip out anything that we threw out for virtualX/Y. */
     i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
 
+    if (pScrn->modes == NULL) {
+	FatalError("No modes left for XFree86 DDX\n");
+    }
+
     /* For some reason, pScrn->modes is circular, unlike the other mode lists.
      * How great is that?
      */
@@ -1088,25 +565,70 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
     last->next = pScrn->modes;
     pScrn->modes->prev = last;
 
-#if DEBUG_REPROBE
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Modes post revalidate\n");
-    do {
-	DisplayModePtr pMode;
-
-	for (pMode = pScrn->modes; ; pMode = pMode->next) {
-	    PrintModeline(pScrn->scrnIndex, pMode);
-	    if (pMode->next == pScrn->modes)
-		break;
-	}
-    } while (0);
-#endif
-
     /* Save a pointer to the previous current mode.  We can't reset
      * pScrn->currentmode, because we rely on xf86SwitchMode's shortcut not
      * happening so we can hot-enable devices at SwitchMode.  We'll notice this
      * case at SwitchMode and free the saved mode.
      */
     pI830->savedCurrentMode = saved_mode;
+}
+
+/**
+ * Takes the output mode lists and decides the default root window size
+ * and framebuffer pitch.
+ */
+static void
+i830_set_default_screen_size(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int maxX = -1, maxY = -1;
+    int i;
+
+    /* Set up a virtual size that will cover any clone mode we'd want to
+     * set for the currently-connected outputs.
+     */
+    for (i = 0; i < pI830->num_outputs; i++) {
+	DisplayModePtr mode;
+
+	for (mode = pI830->output[i].probed_modes; mode != NULL;
+	     mode = mode->next)
+	{
+	    if (mode->HDisplay > maxX)
+		maxX = mode->HDisplay;
+	    if (mode->VDisplay > maxY)
+		maxY = mode->VDisplay;
+	}
+    }
+    /* let the user specify a bigger virtual size if they like */
+    if (pScrn->display->virtualX > maxX)
+	maxX = pScrn->display->virtualX;
+    if (pScrn->display->virtualY > maxY)
+	maxY = pScrn->display->virtualY;
+    pScrn->virtualX = maxX;
+    pScrn->virtualY = maxY;
+    pScrn->displayWidth = (maxX + 63) & ~63;
+}
+
+/**
+ * Probes for video modes on attached otuputs, and assembles a list to insert
+ * into pScrn.
+ *
+ * \param first_time indicates that the memory layout has already been set up,
+ * 	  so displayWidth, virtualX, and virtualY shouldn't be touched.
+ *
+ * A SetMode must follow this call in order for operatingDevices to match the
+ * hardware's state, in case we detect a new output device.
+ */
+int
+I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
+{
+    i830_reprobe_output_modes(pScrn);
+
+    if (first_time) {
+	i830_set_default_screen_size(pScrn);
+    }
+
+    i830_set_xf86_modes_from_outputs(pScrn);
 
     return 1; /* XXX */
 }
@@ -1118,14 +640,32 @@ DisplayModePtr
 i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     xf86MonPtr ddc_mon;
-    DisplayModePtr ddc_modes;
+    DisplayModePtr ddc_modes, mode;
 
     ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
     if (ddc_mon == NULL)
 	return NULL;
 
+    if (output->MonInfo != NULL)
+	xfree(output->MonInfo);
+    output->MonInfo = ddc_mon;
+
+    /* Debug info for now, at least */
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n",
+	       i830_output_type_names[output->type]);
+    xf86PrintEDID(output->MonInfo);
+
     ddc_modes = i830GetDDCModes(pScrn, ddc_mon);
 
+    /* Strip out any modes that can't be supported on this output. */
+    for (mode = ddc_modes; mode != NULL; mode = mode->next) {
+	int status = output->mode_valid(pScrn, output, mode);
+
+	if (status != MODE_OK)
+	    mode->status = status;
+    }
+    i830xf86PruneInvalidModes(pScrn, &ddc_modes, TRUE);
+
     xfree(ddc_mon);
 
     return ddc_modes;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index f8064b9..69063a8 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -630,8 +630,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 			  randrp->virtualX, randrp->virtualY);
     for (i = 0; i < pI830->num_outputs; i++)
     {
-	MonPtr mon;
-
 	output = &pI830->output[i];
 	/*
 	 * Valid crtcs
@@ -701,6 +699,11 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 
 	RROutputSetCrtc (randrp->outputs[i], crtc);
 
+	/* We should pull info out of EDID to get the output physical
+	 * size when available.
+	 */
+	RROutputSetPhysicalSize(randrp->outputs[i], 0, 0);
+
 	RROutputSetPossibleOptions (randrp->outputs[i], possibleOptions);
 	RROutputSetCurrentOptions (randrp->outputs[i], currentOptions);
         nmode = 0;
@@ -709,11 +712,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 
 	modes = pI830->output[i].probed_modes;
 
-	if (pI830->output[i].pipe >= 0)
-	    mon = pI830->pipeMon[pipe];
-	else
-	    mon = NULL;
-
 	for (mode = modes; mode; mode = mode->next)
 	    nmode++;
 
@@ -723,11 +721,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
 		return FALSE;
 	    nmode = 0;
 
-	    /* We should pull info out of EDID to get the output physical
-	     * size when available.
-	     */
-	    RROutputSetPhysicalSize(randrp->outputs[i], 0, 0);
-
 	    for (p = 1; p >= 0; p--) {
 		for (mode = modes; mode; mode = mode->next) {
 		    if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
@@ -806,7 +799,7 @@ I830RandRGetInfo12 (ScreenPtr pScreen, R
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
-    I830ValidateXF86ModeList(pScrn, FALSE);
+    i830_reprobe_output_modes(pScrn);
     return I830RandRSetInfo12 (pScreen);
 }
 
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index b6a3d67..eda2857 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -66,8 +66,8 @@ struct i830_sdvo_priv {
      */
     struct i830_sdvo_caps caps;
 
-    /** Pixel clock limitations reported by the SDVO device */
-    CARD16 pixel_clock_min, pixel_clock_max;
+    /** Pixel clock limitations reported by the SDVO device, in kHz */
+    int pixel_clock_min, pixel_clock_max;
 
     /** State for save/restore */
     /** @{ */
@@ -323,9 +323,12 @@ i830_sdvo_set_active_outputs(I830OutputP
     return (status == SDVO_CMD_STATUS_SUCCESS);
 }
 
+/**
+ * Returns the pixel clock range limits of the current target input in kHz.
+ */
 static Bool
-i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, CARD16 *clock_min,
-				      CARD16 *clock_max)
+i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min,
+				      int *clock_max)
 {
     struct i830_sdvo_pixel_clock_range clocks;
     CARD8 status;
@@ -337,8 +340,9 @@ i830_sdvo_get_input_pixel_clock_range(I8
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return FALSE;
 
-    *clock_min = clocks.min;
-    *clock_max = clocks.max;
+    /* Convert the values from units of 10 kHz to kHz. */
+    *clock_min = clocks.min * 10;
+    *clock_max = clocks.max * 10;
 
     return TRUE;
 }
@@ -735,6 +739,9 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, 
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
+    if (pMode->Flags & V_DBLSCAN)
+	return MODE_NO_DBLESCAN;
+
     if (dev_priv->pixel_clock_min > pMode->Clock)
 	return MODE_CLOCK_HIGH;
 
@@ -1035,10 +1042,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 	       "SDVO device VID/DID: %02X:%02X.%02X, "
+	       "clock range %.1fMHz - %.1fMHz, "
 	       "input 1: %c, input 2: %c, "
 	       "output 1: %c, output 2: %c\n",
 	       dev_priv->caps.vendor_id, dev_priv->caps.device_id,
 	       dev_priv->caps.device_rev_id,
+	       dev_priv->pixel_clock_min / 1000.0,
+	       dev_priv->pixel_clock_max / 1000.0,
 	       (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
 	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
 	       dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N',
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 47c0d03..c597db5 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -423,7 +423,7 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830Ou
  * This should probably return a set of fixed modes, unless we can figure out
  * how to probe modes off of TV connections.
  */
-DisplayModePtr
+static DisplayModePtr
 i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
 {
     return NULL;
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 8c34053..8e8a94c 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -195,6 +195,59 @@ I830xf86SetModeCrtc(DisplayModePtr p, in
 }
 
 /**
+ * Allocates and returns a copy of pMode, including pointers within pMode.
+ */
+DisplayModePtr
+i830xf86DuplicateMode(DisplayModePtr pMode)
+{
+    DisplayModePtr pNew;
+
+    pNew = xnfalloc(sizeof(DisplayModeRec));
+    *pNew = *pMode;
+    pNew->next = NULL;
+    pNew->prev = NULL;
+    if (pNew->name == NULL) {
+	i830xf86SetModeDefaultName(pMode);
+    } else {
+	pNew->name = xnfstrdup(pMode->name);
+    }
+
+    return pNew;
+}
+
+/**
+ * Duplicates every mode in the given list and returns a pointer to the first
+ * mode.
+ *
+ * \param modeList doubly-linked mode list
+ */
+DisplayModePtr
+i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+{
+    DisplayModePtr first = NULL, last = NULL;
+    DisplayModePtr mode;
+
+    for (mode = modeList; mode != NULL; mode = mode->next) {
+	DisplayModePtr new;
+
+	new = i830xf86DuplicateMode(mode);
+
+	/* Insert pNew into modeList */
+	if (last) {
+	    last->next = new;
+	    new->prev = last;
+	} else {
+	    first = new;
+	    new->prev = NULL;
+	}
+	new->next = NULL;
+	last = new;
+    }
+
+    return first;
+}
+
+/**
  * Returns true if the given modes should program to the same timings.
  *
  * This doesn't use Crtc values, as it might be used on ModeRecs without the
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 0cba887..5a26c0e 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -31,6 +31,12 @@ i830xf86ModeHSync(DisplayModePtr mode);
 double
 i830xf86ModeVRefresh(DisplayModePtr mode);
 
+DisplayModePtr
+i830xf86DuplicateMode(DisplayModePtr pMode);
+
+DisplayModePtr
+i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+
 void
 i830xf86SetModeDefaultName(DisplayModePtr mode);
 



More information about the xorg-commit mailing list