xf86-video-intel: Branch 'modesetting' - 2 commits - src/i830_crt.c src/i830_debug.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_xf86Crtc.c src/i830_xf86Crtc.h

Keith Packard keithp at kemper.freedesktop.org
Wed Dec 6 22:56:13 EET 2006


 src/i830.h          |   13 -
 src/i830_crt.c      |   17 -
 src/i830_debug.c    |    2 
 src/i830_display.c  |    6 
 src/i830_driver.c   |  145 +++++++------
 src/i830_dvo.c      |    5 
 src/i830_lvds.c     |    5 
 src/i830_modes.c    |  239 ----------------------
 src/i830_randr.c    |  548 +++++++++-------------------------------------------
 src/i830_sdvo.c     |   14 -
 src/i830_tv.c       |    8 
 src/i830_xf86Crtc.c |  502 ++++++++++++++++++++++++++++++++++++++++++-----
 src/i830_xf86Crtc.h |   47 ++++
 13 files changed, 702 insertions(+), 849 deletions(-)

New commits:
diff-tree 6ee63364f5fabbc5578bcc9ded38c778595f5a6d (from parents)
Merge: 56f71194157ef929b62fe34a89c840bd59e56301 b75ecdb48309a15eb7c52b279c7f8523a95bcd48
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Wed Dec 6 12:53:22 2006 -0800

    Merge branch 'modesetting' into nonrandr-setup
    
    Also, fix buffer overflow in i830_debug.c

diff --cc src/i830_debug.c
index f732389,b1902ff..9f4dd29
@@@ -33,8 -33,157 +33,157 @@@
  #include "i830.h"
  #include "i830_debug.h"
  
+ #define DEBUGSTRING(func) static char *func(I830Ptr pI830, int reg, CARD32 val)
+ 
+ DEBUGSTRING(i830_debug_xyminus1)
+ {
+     return XNFprintf("%d, %d", (val & 0xffff) + 1,
+ 		     ((val & 0xffff0000) >> 16) + 1);
+ }
+ 
+ DEBUGSTRING(i830_debug_yxminus1)
+ {
+     return XNFprintf("%d, %d", ((val & 0xffff0000) >> 16) + 1,
+ 		     (val & 0xffff) + 1);
+ }
+ 
+ DEBUGSTRING(i830_debug_xy)
+ {
+     return XNFprintf("%d, %d", (val & 0xffff),
+ 		     ((val & 0xffff0000) >> 16));
+ }
+ 
+ DEBUGSTRING(i830_debug_dspstride)
+ {
+     return XNFprintf("%d bytes", val);
+ }
+ 
+ DEBUGSTRING(i830_debug_dspcntr)
+ {
+     char *enabled = val & DISPLAY_PLANE_ENABLE ? "enabled" : "disabled";
+     char plane = val & DISPPLANE_SEL_PIPE_B ? 'B' : 'A';
+     return XNFprintf("%s, pipe %c", enabled, plane);
+ }
+ 
+ DEBUGSTRING(i830_debug_pipeconf)
+ {
+     char *enabled = val & PIPEACONF_ENABLE ? "enabled" : "disabled";
+     char *wide = val & PIPEACONF_DOUBLE_WIDE ? "double-wide" : "single-wide";
+     return XNFprintf("%s, %s", enabled, wide);
+ }
+ 
+ DEBUGSTRING(i830_debug_hvtotal)
+ {
+     return XNFprintf("%d active, %d total", (val & 0xffff) + 1,
+ 		     ((val & 0xffff0000) >> 16) + 1);
+ }
+ 
+ DEBUGSTRING(i830_debug_hvsyncblank)
+ {
+     return XNFprintf("%d start, %d end", (val & 0xffff) + 1,
+ 		     ((val & 0xffff0000) >> 16) + 1);
+ }
+ 
+ DEBUGSTRING(i830_debug_vgacntrl)
+ {
+     return XNFprintf("%s", val & VGA_DISP_DISABLE ? "disabled" : "enabled");
+ }
+ 
+ DEBUGSTRING(i830_debug_fp)
+ {
+     return XNFprintf("n = %d, m1 = %d, m2 = %d",
+ 		     ((val & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT),
+ 		     ((val & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT),
+ 		     ((val & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT));
+ }
+ 
+ DEBUGSTRING(i830_debug_pp_status)
+ {
+     char *status = val & PP_ON ? "on" : "off";
+     char *ready = val & PP_READY ? "ready" : "not ready";
+     char *seq = "unknown";
+ 
+     switch (val & PP_SEQUENCE_MASK) {
+     case PP_SEQUENCE_NONE:
+ 	seq = "idle";
+ 	break;
+     case PP_SEQUENCE_ON:
+ 	seq = "on";
+ 	break;
+     case PP_SEQUENCE_OFF:
+ 	seq = "off";
+ 	break;
+     }
+ 
+     return XNFprintf("%s, %s, sequencing %s", status, ready, seq);
+ }
+ 
+ DEBUGSTRING(i830_debug_pp_control)
+ {
+     return XNFprintf("power target: %s",
+ 		     val & POWER_TARGET_ON ? "on" : "off");
+ }
+ 
+ DEBUGSTRING(i830_debug_dpll)
+ {
+     char *enabled = val & DPLL_VCO_ENABLE ? "enabled" : "disabled";
+     char *dvomode = val & DPLL_DVO_HIGH_SPEED ? "dvo" : "non-dvo";
+     char *vgamode = val & DPLL_VGA_MODE_DIS ? "" : ", VGA";
+     char *mode = "unknown";
+     char *clock = "unknown";
+     char *fpextra = val & DISPLAY_RATE_SELECT_FPA1 ? ", using FPx1!" : "";
 -    char sdvoextra[3];
++    char sdvoextra[20];
+     int p1, p2 = 0;
+ 
+     p1 = ffs((val & DPLL_FPA01_P1_POST_DIV_MASK) >>
+ 	     DPLL_FPA01_P1_POST_DIV_SHIFT);
+     switch (val & DPLL_MODE_MASK) {
+     case DPLLB_MODE_DAC_SERIAL:
+ 	mode = "dac/serial";
+ 	p2 = val & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ? 5 : 10;
+ 	break;
+     case DPLLB_MODE_LVDS:
+ 	mode = "LVDS";
+ 	p2 = val & DPLLB_LVDS_P2_CLOCK_DIV_7 ? 7 : 14;
+ 	break;
+     }
+     switch (val & PLL_REF_INPUT_MASK) {
+     case PLL_REF_INPUT_DREFCLK:
+ 	clock = "default";
+ 	break;
+     case PLL_REF_INPUT_TVCLKINA:
+ 	clock = "TV A";
+ 	break;
+     case PLL_REF_INPUT_TVCLKINBC:
+ 	clock = "TV B/C";
+ 	break;
+     }
+     if (IS_I945G(pI830) || IS_I945GM(pI830)) {
+ 	sprintf(sdvoextra, "SDVO mult %d",
+ 		(int)(val & SDVO_MULTIPLIER_MASK) >>
+ 		SDVO_MULTIPLIER_SHIFT_HIRES);
+     } else {
+ 	sdvoextra[0] = '\0';
+     }
+ 
+     return XNFprintf("%s, %s%s, %s mode, %s clock, p1 = %d, "
+ 		     "p2 = %d%s%s",
+ 		     enabled, dvomode, vgamode, mode, clock, p1, p2,
+ 		     fpextra, sdvoextra);
+ }
+ 
+ DEBUGSTRING(i830_debug_lvds)
+ {
+     char pipe = val & LVDS_PIPEB_SELECT ? 'B' : 'A';
+     char *enable = val & LVDS_PORT_EN ? "enabled" : "disabled";
+ 
+     return XNFprintf("%s, pipe %c", enable, pipe);
+ }
+ 
  #define DEFINEREG(reg) \
- 	{ reg, #reg, 0 }
+ 	{ reg, #reg, NULL, 0 }
+ #define DEFINEREG2(reg, func) \
+ 	{ reg, #reg, func, 0 }
  
  static struct i830SnapshotRec {
      int reg;
diff --cc src/i830_randr.c
index 94d2221,d0ced37..2d986df
@@@ -608,11 -602,12 +609,13 @@@
  		return FALSE;
  	    }
  	    crtc->desiredMode = *mode;
 -	    i830PipeSetBase(crtc, x, y);
  	}
  	i830DisableUnusedFunctions (pScrn);
+ 
+ 	i830DumpRegs(pScrn);
      }
 +    if (pos_changed && mode)
 +	i830PipeSetBase(crtc, x, y);
      return xf86RandR12CrtcNotify (randr_crtc);
  }
  
diff --cc src/i830_xf86Crtc.h
index 9b7f788,10d4b72..21fc244
@@@ -27,13 -27,8 +27,14 @@@
  #include "i830_xf86Modes.h"
  
  typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
+ typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
  
 +typedef enum _xf86OutputStatus {
 +   XF86OutputStatusConnected,
 +   XF86OutputStatusDisconnected,
 +   XF86OutputStatusUnknown,
 +} xf86OutputStatus;
 +
  typedef struct _xf86CrtcFuncs {
     /**
      * Turns the crtc on/off, or sets intermediate power levels if available.
diff-tree 56f71194157ef929b62fe34a89c840bd59e56301 (from ffd8aacbe7c72b696ff7257609e3c1d45c057609)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Dec 6 00:13:57 2006 -0800

    Use xf86 structures for default config instead of RandR.
    
    To avoid requiring RandR 1.2 in the X server, use the
    xf86 Crtc and Output structures as the basis for the default configuration
    computation (and, eventually, the config-file based configuration as well).

diff --git a/src/i830.h b/src/i830.h
index 4cfed4b..64d693a 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -192,12 +192,6 @@ struct _I830DVODriver {
 
 extern const char *i830_output_type_names[];
 
-enum detect_status {
-   OUTPUT_STATUS_CONNECTED,
-   OUTPUT_STATUS_DISCONNECTED,
-   OUTPUT_STATUS_UNKNOWN
-};
-
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
     Bool		    gammaEnabled;
@@ -606,6 +600,9 @@ extern Bool I830FixOffset(ScrnInfoPtr pS
 extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
 			char *name);
 
+/* return a mask of output indices matching outputs against type_mask */
+int i830_output_clones (ScrnInfoPtr pScrn, int type_mask);
+
 /* i830_display.c */
 Bool
 i830PipeHasType (xf86CrtcPtr crtc, int type);
@@ -627,10 +624,6 @@ Bool I830BindAGPMemory(ScrnInfoPtr pScrn
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
 
 /* i830_modes.c */
-int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
-void i830_reprobe_output_modes(ScrnInfoPtr pScrn);
-void i830_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn);
-void i830_set_default_screen_size(ScrnInfoPtr pScrn);
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
 
 /* i830_tv.c */
diff --git a/src/i830_crt.c b/src/i830_crt.c
index bf23f9e..1bb52d4 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -272,7 +272,7 @@ i830_crt_detect_ddc(xf86OutputPtr output
  * @param allow_disturb enables detection methods that may cause flickering
  *        on active displays.
  */
-static enum detect_status
+static xf86OutputStatus
 i830_crt_detect(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
@@ -281,13 +281,13 @@ i830_crt_detect(xf86OutputPtr output)
 
     if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
 	if (i830_crt_detect_hotplug(output))
-	    return OUTPUT_STATUS_CONNECTED;
+	    return XF86OutputStatusConnected;
 	else
-	    return OUTPUT_STATUS_DISCONNECTED;
+	    return XF86OutputStatusDisconnected;
     }
 
     if (i830_crt_detect_ddc(output))
-	return OUTPUT_STATUS_CONNECTED;
+	return XF86OutputStatusConnected;
 
     /* Use the load-detect method if we have no other way of telling. */
     crtc = i830GetLoadDetectPipe (output);
@@ -318,12 +318,12 @@ i830_crt_detect(xf86OutputPtr output)
 
 	i830ReleaseLoadDetectPipe (output);
 	if (connected)
-	    return OUTPUT_STATUS_CONNECTED;
+	    return XF86OutputStatusConnected;
 	else
-	    return OUTPUT_STATUS_DISCONNECTED;
+	    return XF86OutputStatusDisconnected;
     }
 
-    return OUTPUT_STATUS_UNKNOWN;
+    return XF86OutputStatusUnknown;
 }
 
 static DisplayModePtr
@@ -337,7 +337,7 @@ i830_crt_get_modes(xf86OutputPtr output)
     if (modes != NULL)
 	return modes;
 
-    if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED)
+    if ((*output->funcs->detect)(output) == XF86OutputStatusDisconnected)
 	return NULL;
 
     /* We've got a potentially-connected monitor that we can't DDC.  Return a
@@ -393,6 +393,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
 	return;
     }
     i830_output->type = I830_OUTPUT_ANALOG;
+    
     output->driver_private = i830_output;
 
     /* Set up the DDC bus. */
diff --git a/src/i830_display.c b/src/i830_display.c
index ac56528..1f41cc3 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -912,15 +912,15 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 Bool
 i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
 {
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     Bool ok = TRUE;
-    int i;
+    xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
 
     DPRINTF(PFX, "i830SetMode\n");
 
-    for (i = 0; i < pI830->xf86_config.num_crtc; i++)
+    if (crtc && crtc->enabled)
     {
-	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[i];
 	ok = i830PipeSetMode(crtc,
 			     i830PipeFindClosestMode(crtc, pMode), 
 			     TRUE);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 73af147..ad25a77 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -686,6 +686,23 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
       pI830->CursorInfoRec->ShowCursor(pScrn);
 }
 
+int
+i830_output_clones (ScrnInfoPtr pScrn, int type_mask)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
+    int			o;
+    int			index_mask = 0;
+
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr		output = config->output[o];
+	I830OutputPrivatePtr	intel_output = output->driver_private;
+	if (type_mask & (1 << intel_output->type))
+	    index_mask |= (1 << o);
+    }
+    return index_mask;
+}
+
 /**
  * Set up the outputs according to what type of chip we are.
  *
@@ -695,7 +712,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 static void
 I830SetupOutputs(ScrnInfoPtr pScrn)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR (pScrn);
+   I830Ptr  pI830 = I830PTR(pScrn);
+   int	    o;
 
    /* everyone has at least a single analog output */
    i830_crt_init(pScrn);
@@ -712,6 +731,44 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
    }
    if (IS_I915GM(pI830) || IS_I945GM(pI830))
       i830_tv_init(pScrn);
+   
+   for (o = 0; o < config->num_output; o++)
+   {
+      xf86OutputPtr	   output = config->output[o];
+      I830OutputPrivatePtr intel_output = output->driver_private;
+      int		   crtc_mask = 0, clone_mask = 0;
+      
+      /*
+       * Valid crtcs
+       */
+      switch (intel_output->type) {
+      case I830_OUTPUT_DVO:
+      case I830_OUTPUT_SDVO:
+	 crtc_mask = ((1 << 0)|
+		      (1 << 1));
+	 clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+		       (1 << I830_OUTPUT_DVO) |
+		       (1 << I830_OUTPUT_SDVO));
+	 break;
+      case I830_OUTPUT_ANALOG:
+	 crtc_mask = ((1 << 0));
+	 clone_mask = ((1 << I830_OUTPUT_ANALOG) |
+		       (1 << I830_OUTPUT_DVO) |
+		       (1 << I830_OUTPUT_SDVO));
+	 break;
+      case I830_OUTPUT_LVDS:
+	 crtc_mask = (1 << 1);
+	 clone_mask = (1 << I830_OUTPUT_LVDS);
+	 break;
+      case I830_OUTPUT_TVOUT:
+	 crtc_mask = ((1 << 0) |
+		      (1 << 1));
+	 clone_mask = (1 << I830_OUTPUT_TVOUT);
+	 break;
+      }
+      output->possible_crtcs = crtc_mask;
+      output->possible_clones = i830_output_clones (pScrn, clone_mask);
+   }
 }
 
 /**
@@ -883,7 +940,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
-   enum detect_status output_status[MAX_OUTPUTS];
 
    if (pScrn->numEntities != 1)
       return FALSE;
@@ -1375,64 +1431,20 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    {
       xf86OutputPtr	      output = pI830->xf86_config.output[i];
 
-      output_status[i] = (*output->funcs->detect) (output);
+      output->status = (*output->funcs->detect) (output);
    }
 #if 0
    RestoreHWState (pScrn);
 #endif
    
-   
-   for (i = 0; i < pI830->xf86_config.num_output; i++) 
-   {
-      xf86OutputPtr	      output = pI830->xf86_config.output[i];
-      I830OutputPrivatePtr    intel_output = output->driver_private;
-      xf86CrtcPtr	      crtc;
-      int		      p;
-
-      output->crtc = NULL;
-
-      if (output_status[i] == OUTPUT_STATUS_DISCONNECTED)
-	 continue;
-      
-      switch (intel_output->type) {
-      case I830_OUTPUT_LVDS:
-	 /* LVDS must live on pipe B for two-pipe devices */
-	 crtc = pI830->xf86_config.crtc[pI830->xf86_config.num_crtc - 1];
-	 if (!i830PipeInUse (crtc))
-	    output->crtc = crtc;
-	 break;
-      case I830_OUTPUT_ANALOG:
-      case I830_OUTPUT_DVO:
-      case I830_OUTPUT_SDVO:
-	 for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	 {
-	    crtc = pI830->xf86_config.crtc[p];
-	    if (!i830PipeInUse(crtc))
-	    {
-	       output->crtc = crtc;
-	       break;
-	    }
-	 }
-	 break;
-      case I830_OUTPUT_TVOUT:
-	 crtc = pI830->xf86_config.crtc[0];
-	 if (!i830PipeInUse(crtc))
-	 {
-	    output->crtc = crtc;
-	 }
-	 break;
-      default:
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled output type\n");
-	 break;
-      }
-   }
-
-   for (i = 0; i < pI830->xf86_config.num_crtc; i++) 
+   if (!xf86InitialConfiguration (pScrn))
    {
-      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
-      crtc->enabled = i830PipeInUse(crtc);
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+      PreInitCleanup(pScrn);
+      return FALSE;
    }
-   
+   pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
+    
    pI830->rotation = RR_Rotate_0;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
       pI830->InitialRotation = 0;
@@ -1677,7 +1689,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    if (!xf86RandR12PreInit (pScrn))
    {
-      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
       PreInitCleanup(pScrn);
       return FALSE;
    }	
@@ -3398,23 +3410,21 @@ static void
 i830AdjustFrame(int scrnIndex, int x, int y, int flags)
 {
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+   xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
    I830Ptr pI830 = I830PTR(pScrn);
-   int i;
+   xf86CrtcPtr	crtc = config->output[config->compat_output]->crtc;
 
    DPRINTF(PFX, "i830AdjustFrame: y = %d (+ %d), x = %d (+ %d)\n",
 	   x, pI830->xoffset, y, pI830->yoffset);
 
-   /* Sync the engine before adjust frame */
-   if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-      (*pI830->AccelInfoRec->Sync)(pScrn);
-      pI830->AccelInfoRec->NeedToSync = FALSE;
-   }
-
-   for (i = 0; i < pI830->xf86_config.num_crtc; i++)
+   if (crtc && crtc->enabled)
    {
-      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
-      if (crtc->enabled)
-	 i830PipeSetBase(crtc, x, y);
+      /* Sync the engine before adjust frame */
+      if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
+	 (*pI830->AccelInfoRec->Sync)(pScrn);
+	 pI830->AccelInfoRec->NeedToSync = FALSE;
+      }
+      i830PipeSetBase(crtc, x, y);
    }
 }
 
@@ -3815,7 +3825,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
    DPRINTF(PFX, "\nUnmapping memory\n");
    I830UnmapMem(pScrn);
    vgaHWUnmapMem(pScrn);
-   xf86CrtcCloseScreen (pScreen);
 
    if (pI830->ScanlineColorExpandBuffers) {
       xfree(pI830->ScanlineColorExpandBuffers);
@@ -4017,7 +4026,9 @@ I830CheckDevicesTimer(OsTimerPtr timer, 
        * implements a sensible policy using RandR-1.2.  For now, all we get
        * is this.
        */
-      I830ValidateXF86ModeList(pScrn, FALSE);
+      
+      xf86ProbeOutputModes (pScrn);
+      xf86SetScrnInfoModes (pScrn);
       xf86SwitchMode(pScrn->pScreen, pScrn->currentMode);
 
       /* Clear the BIOS's hotkey press flags */
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 6fe3157..ccd0846 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -164,10 +164,10 @@ i830_dvo_post_set_mode(xf86OutputPtr out
  *
  * Unimplemented.
  */
-static enum detect_status
+static xf86OutputStatus
 i830_dvo_detect(xf86OutputPtr output)
 {
-    return OUTPUT_STATUS_UNKNOWN;
+    return XF86OutputStatusUnknown;
 }
 
 static Bool
@@ -248,6 +248,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     }
     intel_output->type = I830_OUTPUT_DVO;
     output->driver_private = intel_output;
+    output->subpixel_order = SubPixelHorizontalRGB;
     
     /* Set up the I2C and DDC buses */
     ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index cf70956..5f0c01b 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -180,10 +180,10 @@ i830_lvds_post_set_mode(xf86OutputPtr ou
  * This always returns OUTPUT_STATUS_CONNECTED.  This output should only have
  * been set up if the LVDS was actually connected anyway.
  */
-static enum detect_status
+static xf86OutputStatus
 i830_lvds_detect(xf86OutputPtr output)
 {
-    return OUTPUT_STATUS_CONNECTED;
+    return XF86OutputStatusConnected;
 }
 
 /**
@@ -293,6 +293,7 @@ i830_lvds_init(ScrnInfoPtr pScrn)
     }
     intel_output->type = I830_OUTPUT_LVDS;
     output->driver_private = intel_output;
+    output->subpixel_order = SubPixelHorizontalRGB;
 
     /* 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 a0d79db..34f6cd5 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -57,245 +57,6 @@
 
 #define DEBUG_REPROBE 1
 
-static DisplayModePtr
-i830GetModeListTail(DisplayModePtr pModeList)
-{
-    DisplayModePtr last;
-
-    if (pModeList == NULL)
-	return NULL;
-
-    for (last = pModeList; last->next != NULL; last = last->next)
-	;
-
-    return last;
-}
-
-/**
- * This function removes a mode from a list of modes.  It should probably be
- * moved to xf86Mode.c.
- *
- * There are different types of mode lists:
- *
- *  - singly linked linear lists, ending in NULL
- *  - doubly linked linear lists, starting and ending in NULL
- *  - doubly linked circular lists
- *
- */
-
-static void
-I830xf86DeleteModeFromList(DisplayModePtr *modeList, DisplayModePtr mode)
-{
-    /* Catch the easy/insane cases */
-    if (modeList == NULL || *modeList == NULL || mode == NULL)
-	return;
-
-    /* If the mode is at the start of the list, move the start of the list */
-    if (*modeList == mode)
-	*modeList = mode->next;
-
-    /* If mode is the only one on the list, set the list to NULL */
-    if ((mode == mode->prev) && (mode == mode->next)) {
-	*modeList = NULL;
-    } else {
-	if ((mode->prev != NULL) && (mode->prev->next == mode))
-	    mode->prev->next = mode->next;
-	if ((mode->next != NULL) && (mode->next->prev == mode))
-	    mode->next->prev = mode->prev;
-    }
-}
-
-void
-i830_reprobe_output_modes(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool properties_set = FALSE;
-    int i;
-
-    /* Re-probe the list of modes for each output. */
-    for (i = 0; i < pI830->xf86_config.num_output; i++) 
-    {
-	xf86OutputPtr  output = pI830->xf86_config.output[i];
-	DisplayModePtr mode;
-
-	while (output->probed_modes != NULL)
-	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
-
-	output->probed_modes = (*output->funcs->get_modes) (output);
-
-	/* Set the DDC properties to whatever first output has DDC information.
-	 */
-	if (output->MonInfo != NULL && !properties_set) {
-	    xf86SetDDCproperties(pScrn, output->MonInfo);
-	    properties_set = TRUE;
-	}
-
-	if (output->probed_modes != NULL) 
-	{
-	    /* silently prune modes down to ones matching the user's
-	     * configuration.
-	     */
-	    i830xf86ValidateModesUserConfig(pScrn, output->probed_modes);
-	    i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE);
-	}
-
-#ifdef DEBUG_REPROBE
-	if (output->probed_modes != NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "Printing probed modes for output %s\n",
-		       output->name);
-	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		       "No remaining probed modes for output %s\n",
-		       output->name);
-	}
-#endif
-	for (mode = output->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 = xf86ModeVRefresh(mode);
-	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
-
-#ifdef DEBUG_REPROBE
-	    xf86PrintModeline(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.
- */
-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.
-     */
-    saved_mode = pI830->currentMode;
-    if (saved_mode != NULL) {
-	I830xf86DeleteModeFromList(&pScrn->modes, saved_mode);
-    }
-
-    /* Clear any existing modes from pScrn->modes */
-    while (pScrn->modes != NULL)
-	xf86DeleteMode(&pScrn->modes, pScrn->modes);
-
-    /* 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.
-     */
-    for (i = 0; i < pI830->xf86_config.num_output; i++) {
-	xf86OutputPtr output = pI830->xf86_config.output[i];
-	if (output->probed_modes != NULL) {
-	    pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
-	    break;
-	}
-    }
-
-    xf86RandR12GetOriginalVirtualSize(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 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?
-     */
-    last = i830GetModeListTail(pScrn->modes);
-    last->next = pScrn->modes;
-    pScrn->modes->prev = last;
-
-    /* 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.
- */
-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->xf86_config.num_output; i++) {
-	xf86OutputPtr  output = pI830->xf86_config.output[i];
-	DisplayModePtr mode;
-
-	for (mode = output->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 */
-}
-
 #ifdef RANDR_12_INTERFACE
 
 #define EDID_ATOM_NAME		"EDID_DATA"
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 0077020..94d2221 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -94,7 +94,8 @@ xf86RandR12GetInfo (ScreenPtr pScreen, R
     }
 
     /* Re-probe the outputs for new monitors or modes */
-    I830ValidateXF86ModeList(scrp, FALSE);
+    xf86ProbeOutputModes (scrp);
+    xf86SetScrnInfoModes (scrp);
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
@@ -246,13 +247,13 @@ xf86RandR12SetConfig (ScreenPtr		pScreen
 		    int			rate,
 		    RRScreenSizePtr	pSize)
 {
-    ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
-    XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
-    DisplayModePtr	    mode;
-    int			    px, py;
-    Bool		    useVirtual = FALSE;
-    int			    maxX = 0, maxY = 0;
-    Rotation		    oldRotation = randrp->rotation;
+    ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    DisplayModePtr	mode;
+    int			px, py;
+    Bool		useVirtual = FALSE;
+    int			maxX = 0, maxY = 0;
+    Rotation		oldRotation = randrp->rotation;
 
     randrp->rotation = rotation;
 
@@ -487,15 +488,15 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 {
     ScreenPtr		pScreen = randr_crtc->pScreen;
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     RRModePtr		randr_mode = NULL;
     int			x;
     int			y;
     Rotation		rotation;
     int			numOutputs;
-    RROutputPtr		randr_outputs[MAX_OUTPUTS];
+    RROutputPtr		randr_outputs[XF86_MAX_OUTPUT];
     RROutputPtr		randr_output;
-    xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     xf86OutputPtr	output;
     int			i, j;
     DisplayModePtr	curMode = &crtc->curMode;
@@ -505,9 +506,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     rotation = RR_Rotate_0;
     numOutputs = 0;
     randr_mode = NULL;
-    for (i = 0; i < pI830->xf86_config.num_output; i++)
+    for (i = 0; i < config->num_output; i++)
     {
-	output = pI830->xf86_config.output[i];
+	output = config->output[i];
 	if (output->crtc == crtc)
 	{
 	    randr_output = output->randr_output;
@@ -542,12 +543,13 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		  RROutputPtr	*randr_outputs)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
-    xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
+    Bool		pos_changed;
     int			o, ro;
-    xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
+    xf86CrtcPtr		save_crtcs[XF86_MAX_OUTPUT];
     Bool		save_enabled = crtc->enabled;
 
     if ((mode != NULL) != crtc->enabled)
@@ -555,9 +557,12 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     else if (mode && !xf86ModesEqual (&crtc->curMode, mode))
 	changed = TRUE;
     
-    for (o = 0; o < pI830->xf86_config.num_output; o++) 
+    pos_changed = changed;
+    if (x != crtc->x || y != crtc->y)
+	pos_changed = TRUE;
+    for (o = 0; o < config->num_output; o++) 
     {
-	xf86OutputPtr  output = pI830->xf86_config.output[o];
+	xf86OutputPtr  output = config->output[o];
 	xf86CrtcPtr    new_crtc;
 
 	save_crtcs[o] = output->crtc;
@@ -578,10 +583,12 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    output->crtc = new_crtc;
 	}
     }
+    /* XXX need device-independent mode setting code through an API */
     if (changed)
     {
+	I830Ptr pI830 = I830PTR(pScrn);
 	crtc->enabled = mode != NULL;
-	
+
 	/* Sync the engine before adjust mode */
 	if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 	    (*pI830->AccelInfoRec->Sync)(pScrn);
@@ -593,18 +600,19 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    if (!i830PipeSetMode (crtc, mode, TRUE))
 	    {
 		crtc->enabled = save_enabled;
-		for (o = 0; o < pI830->xf86_config.num_output; o++)
+		for (o = 0; o < config->num_output; o++)
 		{
-		    xf86OutputPtr	output = pI830->xf86_config.output[o];
+		    xf86OutputPtr	output = config->output[o];
 		    output->crtc = save_crtcs[o];
 		}
 		return FALSE;
 	    }
 	    crtc->desiredMode = *mode;
-	    i830PipeSetBase(crtc, x, y);
 	}
 	i830DisableUnusedFunctions (pScrn);
     }
+    if (pos_changed && mode)
+	i830PipeSetBase(crtc, x, y);
     return xf86RandR12CrtcNotify (randr_crtc);
 }
 
@@ -620,7 +628,7 @@ xf86RandR12CrtcSetGamma (ScreenPtr    pS
  * RandR modes and assign them to the output
  */
 static Bool
-I830xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
+xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
 {
     DisplayModePtr  mode;
     RRModePtr	    *rrmodes = NULL;
@@ -660,8 +668,8 @@ I830xf86RROutputSetModes (RROutputPtr ra
 		    modeInfo.modeFlags = mode->Flags;
 
 		    rrmode = RRModeGet (&modeInfo, mode->name);
-		    rrmode->devPrivate = mode;
 		    if (rrmode) {
+			rrmode->devPrivate = mode;
 			rrmodes[nmode++] = rrmode;
 			npreferred += pref;
 		    }
@@ -679,64 +687,25 @@ I830xf86RROutputSetModes (RROutputPtr ra
  * Mirror the current mode configuration to RandR
  */
 static Bool
-xf86RandR12SetInfo12 (ScrnInfoPtr pScrn)
+xf86RandR12SetInfo12 (ScreenPtr pScreen)
 {
-    I830Ptr		    pI830 = I830PTR(pScrn);
-    RROutputPtr		    clones[MAX_OUTPUTS];
-    RRCrtcPtr		    crtcs[MAX_DISPLAY_PIPES];
-    int			    ncrtc;
-    int			    o, c, p;
-    int			    clone_types;
-    int			    crtc_types;
-    int			    subpixel;
-    RRCrtcPtr		    randr_crtc;
-    int			    nclone;
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    RROutputPtr		clones[XF86_MAX_OUTPUT];
+    RRCrtcPtr		crtcs[XF86_MAX_CRTC];
+    int			ncrtc;
+    int			o, c, l;
+    RRCrtcPtr		randr_crtc;
+    int			nclone;
     
-    for (o = 0; o < pI830->xf86_config.num_output; o++)
+    for (o = 0; o < config->num_output; o++)
     {
-	xf86OutputPtr	output = pI830->xf86_config.output[o];
-	I830OutputPrivatePtr	intel_output = output->driver_private;
-	/*
-	 * Valid crtcs
-	 */
-	switch (intel_output->type) {
-	case I830_OUTPUT_DVO:
-	case I830_OUTPUT_SDVO:
-	    crtc_types = ((1 << 0)|
-			  (1 << 1));
-	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
-			   (1 << I830_OUTPUT_DVO) |
-			   (1 << I830_OUTPUT_SDVO));
-	    subpixel = SubPixelHorizontalRGB;
-	    break;
-	case I830_OUTPUT_ANALOG:
-	    crtc_types = ((1 << 0));
-	    clone_types = ((1 << I830_OUTPUT_ANALOG) |
-			   (1 << I830_OUTPUT_DVO) |
-			   (1 << I830_OUTPUT_SDVO));
-	    subpixel = SubPixelNone;
-	    break;
-	case I830_OUTPUT_LVDS:
-	    crtc_types = (1 << 1);
-	    clone_types = (1 << I830_OUTPUT_LVDS);
-	    subpixel = SubPixelHorizontalRGB;
-	    break;
-	case I830_OUTPUT_TVOUT:
-	    crtc_types = ((1 << 0) |
-			  (1 << 1));
-	    clone_types = (1 << I830_OUTPUT_TVOUT);
-	    subpixel = SubPixelNone;
-	    break;
-	default:
-	    crtc_types = 0;
-	    clone_types = 0;
-	    subpixel = SubPixelUnknown;
-	    break;
-	}
+	xf86OutputPtr	output = config->output[o];
+	
 	ncrtc = 0;
-	for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	    if (crtc_types & (1 << p))
-		crtcs[ncrtc++] = pI830->xf86_config.crtc[p]->randr_crtc;
+	for (c = 0; c < config->num_crtc; c++)
+	    if (output->possible_crtcs & (1 << c))
+		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
 
 	if (output->crtc)
 	    randr_crtc = output->crtc->randr_crtc;
@@ -750,32 +719,31 @@ xf86RandR12SetInfo12 (ScrnInfoPtr pScrn)
 	RROutputSetPhysicalSize(output->randr_output, 
 				output->mm_width,
 				output->mm_height);
-	I830xf86RROutputSetModes (output->randr_output, output->probed_modes);
+	xf86RROutputSetModes (output->randr_output, output->probed_modes);
 
-	switch ((*output->funcs->detect)(output)) {
-	case OUTPUT_STATUS_CONNECTED:
+	switch (output->status = (*output->funcs->detect)(output)) {
+	case XF86OutputStatusConnected:
 	    RROutputSetConnection (output->randr_output, RR_Connected);
 	    break;
-	case OUTPUT_STATUS_DISCONNECTED:
+	case XF86OutputStatusDisconnected:
 	    RROutputSetConnection (output->randr_output, RR_Disconnected);
 	    break;
-	case OUTPUT_STATUS_UNKNOWN:
+	case XF86OutputStatusUnknown:
 	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
 	    break;
 	}
 
-	RROutputSetSubpixelOrder (output->randr_output, subpixel);
+	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
 
 	/*
 	 * Valid clones
 	 */
 	nclone = 0;
-	for (c = 0; c < pI830->xf86_config.num_output; c++)
+	for (l = 0; l < config->num_output; l++)
 	{
-	    xf86OutputPtr	    clone = pI830->xf86_config.output[c];
-	    I830OutputPrivatePtr    intel_clone = clone->driver_private;
+	    xf86OutputPtr	    clone = config->output[l];
 	    
-	    if (o != c && ((1 << intel_clone->type) & clone_types))
+	    if (l != o && (output->possible_clones & (1 << l)))
 		clones[nclone++] = clone->randr_output;
 	}
 	if (!RROutputSetClones (output->randr_output, clones, nclone))
@@ -793,15 +761,18 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen,
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
-    i830_reprobe_output_modes(pScrn);
-    return xf86RandR12SetInfo12 (pScrn);
+    xf86ProbeOutputModes (pScrn);
+    xf86SetScrnInfoModes (pScrn);
+    return xf86RandR12SetInfo12 (pScreen);
 }
 
 static Bool
-xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn)
+xf86RandR12CreateObjects12 (ScreenPtr pScreen)
 {
-    I830Ptr		pI830 = I830PTR(pScrn);
-    int			p;
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
+    int			o;
     
     if (!RRInit ())
 	return FALSE;
@@ -809,45 +780,47 @@ xf86RandR12CreateObjects12 (ScrnInfoPtr 
     /*
      * Configure crtcs
      */
-    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
+    for (c = 0; c < config->num_crtc; c++)
     {
-	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[p];
+	xf86CrtcPtr    crtc = config->crtc[c];
 	
+	crtc->randr_crtc = RRCrtcCreate (crtc);
+	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
 	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
+    /*
+     * Configure outputs
+     */
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
 
+	output->randr_output = RROutputCreate (output->name, 
+					       strlen (output->name),
+					       output);
+	RROutputAttachScreen (output->randr_output, pScreen);
+    }
     return TRUE;
 }
 
 static Bool
 xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 {
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr		pI830 = I830PTR(pScrn);
-    int			p, o;
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    int			c;
     int			width, height;
 
     /*
-     * Attach RandR objects to screen
-     */
-    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	if (!RRCrtcAttachScreen (pI830->xf86_config.crtc[p]->randr_crtc, pScreen))
-	    return FALSE;
-
-    for (o = 0; o < pI830->xf86_config.num_output; o++)
-	if (!RROutputAttachScreen (pI830->xf86_config.output[o]->randr_output, pScreen))
-	    return FALSE;
-
-    /*
      * Compute width of screen
      */
     width = 0; height = 0;
-    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
+    for (c = 0; c < config->num_crtc; c++)
     {
-	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[p];
-	int		    crtc_width = crtc->x + crtc->curMode.HDisplay;
-	int		    crtc_height = crtc->y + crtc->curMode.VDisplay;
+	xf86CrtcPtr crtc = config->crtc[c];
+	int	    crtc_width = crtc->x + crtc->curMode.HDisplay;
+	int	    crtc_height = crtc->y + crtc->curMode.VDisplay;
 	
 	if (crtc->enabled && crtc_width > width)
 	    width = crtc_width;
@@ -869,14 +842,14 @@ xf86RandR12CreateScreenResources12 (Scre
 		   "Setting screen physical size to %d x %d\n",
 		   mmWidth, mmHeight);
 	xf86RandR12ScreenSetSize (pScreen,
-				width,
-				height,
-				mmWidth,
-				mmHeight);
+				  width,
+				  height,
+				  mmWidth,
+				  mmHeight);
     }
 
-    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	xf86RandR12CrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
+    for (c = 0; c < config->num_crtc; c++)
+	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -900,356 +873,27 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
 
-    if (xf86CrtcScreenInit (pScreen))
-	return FALSE;
-
     rp->rrGetInfo = xf86RandR12GetInfo12;
     rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
     rp->rrCrtcSet = xf86RandR12CrtcSet;
     rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
-    return TRUE;
-}
-
-static RRModePtr
-I830RRDefaultMode (RROutputPtr output)
-{
-    RRModePtr   target_mode = NULL;
-    int		target_diff = 0;
-    int		mmHeight;
-    int		num_modes;
-    int		m;
-    
-    num_modes = output->numPreferred ? output->numPreferred : output->numModes;
-    mmHeight = output->mmHeight;
-    if (!mmHeight)
-	mmHeight = 203;	/* 768 pixels at 96dpi */
-    /*
-     * Pick a mode closest to 96dpi 
-     */
-    for (m = 0; m < num_modes; m++)
-    {
-	RRModePtr   mode = output->modes[m];
-	int	    dpi;
-	int	    diff;
-
-	dpi = (mode->mode.height * 254) / (mmHeight * 10);
-	diff = dpi - 96;
-	diff = diff < 0 ? -diff : diff;
-	if (target_mode == NULL || diff < target_diff)
-	{
-	    target_mode = mode;
-	    target_diff = diff;
-	}
-    }
-    return target_mode;
-}
-
-static RRModePtr
-I830ClosestMode (RROutputPtr output, RRModePtr match)
-{
-    RRModePtr   target_mode = NULL;
-    int		target_diff = 0;
-    int		m;
-    
-    /*
-     * Pick a mode closest to the specified mode
-     */
-    for (m = 0; m < output->numModes; m++)
-    {
-	RRModePtr   mode = output->modes[m];
-	int	    dx, dy;
-	int	    diff;
-
-	/* exact matches are preferred */
-	if (mode == match)
-	    return mode;
-	
-	dx = match->mode.width - mode->mode.width;
-	dy = match->mode.height - mode->mode.height;
-	diff = dx * dx + dy * dy;
-	if (target_mode == NULL || diff < target_diff)
-	{
-	    target_mode = mode;
-	    target_diff = diff;
-	}
-    }
-    return target_mode;
-}
-
-static int
-I830RRPickCrtcs (RROutputPtr	*outputs,
-		 RRCrtcPtr	*best_crtcs,
-		 RRModePtr	*modes,
-		 int		num_output,
-		 int		n)
-{
-    int		c, o, l;
-    RROutputPtr	output;
-    RRCrtcPtr	crtc;
-    RRCrtcPtr	*crtcs;
-    RRCrtcPtr	best_crtc;
-    int		best_score;
-    int		score;
-    int		my_score;
-    
-    if (n == num_output)
-	return 0;
-    output = outputs[n];
-    
-    /*
-     * Compute score with this output disabled
-     */
-    best_crtcs[n] = NULL;
-    best_crtc = NULL;
-    best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_output, n+1);
-    if (modes[n] == NULL)
-	return best_score;
-    
-    crtcs = xalloc (num_output * sizeof (RRCrtcPtr));
-    if (!crtcs)
-	return best_score;
-
-    my_score = 1;
-    /* Score outputs that are known to be connected higher */
-    if (output->connection == RR_Connected)
-	my_score++;
-    /* Score outputs with preferred modes higher */
-    if (output->numPreferred)
-	my_score++;
-    /*
-     * Select a crtc for this output and
-     * then attempt to configure the remaining
-     * outputs
-     */
-    for (c = 0; c < output->numCrtcs; c++)
-    {
-	crtc = output->crtcs[c];
-	/*
-	 * Check to see if some other output is
-	 * using this crtc
-	 */
-	for (o = 0; o < n; o++)
-	    if (best_crtcs[o] == crtc)
-		break;
-	if (o < n)
-	{
-	    /*
-	     * If the two outputs desire the same mode,
-	     * see if they can be cloned
-	     */
-	    if (modes[o] == modes[n])
-	    {
-		for (l = 0; l < output->numClones; l++)
-		    if (output->clones[l] == outputs[o])
-			break;
-		if (l == output->numClones)
-		    continue;		/* nope, try next CRTC */
-	    }
-	    else
-		continue;		/* different modes, can't clone */
-	}
-	crtcs[n] = crtc;
-	memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr));
-	score = my_score + I830RRPickCrtcs (outputs, crtcs, modes,
-					    num_output, n+1);
-	if (score >= best_score)
-	{
-	    best_crtc = crtc;
-	    best_score = score;
-	    memcpy (best_crtcs, crtcs, num_output * sizeof (RRCrtcPtr));
-	}
-    }
-    xfree (crtcs);
-    return best_score;
-}
-
-static Bool
-I830RRInitialConfiguration (RROutputPtr *outputs,
-			    RRCrtcPtr	*crtcs,
-			    RRModePtr	*modes,
-			    int		num_output)
-{
-    int		o;
-    RRModePtr	target_mode = NULL;
+    if (!xf86RandR12CreateObjects12 (pScreen))
+	return FALSE;
 
-    for (o = 0; o < num_output; o++)
-	modes[o] = NULL;
-    
     /*
-     * Let outputs with preferred modes drive screen size
+     * Configure output modes
      */
-    for (o = 0; o < num_output; o++)
-    {
-	RROutputPtr output = outputs[o];
-
-	if (output->connection != RR_Disconnected && output->numPreferred)
-	{
-	    target_mode = I830RRDefaultMode (output);
-	    if (target_mode)
-	    {
-		modes[o] = target_mode;
-		break;
-	    }
-	}
-    }
-    if (!target_mode)
-    {
-	for (o = 0; o < num_output; o++)
-	{
-	    RROutputPtr output = outputs[o];
-	    if (output->connection != RR_Disconnected)
-	    {
-		target_mode = I830RRDefaultMode (output);
-		if (target_mode)
-		{
-		    modes[o] = target_mode;
-		    break;
-		}
-	    }
-	}
-    }
-    for (o = 0; o < num_output; o++)
-    {
-	RROutputPtr output = outputs[o];
-	
-	if (output->connection != RR_Disconnected && !modes[o])
-	    modes[o] = I830ClosestMode (output, target_mode);
-    }
-
-    if (!I830RRPickCrtcs (outputs, crtcs, modes, num_output, 0))
+    if (!xf86RandR12SetInfo12 (pScreen))
 	return FALSE;
-    
     return TRUE;
 }
 
-/*
- * Compute the virtual size necessary to place all of the available
- * crtcs in a panorama configuration
- */
-
-static void
-I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_output,
-			   RRCrtcPtr *crtcs, int num_crtc,
-			   int *widthp, int *heightp)
-{
-    int	    width = 0, height = 0;
-    int	    o;
-    int	    c;
-    int	    m;
-    int	    s;
-
-    for (c = 0; c < num_crtc; c++)
-    {
-	RRCrtcPtr   crtc = crtcs[c];
-	int	    crtc_width = 1600, crtc_height = 1200;
-
-	for (o = 0; o < num_output; o++) 
-	{
-	    RROutputPtr	output = outputs[o];
-
-	    for (s = 0; s < output->numCrtcs; s++)
-		if (output->crtcs[s] == crtc)
-		{
-		    for (m = 0; m < output->numModes; m++)
-		    {
-			RRModePtr   mode = output->modes[m];
-			if (mode->mode.width > crtc_width)
-			    crtc_width = mode->mode.width;
-			if (mode->mode.height > crtc_width)
-			    crtc_height = mode->mode.height;
-		    }
-		}
-	}
-	if (crtc_width > width)
-	    width = crtc_width;
-	if (crtc_height > height)
-	    height = crtc_height;
-    }
-    *widthp = width;
-    *heightp = height;
-}
-
 #endif
 
 Bool
 xf86RandR12PreInit (ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-#if RANDR_12_INTERFACE
-    RROutputPtr	outputs[MAX_OUTPUTS];
-    RRCrtcPtr	output_crtcs[MAX_OUTPUTS];
-    RRModePtr	output_modes[MAX_OUTPUTS];
-    RRCrtcPtr	crtcs[MAX_DISPLAY_PIPES];
-    int		width, height;
-    int		o;
-    int		c;
-#endif
-    
-    if (pI830->xf86_config.num_output <= 0)
-	return FALSE;
-    
-    i830_reprobe_output_modes(pScrn);
-
-#if RANDR_12_INTERFACE
-    if (!xf86RandR12CreateObjects12 (pScrn))
-	return FALSE;
-
-    /*
-     * Configure output modes
-     */
-    if (!xf86RandR12SetInfo12 (pScrn))
-	return FALSE;
-    /*
-     * With RandR info set up, let RandR choose
-     * the initial configuration
-     */
-    for (o = 0; o < pI830->xf86_config.num_output; o++)
-	outputs[o] = pI830->xf86_config.output[o]->randr_output;
-    for (c = 0; c < pI830->xf86_config.num_crtc; c++)
-	crtcs[c] = pI830->xf86_config.crtc[c]->randr_crtc;
-    
-    if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes,
-				     pI830->xf86_config.num_output))
-	return FALSE;
-    
-    I830RRDefaultScreenLimits (outputs, pI830->xf86_config.num_output, 
-			       crtcs, pI830->xf86_config.num_crtc,
-			       &width, &height);
-    
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (width > pScrn->display->virtualX)
-	pScrn->display->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
-    if (height > pScrn->display->virtualY)
-	pScrn->display->virtualY = height;
-    
-    /* XXX override xf86 common frame computation code */
-    pScrn->display->frameX0 = 0;
-    pScrn->display->frameY0 = 0;
-    for (o = 0; o < pI830->xf86_config.num_output; o++)
-    {
-	xf86OutputPtr  output = pI830->xf86_config.output[o];
-	RRModePtr	    randr_mode = output_modes[o];
-        RRCrtcPtr	    randr_crtc = output_crtcs[o];
-	DisplayModePtr	    mode;
-
-	if (randr_mode && randr_crtc)
-	{
-	    xf86CrtcPtr    crtc = randr_crtc->devPrivate;
-	    
-	    mode = (DisplayModePtr) randr_mode->devPrivate;
-	    crtc->desiredMode = *mode;
-	    output->crtc = crtc;
-	}
-    }
-#endif
-    i830_set_xf86_modes_from_outputs (pScrn);
-    
-    i830_set_default_screen_size(pScrn);
-
     return TRUE;
 }
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index c75800d..a2030b7 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -975,7 +975,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
  *
  * Takes 14ms on average on my i945G.
  */
-static enum detect_status
+static xf86OutputStatus
 i830_sdvo_detect(xf86OutputPtr output)
 {
     CARD8 response[2];
@@ -985,12 +985,12 @@ i830_sdvo_detect(xf86OutputPtr output)
     status = i830_sdvo_read_response(output, &response, 2);
 
     if (status != SDVO_CMD_STATUS_SUCCESS)
-	return OUTPUT_STATUS_UNKNOWN;
+	return XF86OutputStatusUnknown;
 
     if (response[0] != 0 || response[1] != 0)
-	return OUTPUT_STATUS_CONNECTED;
+	return XF86OutputStatusConnected;
     else
-	return OUTPUT_STATUS_DISCONNECTED;
+	return XF86OutputStatusDisconnected;
 }
 
 static void
@@ -1132,9 +1132,15 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
     if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+    {
 	dev_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+        output->subpixel_order = SubPixelHorizontalRGB;
+    }
     else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+    {
 	dev_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+        output->subpixel_order = SubPixelHorizontalRGB;
+    }
     else
     {
 	unsigned char	bytes[2];
diff --git a/src/i830_tv.c b/src/i830_tv.c
index f5716f8..e05bc4c 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -544,7 +544,7 @@ i830_tv_detect_type (xf86CrtcPtr    crtc
  * Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure
  * we have a pipe programmed in order to probe the TV.
  */
-static enum detect_status
+static xf86OutputStatus
 i830_tv_detect(xf86OutputPtr output)
 {
     xf86CrtcPtr		    crtc;
@@ -567,11 +567,11 @@ i830_tv_detect(xf86OutputPtr output)
     
     switch (dev_priv->type) {
     case TV_TYPE_NONE:
-	return OUTPUT_STATUS_DISCONNECTED;
+	return XF86OutputStatusDisconnected;
     case TV_TYPE_UNKNOWN:
-	return OUTPUT_STATUS_UNKNOWN;
+	return XF86OutputStatusUnknown;
     default:
-	return OUTPUT_STATUS_CONNECTED;
+	return XF86OutputStatusConnected;
     }
 }
 
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 7eb581c..5378b34 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -31,6 +31,7 @@
 #include <stdio.h>
 
 #include "xf86.h"
+#include "xf86DDC.h"
 #include "i830_xf86Crtc.h"
 
 /*
@@ -49,12 +50,7 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     crtc->scrn = scrn;
     crtc->funcs = funcs;
 #ifdef RANDR_12_INTERFACE
-    crtc->randr_crtc = RRCrtcCreate (crtc);
-    if (!crtc->randr_crtc)
-    {
-	xfree (crtc);
-	return NULL;
-    }
+    crtc->randr_crtc = NULL;
 #endif
     xf86_config->crtc[xf86_config->num_crtc++] = crtc;
     return crtc;
@@ -67,10 +63,6 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
     int			c;
     
     (*crtc->funcs->destroy) (crtc);
-#ifdef RANDR_12_INTERFACE
-    if (crtc->randr_crtc)
-	RRCrtcDestroy (crtc->randr_crtc);
-#endif
     for (c = 0; c < xf86_config->num_crtc; c++)
 	if (xf86_config->crtc[c] == crtc)
 	{
@@ -101,14 +93,10 @@ xf86OutputCreate (ScrnInfoPtr		    scrn,
     output->scrn = scrn;
     output->funcs = funcs;
     output->name = (char *) (output + 1);
+    output->subpixel_order = SubPixelUnknown;
     strcpy (output->name, name);
 #ifdef RANDR_12_INTERFACE
-    output->randr_output = RROutputCreate (name, strlen (name), output);
-    if (!output->randr_output)
-    {
-	xfree (output);
-	return NULL;
-    }
+    output->randr_output = NULL;
 #endif
     xf86_config->output[xf86_config->num_output++] = output;
     return output;
@@ -122,10 +110,6 @@ xf86OutputDestroy (xf86OutputPtr output)
     int			o;
     
     (*output->funcs->destroy) (output);
-#ifdef RANDR_12_INTERFACE
-    if (output->randr_output)
-	RROutputDestroy (output->randr_output);
-#endif
     while (output->probed_modes)
 	xf86DeleteMode (&output->probed_modes, output->probed_modes);
     for (o = 0; o < xf86_config->num_output; o++)
@@ -140,55 +124,467 @@ xf86OutputDestroy (xf86OutputPtr output)
     xfree (output);
 }
 
-Bool
-xf86CrtcScreenInit (ScreenPtr pScreen)
+static DisplayModePtr
+xf86DefaultMode (xf86OutputPtr output)
 {
-#ifdef RANDR_12_INTERFACE
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			i;
+    DisplayModePtr  target_mode = NULL;
+    DisplayModePtr  mode;
+    int		    target_diff = 0;
+    int		    target_preferred = 0;
+    int		    mm_height;
+    
+    mm_height = output->mm_height;
+    if (!mm_height)
+	mm_height = 203;	/* 768 pixels at 96dpi */
+    /*
+     * Pick a mode closest to 96dpi 
+     */
+    for (mode = output->probed_modes; mode; mode = mode->next)
+    {
+	int	    dpi;
+	int	    preferred = (mode->type & M_T_PREFERRED) != 0;
+	int	    diff;
+
+	dpi = (mode->HDisplay * 254) / (mm_height * 10);
+	diff = dpi - 96;
+	diff = diff < 0 ? -diff : diff;
+	if (target_mode == NULL || (preferred > target_preferred) ||
+	    (preferred == target_preferred && diff < target_diff))
+	{
+	    target_mode = mode;
+	    target_diff = diff;
+	    target_preferred = preferred;
+	}
+    }
+    return target_mode;
+}
 
-    for (i = 0; i < xf86_config->num_crtc; i++)
+static DisplayModePtr
+xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match)
+{
+    DisplayModePtr  target_mode = NULL;
+    DisplayModePtr  mode;
+    int		    target_diff = 0;
+    
+    /*
+     * Pick a mode closest to the specified mode
+     */
+    for (mode = output->probed_modes; mode; mode = mode->next)
     {
-	xf86CrtcPtr crtc = xf86_config->crtc[i];
+	int	    dx, dy;
+	int	    diff;
 
-	if (!crtc->randr_crtc)
-	    crtc->randr_crtc = RRCrtcCreate (crtc);
-	if (!crtc->randr_crtc)
-	    return FALSE;
+	/* exact matches are preferred */
+	if (xf86ModesEqual (mode, match))
+	    return mode;
+	
+	dx = match->HDisplay - mode->HDisplay;
+	dy = match->VDisplay - mode->VDisplay;
+	diff = dx * dx + dy * dy;
+	if (target_mode == NULL || diff < target_diff)
+	{
+	    target_mode = mode;
+	    target_diff = diff;
+	}
     }
-    for (i = 0; i < xf86_config->num_output; i++)
+    return target_mode;
+}
+
+static Bool
+xf86OutputHasPreferredMode (xf86OutputPtr output)
+{
+    DisplayModePtr  mode;
+
+    for (mode = output->probed_modes; mode; mode = mode->next)
+	if (mode->type & M_T_PREFERRED)
+	    return TRUE;
+    return FALSE;
+}
+
+static int
+xf86PickCrtcs (ScrnInfoPtr	pScrn,
+	       xf86CrtcPtr	*best_crtcs,
+	       DisplayModePtr	*modes,
+	       int		n)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int		    c, o, l;
+    xf86OutputPtr   output;
+    xf86CrtcPtr	    crtc;
+    xf86CrtcPtr	    *crtcs;
+    xf86CrtcPtr	    best_crtc;
+    int		    best_score;
+    int		    score;
+    int		    my_score;
+    
+    if (n == config->num_output)
+	return 0;
+    output = config->output[n];
+    
+    /*
+     * Compute score with this output disabled
+     */
+    best_crtcs[n] = NULL;
+    best_crtc = NULL;
+    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1);
+    if (modes[n] == NULL)
+	return best_score;
+    
+    crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr));
+    if (!crtcs)
+	return best_score;
+
+    my_score = 1;
+    /* Score outputs that are known to be connected higher */
+    if (output->status == XF86OutputStatusConnected)
+	my_score++;
+    /* Score outputs with preferred modes higher */
+    if (xf86OutputHasPreferredMode (output))
+	my_score++;
+    /*
+     * Select a crtc for this output and
+     * then attempt to configure the remaining
+     * outputs
+     */
+    for (c = 0; c < config->num_crtc; c++)
     {
-	xf86OutputPtr output = xf86_config->output[i];
+	if ((output->possible_crtcs & (1 << c)) == 0)
+	    continue;
 	
-	if (!output->randr_output)
-	    output->randr_output = RROutputCreate (output->name,
-						   strlen (output->name),
-						   output);
-	if (!output->randr_output)
-	    return FALSE;
+	crtc = config->crtc[c];
+	/*
+	 * Check to see if some other output is
+	 * using this crtc
+	 */
+	for (o = 0; o < n; o++)
+	    if (best_crtcs[o] == crtc)
+		break;
+	if (o < n)
+	{
+	    /*
+	     * If the two outputs desire the same mode,
+	     * see if they can be cloned
+	     */
+	    if (xf86ModesEqual (modes[o], modes[n]))
+	    {
+		for (l = 0; l < config->num_output; l++)
+		    if (output->possible_clones & (1 << l))
+			break;
+		if (l == config->num_output)
+		    continue;		/* nope, try next CRTC */
+	    }
+	    else
+		continue;		/* different modes, can't clone */
+	}
+	crtcs[n] = crtc;
+	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
+	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1);
+	if (score >= best_score)
+	{
+	    best_crtc = crtc;
+	    best_score = score;
+	    memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr));
+	}
+    }
+    xfree (crtcs);
+    return best_score;
+}
+
+
+/*
+ * Compute the virtual size necessary to place all of the available
+ * crtcs in a panorama configuration
+ */
+
+static void
+xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int	    width = 0, height = 0;
+    int	    o;
+    int	    c;
+    int	    s;
+
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	int	    crtc_width = 1600, crtc_height = 1200;
+
+	for (o = 0; o < config->num_output; o++) 
+	{
+	    xf86OutputPtr   output = config->output[o];
+
+	    for (s = 0; s < config->num_crtc; s++)
+		if (output->possible_crtcs & (1 << s))
+		{
+		    DisplayModePtr  mode;
+		    for (mode = output->probed_modes; mode; mode = mode->next)
+		    {
+			if (mode->HDisplay > crtc_width)
+			    crtc_width = mode->HDisplay;
+			if (mode->VDisplay > crtc_width)
+			    crtc_height = mode->VDisplay;
+		    }
+		}
+	}
+	if (crtc_width > width)
+	    width = crtc_width;
+	if (crtc_height > height)
+	    height = crtc_height;
     }
+    *widthp = width;
+    *heightp = height;
+}
+
+void
+xf86ProbeOutputModes (ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    Bool		properties_set = FALSE;
+    int			o;
+
+    /* Probe the list of modes for each output. */
+    for (o = 0; o < config->num_output; o++) 
+    {
+	xf86OutputPtr  output = config->output[o];
+	DisplayModePtr mode;
+
+	while (output->probed_modes != NULL)
+	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
+
+	output->probed_modes = (*output->funcs->get_modes) (output);
+
+	/* Set the DDC properties to whatever first output has DDC information.
+	 */
+	if (output->MonInfo != NULL && !properties_set) {
+	    xf86SetDDCproperties(pScrn, output->MonInfo);
+	    properties_set = TRUE;
+	}
+
+#ifdef DEBUG_REPROBE
+	if (output->probed_modes != NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Printing probed modes for output %s\n",
+		       output->name);
+	} else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "No remaining probed modes for output %s\n",
+		       output->name);
+	}
 #endif
-    return TRUE;
+	for (mode = output->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 = xf86ModeVRefresh(mode);
+	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
+
+#ifdef DEBUG_REPROBE
+	    xf86PrintModeline(pScrn->scrnIndex, mode);
+#endif
+	}
+    }
 }
 
+
+/**
+ * Copy one of the output mode lists to the ScrnInfo record
+ */
+
+/* XXX where does this function belong? Here? */
+void
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+
 void
-xf86CrtcCloseScreen (ScreenPtr pScreen)
+xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
 {
-#ifdef RANDR_12_INTERFACE
-    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int			i;
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86OutputPtr	output;
+    xf86CrtcPtr		crtc;
+    DisplayModePtr	last, mode;
+    int			originalVirtualX, originalVirtualY;
+
+    output = config->output[config->compat_output];
+    if (!output->crtc)
+    {
+	int o;
+
+	output = NULL;
+	for (o = 0; o < config->num_output; o++)
+	    if (config->output[o]->crtc)
+	    {
+		config->compat_output = o;
+		output = config->output[o];
+		break;
+	    }
+	/* no outputs are active, punt and leave things as they are */
+	if (!output)
+	    return;
+    }
+    crtc = output->crtc;
+
+    /* Clear any existing modes from pScrn->modes */
+    while (pScrn->modes != NULL)
+	xf86DeleteMode(&pScrn->modes, pScrn->modes);
+
+    /* Set pScrn->modes to the mode list for the 'compat' output */
+    pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
+
+    xf86RandR12GetOriginalVirtualSize(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 that we threw out for virtualX/Y. */
+    i830xf86PruneInvalidModes(pScrn, &pScrn->modes, TRUE);
+
+    for (mode = pScrn->modes; mode; mode = mode->next)
+	if (xf86ModesEqual (mode, &crtc->desiredMode))
+	    break;
+    
+    /* For some reason, pScrn->modes is circular, unlike the other mode lists.
+     * How great is that?
+     */
+    for (last = pScrn->modes; last && last->next; last = last->next);
+    last->next = pScrn->modes;
+    pScrn->modes->prev = last;
+    if (mode)
+	while (pScrn->modes != mode)
+	    pScrn->modes = pScrn->modes->next;
+    pScrn->currentMode = pScrn->modes;
+}
+
+/**
+ * Construct default screen configuration
+ *
+ * Given auto-detected (and, eventually, configured) values,
+ * construct a usable configuration for the system
+ */
+
+Bool
+xf86InitialConfiguration (ScrnInfoPtr	    pScrn)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o, c;
+    DisplayModePtr	target_mode = NULL;
+    xf86CrtcPtr		*crtcs;
+    DisplayModePtr	*modes;
+    int			width, height;
 
-    for (i = 0; i < xf86_config->num_crtc; i++)
+    xf86ProbeOutputModes (pScrn);
+
+    crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
+    modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
+    
+    for (o = 0; o < config->num_output; o++)
+	modes[o] = NULL;
+    
+    /*
+     * Let outputs with preferred modes drive screen size
+     */
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr output = config->output[o];
+
+	if (output->status != XF86OutputStatusDisconnected &&
+	    xf86OutputHasPreferredMode (output))
+	{
+	    target_mode = xf86DefaultMode (output);
+	    if (target_mode)
+	    {
+		modes[o] = target_mode;
+		config->compat_output = o;
+		break;
+	    }
+	}
+    }
+    if (!target_mode)
     {
-	xf86CrtcPtr crtc = xf86_config->crtc[i];
-	crtc->randr_crtc = NULL;
+	for (o = 0; o < config->num_output; o++)
+	{
+	    xf86OutputPtr output = config->output[o];
+	    if (output->status != XF86OutputStatusDisconnected)
+	    {
+		target_mode = xf86DefaultMode (output);
+		if (target_mode)
+		{
+		    modes[o] = target_mode;
+		    config->compat_output = o;
+		    break;
+		}
+	    }
+	}
     }
-    for (i = 0; i < xf86_config->num_output; i++)
+    for (o = 0; o < config->num_output; o++)
     {
-	xf86OutputPtr output = xf86_config->output[i];
-	output->randr_output = NULL;
+	xf86OutputPtr output = config->output[o];
+	
+	if (output->status != XF86OutputStatusDisconnected && !modes[o])
+	    modes[o] = xf86ClosestMode (output, target_mode);
     }
-#endif
+
+    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0))
+    {
+	xfree (crtcs);
+	xfree (modes);
+	return FALSE;
+    }
+    
+    xf86DefaultScreenLimits (pScrn, &width, &height);
+    
+    /*
+     * Expand virtual size to cover potential mode switches
+     */
+    if (width > pScrn->virtualX)
+	pScrn->virtualX = width;
+    if (width > pScrn->display->virtualX)
+	pScrn->display->virtualX = width;
+    if (height > pScrn->virtualY)
+	pScrn->virtualY = height;
+    if (height > pScrn->display->virtualY)
+	pScrn->display->virtualY = height;
+    
+    /* XXX override xf86 common frame computation code */
+    
+    pScrn->display->frameX0 = 0;
+    pScrn->display->frameY0 = 0;
+    
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	xf86CrtcPtr	crtc = config->crtc[c];
+
+	crtc->enabled = FALSE;
+	memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode));
+    }
+	
+    /*
+     * Set initial configuration
+     */
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+	DisplayModePtr	mode = modes[o];
+        xf86CrtcPtr	crtc = crtcs[o];
+
+	if (mode && crtc)
+	{
+	    crtc->desiredMode = *mode;
+	    crtc->enabled = TRUE;
+	    crtc->x = 0;
+	    crtc->y = 0;
+	    output->crtc = crtc;
+	    /* XXX set position; for now, we clone */
+	}
+    }
+    
+    /* Mirror output modes to pScrn mode list */
+    xf86SetScrnInfoModes (pScrn);
+    
+    xfree (crtcs);
+    xfree (modes);
+    return TRUE;
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 21ba1fc..9b7f788 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -28,6 +28,12 @@
 
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
 
+typedef enum _xf86OutputStatus {
+   XF86OutputStatusConnected,
+   XF86OutputStatusDisconnected,
+   XF86OutputStatusUnknown,
+} xf86OutputStatus;
+
 typedef struct _xf86CrtcFuncs {
    /**
     * Turns the crtc on/off, or sets intermediate power levels if available.
@@ -186,7 +192,7 @@ typedef struct _xf86OutputFuncs {
     /**
      * Probe for a connected output, and return detect_status.
      */
-    enum detect_status
+    xf86OutputStatus
     (*detect)(xf86OutputPtr	    output);
 
     /**
@@ -211,12 +217,23 @@ struct _xf86Output {
      * Associated ScrnInfo
      */
     ScrnInfoPtr		scrn;
+
     /**
      * Currently connected crtc (if any)
      *
      * If this output is not in use, this field will be NULL.
      */
     xf86CrtcPtr		crtc;
+
+    /**
+     * Possible CRTCs for this output as a mask of crtc indices
+     */
+    CARD32		possible_crtcs;
+
+    /**
+     * Possible outputs to share the same CRTC as a mask of output indices
+     */
+    CARD32		possible_clones;
     /**
      * List of available modes on this output.
      *
@@ -225,9 +242,20 @@ struct _xf86Output {
      */
     DisplayModePtr	probed_modes;
 
+    /**
+     * Current connection status
+     *
+     * This indicates whether a monitor is known to be connected
+     * to this output or not, or whether there is no way to tell
+     */
+    xf86OutputStatus	status;
+
     /** EDID monitor information */
     xf86MonPtr		MonInfo;
 
+    /** subpixel order */
+    int			subpixel_order;
+
     /** Physical size of the currently attached output device. */
     int			mm_width, mm_height;
 
@@ -253,12 +281,20 @@ struct _xf86Output {
 #endif
 };
 
+/* XXX yes, static allocation is a kludge */
 #define XF86_MAX_CRTC	4
 #define XF86_MAX_OUTPUT	16
 
 typedef struct _xf86CrtcConfig {
    int			num_output;
    xf86OutputPtr	output[XF86_MAX_OUTPUT];
+   /**
+    * compat_output is used whenever we deal
+    * with legacy code that only understands a single
+    * output. pScrn->modes will be loaded from this output,
+    * adjust frame will whack this output, etc.
+    */
+   int			compat_output;
     
    int			num_crtc;
    xf86CrtcPtr		crtc[XF86_MAX_CRTC];
@@ -307,10 +343,13 @@ xf86OutputCreate (ScrnInfoPtr		scrn,
 void
 xf86OutputDestroy (xf86OutputPtr	output);
 
-Bool
-xf86CrtcScreenInit (ScreenPtr pScreen);
+void
+xf86ProbeOutputModes (ScrnInfoPtr pScrn);
 
 void
-xf86CrtcCloseScreen (ScreenPtr pScreen);
+xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
+
+Bool
+xf86InitialConfiguration (ScrnInfoPtr pScrn);
 
 #endif /* _XF86CRTC_H_ */



More information about the xorg-commit mailing list