xf86-video-intel: Branch 'modesetting' - 10 commits - src/i810_reg.h src/i830_crt.c src/i830_cursor.c src/i830_display.c src/i830_display.h src/i830_dri.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_randr.h src/i830_rotate.c src/i830_sdvo.c src/i830_tv.c src/i830_video.c src/i830_xf86Crtc.c src/i830_xf86Crtc.h src/i830_xf86Modes.c src/i830_xf86Modes.h src/Makefile.am

Keith Packard keithp at kemper.freedesktop.org
Fri Dec 1 00:09:37 EET 2006


 src/Makefile.am      |    2 
 src/i810_reg.h       |    1 
 src/i830.h           |  140 +++--------------
 src/i830_crt.c       |  180 ++++++++++++++--------
 src/i830_cursor.c    |  102 ++++++------
 src/i830_display.c   |  271 ++++++++++++++++-----------------
 src/i830_display.h   |   14 -
 src/i830_dri.c       |    8 -
 src/i830_driver.c    |  183 ++++++++++++++--------
 src/i830_dvo.c       |  147 ++++++++++++------
 src/i830_lvds.c      |   93 +++++++----
 src/i830_modes.c     |   73 ++++-----
 src/i830_randr.c     |  407 +++++++++++++++++++++++----------------------------
 src/i830_randr.h     |   37 ++++
 src/i830_rotate.c    |    2 
 src/i830_sdvo.c      |  295 +++++++++++++++++++++---------------
 src/i830_tv.c        |  299 ++++++++++++++++++++++++-------------
 src/i830_video.c     |    2 
 src/i830_xf86Crtc.c  |  140 +++++++++++++++++
 src/i830_xf86Crtc.h  |  310 ++++++++++++++++++++++++++++++++++++++
 src/i830_xf86Modes.c |   24 +++
 src/i830_xf86Modes.h |    7 
 22 files changed, 1721 insertions(+), 1016 deletions(-)

New commits:
diff-tree ff64bc7397cafbec94e388e1625b3a1999f1aca7 (from parents)
Merge: b94b7c4bcfdb7ba59ed818f72309b5060a2ab7ee 16e01b117bb7ae90b150dd4f25a887dd895cf473
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 30 14:09:31 2006 -0800

    Merge branch 'restructure-outputs' into modesetting.
    
    Outputs and Crtcs now have a driver-independent representation which should
    permit generic code to control RandR 1.2 and startup configuration.

diff --cc src/Makefile.am
index 5246270,0a14d1a..976a95a
@@@ -81,7 -80,8 +81,9 @@@
  	 i830_tv.c \
  	 i830_xf86Modes.h \
  	 i830_xf86Modes.c \
 +	 i830_xf86cvt.c \
+ 	 i830_xf86Crtc.h \
+ 	 i830_xf86Crtc.c \
  	 i915_3d.c \
  	 i915_3d.h \
  	 i915_reg.h \
diff --cc src/i830.h
index 422fdb7,14adb3c..4cfed4b
@@@ -197,108 -189,25 +198,33 @@@
     OUTPUT_STATUS_UNKNOWN
  };
  
- struct _I830OutputRec {
-    int type;
-    int pipe;
-    Bool enabled;
-    /**
-     * Marks that the output and associated pipe is temporarily enabled for
-     * load detection.
-     */
-    Bool load_detect_temp;
- 
-    /**
-     * Turns the output on/off, or sets intermediate power levels if available.
-     *
-     * Unsupported intermediate modes drop to the lower power setting.  If the
-     * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
-     * disabled afterwards.
-     */
-    void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
- 
-    /**
-     * Saves the output's state for restoration on VT switch.
-     */
-    void (*save)(ScrnInfoPtr pScrn, I830OutputPtr output);
- 
-    /**
-     * Restore's the output's state at VT switch.
-     */
-    void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
- 
-    /**
-     * Callback for testing a video mode for a given output.
-     *
-     * This function should only check for cases where a mode can't be supported
-     * on the pipe specifically, and not represent generic CRTC limitations.
-     *
-     * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
-     */
-    int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output,
- 		     DisplayModePtr pMode);
- 
-    /**
-     * Callback for setting up a video mode before any pipe/dpll changes.
-     *
-     * \param pMode the mode that will be set, or NULL if the mode to be set is
-     * unknown (such as the restore path of VT switching).
-     */
-    void (*pre_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
- 			DisplayModePtr pMode);
- 
-    /**
-     * Callback for setting up a video mode after the DPLL update but before
-     * the plane is enabled.
-     */
-    void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
- 			 DisplayModePtr pMode);
- 
-    /**
-     * Probe for a connected output, and return detect_status.
-     */
-    enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
- 
-    /**
-     * Query the device for the modes it provides.
-     *
-     * This function may also update MonInfo, mm_width, and mm_height.
-     *
-     * \return singly-linked list of modes or NULL if no modes found.
-     */
-    DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output);
- 
-    /**
-     * List of available modes on this output.
-     *
-     * This should be the list from get_modes(), plus perhaps additional
-     * compatible modes added later.
-     */
-    DisplayModePtr probed_modes;
- 
-    /** EDID monitor information */
-    xf86MonPtr MonInfo;
- 
-    /** Physical size of the output currently attached. */
-    int mm_width, mm_height;
- 
-    I2CBusPtr pI2CBus;
-    I2CBusPtr pDDCBus;
-    struct _I830DVODriver *i2c_drv;
+ typedef struct _I830CrtcPrivateRec {
+     int			    pipe;
+     Bool		    gammaEnabled;
+ } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
+ 
+ #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
+ 
+ typedef struct _I830OutputPrivateRec {
+    int			    type;
+    I2CBusPtr		    pI2CBus;
+    I2CBusPtr		    pDDCBus;
+    struct _I830DVODriver    *i2c_drv;
+    Bool			    load_detect_temp;
     /** Output-private structure.  Should replace i2c_drv */
-    void *dev_priv;
- #ifdef RANDR_12_INTERFACE
-    RROutputPtr randr_output;
- #endif
- };
+    void			    *dev_priv;
+ } I830OutputPrivateRec, *I830OutputPrivatePtr;
+ 
+ #define I830OutputPrivate(o) ((I830OutputPrivatePtr) (o)->driver_private)
  
 +/** enumeration of 3d consumers so some can maintain invariant state. */
 +enum last_3d {
 +    LAST_3D_OTHER,
 +    LAST_3D_VIDEO,
 +    LAST_3D_RENDER,
 +    LAST_3D_ROTATION
 +};
 +
  typedef struct _I830PipeRec {
     Bool		  enabled;
     Bool		  gammaEnabled;
diff --cc src/i830_crt.c
index 76a8007,37a5b3f..7a706d1
@@@ -279,10 -292,33 +292,33 @@@
  	return OUTPUT_STATUS_CONNECTED;
  
      /* Use the load-detect method if we have no other way of telling. */
-     if (i830GetLoadDetectPipe(pScrn, output) != -1) {
- 	Bool connected = i830_crt_detect_load(pScrn, output);
+     crtc = i830GetLoadDetectPipe (output);
+     
+     if (crtc)
+     {
+ 	/* VESA 640x480x72Hz mode to set on the pipe */
+ 	static DisplayModeRec   mode = {
+ 	    NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+ 	    31500,
+ 	    640, 664, 704, 832, 0,
+ 	    480, 489, 491, 520, 0,
+ 	    V_NHSYNC | V_NVSYNC,
+ 	    0, 0,
+ 	    0, 0, 0, 0, 0, 0, 0,
+ 	    0, 0, 0, 0, 0, 0,
+ 	    FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+ 	};
+ 	Bool			connected;
+ 	I830OutputPrivatePtr	intel_output = output->driver_private;
+ 	
+ 	if (intel_output->load_detect_temp)
+ 	{
 -	    I830xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
++	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ 	    i830PipeSetMode (crtc, &mode, FALSE);
+ 	}
+ 	connected = i830_crt_detect_load (crtc, output);
  
- 	i830ReleaseLoadDetectPipe(pScrn, output);
+ 	i830ReleaseLoadDetectPipe (output);
  	if (connected)
  	    return OUTPUT_STATUS_CONNECTED;
  	else
diff --cc src/i830_display.c
index e2e4b6e,dd79a5e..29b783b
@@@ -366,7 -378,9 +378,9 @@@
  		   "No suitable mode found to program for the pipe.\n"
  		   "	continuing with desired mode %dx%d@%.1f\n",
  		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
 -    } else if (!I830ModesEqual(pBest, pMode)) {
 +    } else if (!xf86ModesEqual(pBest, pMode)) {
+ 	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
+ 	int		    pipe = intel_crtc->pipe;
  	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  		   "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
  		   "mode %dx%d@%.1f\n", pipe,
@@@ -434,7 -451,7 +451,7 @@@
      Bool didLock = FALSE;
  #endif
  
-     if (xf86ModesEqual(&pI830Pipe->curMode, pMode))
 -    if (I830ModesEqual(&crtc->curMode, pMode))
++    if (xf86ModesEqual(&crtc->curMode, pMode))
  	return TRUE;
  
      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
diff --cc src/i830_display.h
index 266d0b2,e491b74..c80c3f7
@@@ -25,29 -25,16 +25,30 @@@
   *
   */
  
 +#include "xorgVersion.h"
 +
  /* i830_display.c */
  DisplayModePtr
- i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
- Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+ i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
+ Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, 
  		     Bool plane_enable);
  void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
  Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
- void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
+ void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
  void i830WaitForVblank(ScrnInfoPtr pScrn);
  void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
- int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
- void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
- Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe);
++
+ xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
+ void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
+ Bool i830PipeInUse(xf86CrtcPtr crtc);
 +
 +/** @{
 + */
 +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
 +DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
 +DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
 +				Bool Reduced, Bool Interlaced);
 +#define xf86DDCGetModes i830_xf86DDCGetModes
 +#define xf86CVTMode i830_xf86CVTMode
 +#endif /* XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2) */
 +/** @} */
diff --cc src/i830_driver.c
index 61dbeea,e4d6772..c5e56e5
@@@ -850,6 -832,8 +876,7 @@@
     pointer pVBEModule = NULL;
     Bool enable;
     const char *chipname;
 -   int mem_skip;
+    int num_pipe;
  #ifdef XF86DRI
     unsigned long savedMMSize;
  #endif
diff --cc src/i830_modes.c
index 60bedad,513e233..a0d79db
@@@ -200,10 -511,10 +197,10 @@@
       * 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->num_outputs; i++) {
- 	if (pI830->output[i].probed_modes != NULL) {
- 	    pScrn->modes =
- 		xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
+     for (i = 0; i < pI830->xf86_config.num_output; i++) {
+ 	xf86OutputPtr output = pI830->xf86_config.output[i];
+ 	if (output->probed_modes != NULL) {
 -	    pScrn->modes = i830xf86DuplicateModes(pScrn, output->probed_modes);
++	    pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
  	    break;
  	}
      }
@@@ -355,11 -667,10 +353,10 @@@
  #endif
  
      /* Debug info for now, at least */
-     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n",
- 	       i830_output_type_names[output->type]);
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
      xf86PrintEDID(output->MonInfo);
  
 -    ddc_modes = i830GetDDCModes(pScrn, ddc_mon);
 +    ddc_modes = xf86DDCGetModes(pScrn->scrnIndex, ddc_mon);
  
      /* Strip out any modes that can't be supported on this output. */
      for (mode = ddc_modes; mode != NULL; mode = mode->next) {
diff --cc src/i830_randr.c
index 9def4d8,1ff2360..9ac54b5
@@@ -506,12 -516,12 +516,12 @@@
  	     * We make copies of modes, so pointer equality 
  	     * isn't sufficient
  	     */
- 	    for (j = 0; j < rrout->numModes; j++)
+ 	    for (j = 0; j < randr_output->numModes; j++)
  	    {
- 		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
- 		if (xf86ModesEqual(pipeMode, outMode))
+ 		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
 -		if (I830ModesEqual(curMode, outMode))
++		if (xf86ModesEqual(curMode, outMode))
  		{
- 		    mode = rrout->modes[j];
+ 		    randr_mode = randr_output->modes[j];
  		    break;
  		}
  	    }
@@@ -530,61 -541,39 +541,39 @@@
  		  int		num_randr_outputs,
  		  RROutputPtr	*randr_outputs)
  {
-     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
      ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
      I830Ptr		pI830 = I830PTR(pScrn);
-     int			pipe = (int) (crtc->devPrivate);
-     I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
-     DisplayModePtr	display_mode = mode ? mode->devPrivate : NULL;
+     xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
      Bool		changed = FALSE;
-     Bool		disable = FALSE;
      int			o, ro;
-     struct {
- 	int pipe;
- 	int enabled;
-     }			save_output[MAX_OUTPUTS];
-     Bool		save_enabled = pI830Pipe->enabled;
+     xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
+     Bool		save_enabled = crtc->enabled;
  
-     if (display_mode != randrp->modes[pipe])
-     {
 -    if (!I830ModesEqual (&crtc->curMode, mode))
++    if (!xf86ModesEqual (&crtc->curMode, mode))
  	changed = TRUE;
- 	if (!display_mode)
- 	    disable = TRUE;
-     }
      
-     for (o = 0; o < pI830->num_outputs; o++) 
+     for (o = 0; o < pI830->xf86_config.num_output; o++) 
      {
- 	I830OutputPtr	output = &pI830->output[o];
- 	RROutputPtr	randr_output = NULL;
+ 	xf86OutputPtr  output = pI830->xf86_config.output[o];
+ 	xf86CrtcPtr    new_crtc;
+ 
+ 	save_crtcs[o] = output->crtc;
  	
- 	save_output[o].enabled = output->enabled;
- 	save_output[o].pipe = output->pipe;
+ 	if (output->crtc == crtc)
+ 	    new_crtc = NULL;
+ 	else
+ 	    new_crtc = output->crtc;
  	for (ro = 0; ro < num_randr_outputs; ro++) 
- 	{
  	    if (output->randr_output == randr_outputs[ro])
  	    {
- 		randr_output = randr_outputs[ro];
+ 		new_crtc = crtc;
  		break;
  	    }
- 	}
- 	if (randr_output)
- 	{
- 	    if (output->pipe != pipe || !output->enabled)
- 	    {
- 		output->pipe = pipe;
- 		output->enabled = TRUE;
- 		changed = TRUE;
- 	    }
- 	}
- 	else
+ 	if (new_crtc != output->crtc)
  	{
- 	    /* Disable outputs which were on this pipe */
- 	    if (output->enabled && output->pipe == pipe)
- 	    {
- 		output->enabled = FALSE;
- 		changed = TRUE;
- 		disable = TRUE;
- 	    }
+ 	    changed = TRUE;
+ 	    output->crtc = new_crtc;
  	}
      }
      if (changed)
@@@ -889,10 -863,10 +863,10 @@@
  	    mmWidth = mmWidth * width / pScreen->width;
  	if (height != pScreen->height)
  	    mmHeight = mmHeight * height / pScreen->height;
 -	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 +	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
  		   "Setting screen physical size to %d x %d\n",
  		   mmWidth, mmHeight);
- 	I830RandRScreenSetSize (pScreen,
+ 	xf86RandR12ScreenSetSize (pScreen,
  				width,
  				height,
  				mmWidth,
diff --cc src/i830_sdvo.c
index ebf5868,c685a8d..aa06182
@@@ -80,39 -80,32 +80,42 @@@
  };
  
  /** Read a single byte from the given address on the SDVO device. */
- static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr,
+ static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
  				unsigned char *ch)
  {
-     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+     I830OutputPrivatePtr    intel_output = output->driver_private;
+     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
  
      if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
- 	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+ 	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
 -		   "Unable to read from %s slave %d.\n",
 +		   "Unable to read from %s slave 0x%02x.\n",
- 		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ 		   intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
  	return FALSE;
      }
      return TRUE;
  }
  
 +/** Read a single byte from the given address on the SDVO device. */
- static Bool i830_sdvo_read_byte_quiet(I830OutputPtr output, int addr,
++static Bool i830_sdvo_read_byte_quiet(xf86OutputPtr output, int addr,
 +				      unsigned char *ch)
 +{
-     struct i830_sdvo_priv *dev_priv = output->dev_priv;
++    I830OutputPrivatePtr    intel_output = output->driver_private;
++    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 +
 +    return xf86I2CReadByte(&dev_priv->d, addr, ch);
 +}
 +
  /** Write a single byte to the given address on the SDVO device. */
- static Bool i830_sdvo_write_byte(I830OutputPtr output,
+ static Bool i830_sdvo_write_byte(xf86OutputPtr output,
  				 int addr, unsigned char ch)
  {
-     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+     I830OutputPrivatePtr    intel_output = output->driver_private;
+     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
  
      if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
- 	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
- 		   "Unable to write to %s Slave %02x.\n",
- 		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+ 	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
 -		   "Unable to write to %s Slave %d.\n",
++		   "Unable to write to %s Slave 0x%02x.\n",
+ 		   intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
  	return FALSE;
      }
      return TRUE;
@@@ -1026,22 -1071,6 +1081,20 @@@
  	return;
      }
  
-     output->pI2CBus = i2cbus;
-     output->dev_priv = dev_priv;
++    intel_output->pI2CBus = i2cbus;
++    intel_output->dev_priv = dev_priv;
 +
 +    /* Read the regs to test if we can talk to the device */
 +    for (i = 0; i < 0x40; i++) {
 +	if (!i830_sdvo_read_byte_quiet(output, i, &ch[i])) {
 +	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 +		       "No SDVO device found on SDVO%c\n",
 +		       output_device == SDVOB ? 'B' : 'C');
- 	    xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
- 	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
- 	    xfree(dev_priv);
++	    xf86OutputDestroy (output);
 +	    return;
 +	}
 +    }
 +
      /* Set up our wrapper I2C bus for DDC.  It acts just like the regular I2C
       * bus, except that it does the control bus switch to DDC mode before every
       * Start.  While we only need to do it at Start after every Stop after a
@@@ -1064,15 -1092,26 +1116,18 @@@
      ddcbus->I2CStart = i830_sdvo_ddc_i2c_start;
      ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop;
      ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address;
-     ddcbus->DriverPrivate.ptr = &pI830->output[pI830->num_outputs];
-     if (!xf86I2CBusInit(ddcbus)) {
- 	xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
- 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
- 	xfree(dev_priv);
+     ddcbus->DriverPrivate.ptr = output;
+     
+     if (!xf86I2CBusInit(ddcbus)) 
+     {
+ 	xf86OutputDestroy (output);
  	return;
      }
-     output->pDDCBus = ddcbus;
+ 
+     intel_output->pI2CBus = i2cbus;
+     intel_output->pDDCBus = ddcbus;
+     intel_output->dev_priv = dev_priv;
  
 -    /* Read the regs to test if we can talk to the device */
 -    for (i = 0; i < 0x40; i++) {
 -	if (!i830_sdvo_read_byte(output, i, &ch[i])) {
 -	    xf86OutputDestroy (output);
 -	    return;
 -	}
 -    }
 -
      i830_sdvo_get_capabilities(output, &dev_priv->caps);
  
      memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
diff --cc src/i830_tv.c
index f938d5c,c219250..f7d9207
@@@ -501,9 -546,34 +546,34 @@@
   * we have a pipe programmed in order to probe the TV.
   */
  static enum detect_status
- i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+ i830_tv_detect(xf86OutputPtr output)
  {
-     return OUTPUT_STATUS_CONNECTED;
+     xf86CrtcPtr	    crtc;
+     DisplayModeRec	    mode;
+     I830OutputPrivatePtr    intel_output = output->driver_private;
+     int			    type;
+ 
+     crtc = i830GetLoadDetectPipe (output);
+     if (!crtc)
+ 	return OUTPUT_STATUS_UNKNOWN;
+     
+     if (intel_output->load_detect_temp)
+     {
+ 	mode = tvModes[0];
 -	I830xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
++	xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+ 	i830PipeSetMode (crtc, &mode, FALSE);
+     }
+     type = i830_tv_detect_type (crtc, output);
+     i830ReleaseLoadDetectPipe (output);
+     
+     switch (type) {
+     case TV_TYPE_NONE:
+ 	return OUTPUT_STATUS_DISCONNECTED;
+     case TV_TYPE_UNKNOWN:
+ 	return OUTPUT_STATUS_UNKNOWN;
+     default:
+ 	return OUTPUT_STATUS_CONNECTED;
+     }
  }
  
  /**
diff --cc src/i830_xf86Modes.c
index 809acf5,ca92e4d..c091aef
@@@ -526,3 -530,112 +526,27 @@@
  	mode = next;
      }
  }
+ 
 -#define MODEPREFIX(name) NULL, NULL, name, MODE_OK, M_T_DEFAULT
 -#define MODESUFFIX       0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
 -
+ /**
 - * List of VESA established modes, taken from xf86DefaultModes but trimmed down.
 - * (not trimming should be harmless).
++ * Adds the new mode into the mode list, and returns the new list
++ *
++ * \param modes doubly-linked mode list.
+  */
 -DisplayModeRec I830xf86DefaultModes[] = {
 -/* 640x350 @ 85Hz (VESA) hsync: 37.9kHz */
 -	{MODEPREFIX("640x350"),31500, 640,672,736,832,0, 350,382,385,445,0, V_PHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("320x175"),15750, 320,336,368,416,0, 175,191,192,222,0, V_PHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 640x400 @ 85Hz (VESA) hsync: 37.9kHz */
 -	{MODEPREFIX("640x400"),31500, 640,672,736,832,0, 400,401,404,445,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("320x200"),15750, 320,336,368,416,0, 200,200,202,222,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 720x400 @ 85Hz (VESA) hsync: 37.9kHz */
 -	{MODEPREFIX("720x400"),35500, 720,756,828,936,0, 400,401,404,446,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("360x200"),17750, 360,378,414,468,0, 200,200,202,223,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 640x480 @ 72Hz (VESA) hsync: 37.9kHz */
 -	{MODEPREFIX("640x480"),31500, 640,664,704,832,0, 480,489,491,520,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("320x240"),15750, 320,332,352,416,0, 240,244,245,260,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 640x480 @ 75Hz (VESA) hsync: 37.5kHz */
 -	{MODEPREFIX("640x480"),31500, 640,656,720,840,0, 480,481,484,500,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("320x240"),15750, 320,328,360,420,0, 240,240,242,250,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 640x480 @ 85Hz (VESA) hsync: 43.3kHz */
 -	{MODEPREFIX("640x480"),36000, 640,696,752,832,0, 480,481,484,509,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("320x240"),18000, 320,348,376,416,0, 240,240,242,254,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 800x600 @ 56Hz (VESA) hsync: 35.2kHz */
 -	{MODEPREFIX("800x600"),36000, 800,824,896,1024,0, 600,601,603,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("400x300"),18000, 400,412,448,512,0, 300,300,301,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 800x600 @ 60Hz (VESA) hsync: 37.9kHz */
 -	{MODEPREFIX("800x600"),40000, 800,840,968,1056,0, 600,601,605,628,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("400x300"),20000, 400,420,484,528,0, 300,300,302,314,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 800x600 @ 72Hz (VESA) hsync: 48.1kHz */
 -	{MODEPREFIX("800x600"),50000, 800,856,976,1040,0, 600,637,643,666,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("400x300"),25000, 400,428,488,520,0, 300,318,321,333,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 800x600 @ 75Hz (VESA) hsync: 46.9kHz */
 -	{MODEPREFIX("800x600"),49500, 800,816,896,1056,0, 600,601,604,625,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("400x300"),24750, 400,408,448,528,0, 300,300,302,312,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 800x600 @ 85Hz (VESA) hsync: 53.7kHz */
 -	{MODEPREFIX("800x600"),56300, 800,832,896,1048,0, 600,601,604,631,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("400x300"),28150, 400,416,448,524,0, 300,300,302,315,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1024x768 @ 60Hz (VESA) hsync: 48.4kHz */
 -	{MODEPREFIX("1024x768"),65000, 1024,1048,1184,1344,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("512x384"),32500, 512,524,592,672,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1024x768 @ 70Hz (VESA) hsync: 56.5kHz */
 -	{MODEPREFIX("1024x768"),75000, 1024,1048,1184,1328,0, 768,771,777,806,0, V_NHSYNC | V_NVSYNC, MODESUFFIX},
 -	{MODEPREFIX("512x384"),37500, 512,524,592,664,0, 384,385,388,403,0, V_NHSYNC | V_NVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1024x768 @ 75Hz (VESA) hsync: 60.0kHz */
 -	{MODEPREFIX("1024x768"),78800, 1024,1040,1136,1312,0, 768,769,772,800,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("512x384"),39400, 512,520,568,656,0, 384,384,386,400,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1024x768 @ 85Hz (VESA) hsync: 68.7kHz */
 -	{MODEPREFIX("1024x768"),94500, 1024,1072,1168,1376,0, 768,769,772,808,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("512x384"),47250, 512,536,584,688,0, 384,384,386,404,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1152x864 @ 75Hz (VESA) hsync: 67.5kHz */
 -	{MODEPREFIX("1152x864"),108000, 1152,1216,1344,1600,0, 864,865,868,900,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("576x432"),54000, 576,608,672,800,0, 432,432,434,450,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1280x960 @ 60Hz (VESA) hsync: 60.0kHz */
 -	{MODEPREFIX("1280x960"),108000, 1280,1376,1488,1800,0, 960,961,964,1000,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("640x480"),54000, 640,688,744,900,0, 480,480,482,500,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1280x960 @ 85Hz (VESA) hsync: 85.9kHz */
 -	{MODEPREFIX("1280x960"),148500, 1280,1344,1504,1728,0, 960,961,964,1011,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("640x480"),74250, 640,672,752,864,0, 480,480,482,505,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1280x1024 @ 60Hz (VESA) hsync: 64.0kHz */
 -	{MODEPREFIX("1280x1024"),108000, 1280,1328,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("640x512"),54000, 640,664,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1280x1024 @ 75Hz (VESA) hsync: 80.0kHz */
 -	{MODEPREFIX("1280x1024"),135000, 1280,1296,1440,1688,0, 1024,1025,1028,1066,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("640x512"),67500, 640,648,720,844,0, 512,512,514,533,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1280x1024 @ 85Hz (VESA) hsync: 91.1kHz */
 -	{MODEPREFIX("1280x1024"),157500, 1280,1344,1504,1728,0, 1024,1025,1028,1072,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("640x512"),78750, 640,672,752,864,0, 512,512,514,536,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1600x1200 @ 60Hz (VESA) hsync: 75.0kHz */
 -	{MODEPREFIX("1600x1200"),162000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("800x600"),81000, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1600x1200 @ 65Hz (VESA) hsync: 81.3kHz */
 -	{MODEPREFIX("1600x1200"),175500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("800x600"),87750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1600x1200 @ 70Hz (VESA) hsync: 87.5kHz */
 -	{MODEPREFIX("1600x1200"),189000, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("800x600"),94500, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1600x1200 @ 75Hz (VESA) hsync: 93.8kHz */
 -	{MODEPREFIX("1600x1200"),202500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("800x600"),101250, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1600x1200 @ 85Hz (VESA) hsync: 106.3kHz */
 -	{MODEPREFIX("1600x1200"),229500, 1600,1664,1856,2160,0, 1200,1201,1204,1250,0, V_PHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("800x600"),114750, 800,832,928,1080,0, 600,600,602,625,0, V_PHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1792x1344 @ 60Hz (VESA) hsync: 83.6kHz */
 -	{MODEPREFIX("1792x1344"),204800, 1792,1920,2120,2448,0, 1344,1345,1348,1394,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("896x672"),102400, 896,960,1060,1224,0, 672,672,674,697,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1792x1344 @ 75Hz (VESA) hsync: 106.3kHz */
 -	{MODEPREFIX("1792x1344"),261000, 1792,1888,2104,2456,0, 1344,1345,1348,1417,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("896x672"),130500, 896,944,1052,1228,0, 672,672,674,708,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1856x1392 @ 60Hz (VESA) hsync: 86.3kHz */
 -	{MODEPREFIX("1856x1392"),218300, 1856,1952,2176,2528,0, 1392,1393,1396,1439,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("928x696"),109150, 928,976,1088,1264,0, 696,696,698,719,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1856x1392 @ 75Hz (VESA) hsync: 112.5kHz */
 -	{MODEPREFIX("1856x1392"),288000, 1856,1984,2208,2560,0, 1392,1393,1396,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("928x696"),144000, 928,992,1104,1280,0, 696,696,698,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1920x1440 @ 60Hz (VESA) hsync: 90.0kHz */
 -	{MODEPREFIX("1920x1440"),234000, 1920,2048,2256,2600,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("960x720"),117000, 960,1024,1128,1300,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -/* 1920x1440 @ 75Hz (VESA) hsync: 112.5kHz */
 -	{MODEPREFIX("1920x1440"),297000, 1920,2064,2288,2640,0, 1440,1441,1444,1500,0, V_NHSYNC | V_PVSYNC, MODESUFFIX},
 -	{MODEPREFIX("960x720"),148500, 960,1032,1144,1320,0, 720,720,722,750,0, V_NHSYNC | V_PVSYNC | V_DBLSCAN, MODESUFFIX},
 -
 -	/* Terminator */
 -	{MODEPREFIX(NULL), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX}
 -};
++DisplayModePtr
++xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new)
++{
++    if (modes == NULL)
++	return new;
++
++    if (new) {
++	DisplayModePtr mode = modes;
++
++	while (mode->next)
++	    mode = mode->next;
++
++	mode->next = new;
++	new->prev = mode;
++    }
++
++    return modes;
++}
diff --cc src/i830_xf86Modes.h
index d057ef5,30b926a..3bd8557
@@@ -25,27 -25,29 +25,32 @@@
   *
   */
  
+ #ifndef _I830_XF86MODES_H_
+ #define _I830_XF86MODES_H_
 +#include "xorgVersion.h"
  
 -double
 -i830xf86ModeHSync(DisplayModePtr mode);
 -
 -double
 -i830xf86ModeVRefresh(DisplayModePtr mode);
 -
 -DisplayModePtr
 -i830xf86DuplicateMode(DisplayModePtr pMode);
 -
 -DisplayModePtr
 -i830xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList);
 -
 -void
 -i830xf86SetModeDefaultName(DisplayModePtr mode);
 -
 -void
 -I830xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
 -
 -Bool
 -I830ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
 +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,1,99,2,0)
 +double i830_xf86ModeHSync(DisplayModePtr mode);
 +double i830_xf86ModeVRefresh(DisplayModePtr mode);
 +DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode);
 +DisplayModePtr i830_xf86DuplicateModes(ScrnInfoPtr pScrn,
 +				       DisplayModePtr modeList);
 +void i830_xf86SetModeDefaultName(DisplayModePtr mode);
 +void i830_xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
 +Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
 +void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
++DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
++
 +#define xf86ModeHSync i830_xf86ModeHSync
 +#define xf86ModeVRefresh i830_xf86ModeVRefresh
 +#define xf86DuplicateMode i830_xf86DuplicateMode
 +#define xf86DuplicateModes i830_xf86DuplicateModes
 +#define xf86SetModeDefaultName i830_xf86SetModeDefaultName
 +#define xf86SetModeCrtc i830_xf86SetModeCrtc
 +#define xf86ModesEqual i830_xf86ModesEqual
 +#define xf86PrintModeline i830_xf86PrintModeline
++#define xf86ModesAdd i830_xf86ModesAdd
 +#endif /* XORG_VERSION_CURRENT <= 7.1.99.2 */
  
  void
  i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
@@@ -73,3 -75,10 +78,5 @@@
  
  void
  i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+ 
 -void
 -PrintModeline(int scrnIndex,DisplayModePtr mode);
 -
 -extern DisplayModeRec I830xf86DefaultModes[];
 -
+ #endif /* _I830_XF86MODES_H_ */
diff-tree 16e01b117bb7ae90b150dd4f25a887dd895cf473 (from bcf206ff17c6eca8212db72dd86fcd8fdc0162da)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 30 11:55:29 2006 -0800

    Oops. Don't try to use xf86RandR names, use xf86RandR12 instead.
    
    Attempts to override functions in core server fail, so use
    new names instead.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index b4333c4..e4d6772 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1584,7 +1584,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   if (!xf86RandRPreInit (pScrn))
+   if (!xf86RandR12PreInit (pScrn))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
@@ -2613,7 +2613,7 @@ I830CreateScreenResources (ScreenPtr pSc
    if (!(*pScreen->CreateScreenResources)(pScreen))
       return FALSE;
 
-   if (!xf86RandRCreateScreenResources (pScreen))
+   if (!xf86RandR12CreateScreenResources (pScreen))
       return FALSE;
 
    return TRUE;
@@ -3156,11 +3156,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       xf86DisableRandR(); /* Disable built-in RandR extension */
       shadowSetup(pScreen);
       /* support all rotations */
-      xf86RandRInit (pScreen);
+      xf86RandR12Init (pScreen);
       if (IS_I965G(pI830)) {
-	 xf86RandRSetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
+	 xf86RandR12SetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
       } else {
-	 xf86RandRSetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
+	 xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
       }
       pI830->PointerMoved = pScrn->PointerMoved;
       pScrn->PointerMoved = I830PointerMoved;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7b48794..513e233 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -519,7 +519,7 @@ i830_set_xf86_modes_from_outputs(ScrnInf
 	}
     }
 
-    xf86GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
+    xf86RandR12GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
 
     /* Disable modes in the XFree86 DDX list that are larger than the current
      * virtual size.
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 38ac320..1ff2360 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -44,7 +44,7 @@
 #include "i830_display.h"
 #include "i830.h"
 
-typedef struct _xf86RandRInfo {
+typedef struct _xf86RandR12Info {
     int				    virtualX;
     int				    virtualY;
     int				    mmWidth;
@@ -56,18 +56,18 @@ typedef struct _xf86RandRInfo {
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
 
 #ifdef RANDR_12_INTERFACE
-static Bool xf86RandRInit12 (ScreenPtr pScreen);
-static Bool xf86RandRCreateScreenResources12 (ScreenPtr pScreen);
+static Bool xf86RandR12Init12 (ScreenPtr pScreen);
+static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
 #endif
 
-static int	    xf86RandRIndex;
-static int	    xf86RandRGeneration;
+static int	    xf86RandR12Index;
+static int	    xf86RandR12Generation;
 
 #define XF86RANDRINFO(p) \
-	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandRIndex].ptr)
+	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
 
 static int
-xf86RandRModeRefresh (DisplayModePtr mode)
+xf86RandR12ModeRefresh (DisplayModePtr mode)
 {
     if (mode->VRefresh)
 	return (int) (mode->VRefresh + 0.5);
@@ -76,7 +76,7 @@ xf86RandRModeRefresh (DisplayModePtr mod
 }
 
 static Bool
-xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
 {
     RRScreenSizePtr	    pSize;
     ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
@@ -98,7 +98,7 @@ xf86RandRGetInfo (ScreenPtr pScreen, Rot
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
-	int refresh = xf86RandRModeRefresh (mode);
+	int refresh = xf86RandR12ModeRefresh (mode);
 	if (randrp->maxX == 0 || randrp->maxY == 0)
 	{
 		if (maxX < mode->HDisplay)
@@ -152,7 +152,7 @@ xf86RandRGetInfo (ScreenPtr pScreen, Rot
 }
 
 static Bool
-xf86RandRSetMode (ScreenPtr	    pScreen,
+xf86RandR12SetMode (ScreenPtr	    pScreen,
 		  DisplayModePtr    mode,
 		  Bool		    useVirtual,
 		  int		    mmWidth,
@@ -241,7 +241,7 @@ xf86RandRSetMode (ScreenPtr	    pScreen,
 }
 
 Bool
-xf86RandRSetConfig (ScreenPtr		pScreen,
+xf86RandR12SetConfig (ScreenPtr		pScreen,
 		    Rotation		rotation,
 		    int			rate,
 		    RRScreenSizePtr	pSize)
@@ -274,7 +274,7 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 	}
 	if (mode->HDisplay == pSize->width &&
 	    mode->VDisplay == pSize->height &&
-	    (rate == 0 || xf86RandRModeRefresh (mode) == rate))
+	    (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
 	    break;
 	if (mode->next == scrp->modes)
 	{
@@ -300,7 +300,7 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 	randrp->maxY = maxY;
     }
 
-    if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+    if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
 			   pSize->mmHeight)) {
         randrp->rotation = oldRotation;
 	return FALSE;
@@ -323,7 +323,7 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 }
 
 Rotation
-xf86RandRGetRotation(ScreenPtr pScreen)
+xf86RandR12GetRotation(ScreenPtr pScreen)
 {
     XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
 
@@ -331,7 +331,7 @@ xf86RandRGetRotation(ScreenPtr pScreen)
 }
 
 Bool
-xf86RandRCreateScreenResources (ScreenPtr pScreen)
+xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 {
 #if 0
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -343,7 +343,7 @@ xf86RandRCreateScreenResources (ScreenPt
 	return TRUE;
 #endif
 #if RANDR_12_INTERFACE
-    if (xf86RandRCreateScreenResources12 (pScreen))
+    if (xf86RandR12CreateScreenResources12 (pScreen))
 	return TRUE;
 #endif
 #if 0
@@ -361,7 +361,7 @@ xf86RandRCreateScreenResources (ScreenPt
 	p.mmHeight = pScreen->mmHeight;
 
 	pI830->starting = TRUE; /* abuse this for dual head & rotation */
-	xf86RandRSetConfig (pScreen, requestedRotation, 0, &p);
+	xf86RandR12SetConfig (pScreen, requestedRotation, 0, &p);
 	pI830->starting = FALSE;
     }
 #endif
@@ -370,7 +370,7 @@ xf86RandRCreateScreenResources (ScreenPt
 
 
 Bool
-xf86RandRInit (ScreenPtr pScreen)
+xf86RandR12Init (ScreenPtr pScreen)
 {
     rrScrPrivPtr	rp;
     XF86RandRInfoPtr	randrp;
@@ -380,10 +380,10 @@ xf86RandRInit (ScreenPtr pScreen)
     if (!noPanoramiXExtension)
 	return TRUE;
 #endif
-    if (xf86RandRGeneration != serverGeneration)
+    if (xf86RandR12Generation != serverGeneration)
     {
-	xf86RandRIndex = AllocateScreenPrivateIndex();
-	xf86RandRGeneration = serverGeneration;
+	xf86RandR12Index = AllocateScreenPrivateIndex();
+	xf86RandR12Generation = serverGeneration;
     }
 
     randrp = xalloc (sizeof (XF86RandRInfoRec));
@@ -396,8 +396,8 @@ xf86RandRInit (ScreenPtr pScreen)
 	return FALSE;
     }
     rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = xf86RandRGetInfo;
-    rp->rrSetConfig = xf86RandRSetConfig;
+    rp->rrGetInfo = xf86RandR12GetInfo;
+    rp->rrSetConfig = xf86RandR12SetConfig;
 
     randrp->virtualX = -1;
     randrp->virtualY = -1;
@@ -410,17 +410,17 @@ xf86RandRInit (ScreenPtr pScreen)
 
     randrp->maxX = randrp->maxY = 0;
 
-    pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
+    pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
 
 #if RANDR_12_INTERFACE
-    if (!xf86RandRInit12 (pScreen))
+    if (!xf86RandR12Init12 (pScreen))
 	return FALSE;
 #endif
     return TRUE;
 }
 
 void
-xf86RandRSetRotations (ScreenPtr pScreen, Rotation rotations)
+xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
 
@@ -428,11 +428,11 @@ xf86RandRSetRotations (ScreenPtr pScreen
 }
 
 void
-xf86GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
 {
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
 
-    if (xf86RandRGeneration != serverGeneration ||
+    if (xf86RandR12Generation != serverGeneration ||
 	XF86RANDRINFO(pScreen)->virtualX == -1)
     {
 	*x = pScrn->virtualX;
@@ -447,7 +447,7 @@ xf86GetOriginalVirtualSize(ScrnInfoPtr p
 
 #if RANDR_12_INTERFACE
 static Bool
-xf86RandRScreenSetSize (ScreenPtr	pScreen,
+xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
 			CARD16		width,
 			CARD16		height,
 			CARD32		mmWidth,
@@ -483,7 +483,7 @@ xf86RandRScreenSetSize (ScreenPtr	pScree
 }
 
 static Bool
-xf86RandRCrtcNotify (RRCrtcPtr	randr_crtc)
+xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 {
     ScreenPtr		pScreen = randr_crtc->pScreen;
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -532,7 +532,7 @@ xf86RandRCrtcNotify (RRCrtcPtr	randr_crt
 }
 
 static Bool
-xf86RandRCrtcSet (ScreenPtr	pScreen,
+xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		  RRCrtcPtr	randr_crtc,
 		  RRModePtr	randr_mode,
 		  int		x,
@@ -603,11 +603,11 @@ xf86RandRCrtcSet (ScreenPtr	pScreen,
 	}
 	i830DisableUnusedFunctions (pScrn);
     }
-    return xf86RandRCrtcNotify (randr_crtc);
+    return xf86RandR12CrtcNotify (randr_crtc);
 }
 
 static Bool
-xf86RandRCrtcSetGamma (ScreenPtr    pScreen,
+xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
 		       RRCrtcPtr    crtc)
 {
     return FALSE;
@@ -677,7 +677,7 @@ I830xf86RROutputSetModes (RROutputPtr ra
  * Mirror the current mode configuration to RandR
  */
 static Bool
-xf86RandRSetInfo12 (ScrnInfoPtr pScrn)
+xf86RandR12SetInfo12 (ScrnInfoPtr pScrn)
 {
     I830Ptr		    pI830 = I830PTR(pScrn);
     RROutputPtr		    clones[MAX_OUTPUTS];
@@ -787,16 +787,16 @@ xf86RandRSetInfo12 (ScrnInfoPtr pScrn)
  * that to RandR
  */
 static Bool
-xf86RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
     i830_reprobe_output_modes(pScrn);
-    return xf86RandRSetInfo12 (pScrn);
+    return xf86RandR12SetInfo12 (pScrn);
 }
 
 static Bool
-xf86RandRCreateObjects12 (ScrnInfoPtr pScrn)
+xf86RandR12CreateObjects12 (ScrnInfoPtr pScrn)
 {
     I830Ptr		pI830 = I830PTR(pScrn);
     int			p;
@@ -818,7 +818,7 @@ xf86RandRCreateObjects12 (ScrnInfoPtr pS
 }
 
 static Bool
-xf86RandRCreateScreenResources12 (ScreenPtr pScreen)
+xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -866,7 +866,7 @@ xf86RandRCreateScreenResources12 (Screen
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Setting screen physical size to %d x %d\n",
 		   mmWidth, mmHeight);
-	xf86RandRScreenSetSize (pScreen,
+	xf86RandR12ScreenSetSize (pScreen,
 				width,
 				height,
 				mmWidth,
@@ -874,7 +874,7 @@ xf86RandRCreateScreenResources12 (Screen
     }
 
     for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	xf86RandRCrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
+	xf86RandR12CrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -888,22 +888,22 @@ xf86RandRCreateScreenResources12 (Screen
 }
 
 static void
-xf86RandRPointerMoved (int scrnIndex, int x, int y)
+xf86RandR12PointerMoved (int scrnIndex, int x, int y)
 {
 }
 
 static Bool
-xf86RandRInit12 (ScreenPtr pScreen)
+xf86RandR12Init12 (ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
 
-    rp->rrGetInfo = xf86RandRGetInfo12;
-    rp->rrScreenSetSize = xf86RandRScreenSetSize;
-    rp->rrCrtcSet = xf86RandRCrtcSet;
-    rp->rrCrtcSetGamma = xf86RandRCrtcSetGamma;
+    rp->rrGetInfo = xf86RandR12GetInfo12;
+    rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
+    rp->rrCrtcSet = xf86RandR12CrtcSet;
+    rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
     rp->rrSetConfig = NULL;
-    pScrn->PointerMoved = xf86RandRPointerMoved;
+    pScrn->PointerMoved = xf86RandR12PointerMoved;
     return TRUE;
 }
 
@@ -1169,7 +1169,7 @@ I830RRDefaultScreenLimits (RROutputPtr *
 #endif
 
 Bool
-xf86RandRPreInit (ScrnInfoPtr pScrn)
+xf86RandR12PreInit (ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 #if RANDR_12_INTERFACE
@@ -1188,13 +1188,13 @@ xf86RandRPreInit (ScrnInfoPtr pScrn)
     i830_reprobe_output_modes(pScrn);
 
 #if RANDR_12_INTERFACE
-    if (!xf86RandRCreateObjects12 (pScrn))
+    if (!xf86RandR12CreateObjects12 (pScrn))
 	return FALSE;
 
     /*
      * Configure output modes
      */
-    if (!xf86RandRSetInfo12 (pScrn))
+    if (!xf86RandR12SetInfo12 (pScrn))
 	return FALSE;
     /*
      * With RandR info set up, let RandR choose
diff --git a/src/i830_randr.h b/src/i830_randr.h
index 8c6af92..8a4668b 100644
--- a/src/i830_randr.h
+++ b/src/i830_randr.h
@@ -25,13 +25,13 @@
 #include <randrstr.h>
 #include <X11/extensions/render.h>
 
-Bool xf86RandRCreateScreenResources (ScreenPtr pScreen);
-Bool xf86RandRInit(ScreenPtr pScreen);
-void xf86RandRSetRotations (ScreenPtr pScreen, Rotation rotation);
-Bool xf86RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
+Bool xf86RandR12Init(ScreenPtr pScreen);
+void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
+Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
 			RRScreenSizePtr pSize);
-Rotation xf86RandRGetRotation(ScreenPtr pScreen);
-void xf86GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
-Bool xf86RandRPreInit (ScrnInfoPtr pScrn);
+Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
+void xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+Bool xf86RandR12PreInit (ScrnInfoPtr pScrn);
 
 #endif /* _XF86_RANDR_H_ */
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 1427c24..891a8f7 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -757,7 +757,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       pScrn2 = pScrn;
    }
 
-   pI830->rotation = xf86RandRGetRotation(pScrn->pScreen);
+   pI830->rotation = xf86RandR12GetRotation(pScrn->pScreen);
 
    /* Check if we've still got the same orientation, or same mode */
    if (pI830->rotation == oldRotation && pI830->currentMode == mode)
diff-tree bcf206ff17c6eca8212db72dd86fcd8fdc0162da (from parents)
Merge: 27ca1c17aab30670dd1d07e0809fd58cdecfc3b6 2c8c310bd8a105dbeda5c989dca31cc766eb6bb8
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 30 11:39:56 2006 -0800

    Merge branch 'restructure-outputs-origin' into restructure-outputs

diff --cc src/i830.h
index 1b0b305,4e8e8de..14adb3c
@@@ -58,9 -58,7 +58,8 @@@
  #include "xf86int10.h"
  #include "vbe.h"
  #include "vgaHW.h"
- #include "randrstr.h"
  #include "i830_xf86Crtc.h"
 +#include "i830_randr.h"
  
  #ifdef XF86DRI
  #include "xf86drm.h"
diff-tree 27ca1c17aab30670dd1d07e0809fd58cdecfc3b6 (from e8d1db326388c9a112f2b8e2eff5a81210b8d6e4)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 30 11:39:37 2006 -0800

    Rename I830 randr functions to xf86 as they are becoming generic.
    
    Change function names, create separate i830_randr.h header file
    to contain definitions.

diff --git a/src/i830.h b/src/i830.h
index e88cd43..1b0b305 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -60,6 +60,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "vgaHW.h"
 #include "randrstr.h"
 #include "i830_xf86Crtc.h"
+#include "i830_randr.h"
 
 #ifdef XF86DRI
 #include "xf86drm.h"
@@ -606,15 +607,6 @@ void i830_set_xf86_modes_from_outputs(Sc
 void i830_set_default_screen_size(ScrnInfoPtr pScrn);
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
 
-/* i830_randr.c */
-Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
-Bool I830RandRInit(ScreenPtr pScreen, int rotation);
-Bool I830RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
-			RRScreenSizePtr pSize);
-Rotation I830GetRotation(ScreenPtr pScreen);
-void I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
-Bool I830RandRPreInit (ScrnInfoPtr pScrn);
-
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 50a5da0..6b7439a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1585,7 +1585,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
 	      "Maximum frambuffer space: %d kByte\n", pScrn->videoRam);
 
-   if (!I830RandRPreInit (pScrn))
+   if (!xf86RandRPreInit (pScrn))
    {
       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
       PreInitCleanup(pScrn);
@@ -2614,7 +2614,7 @@ I830CreateScreenResources (ScreenPtr pSc
    if (!(*pScreen->CreateScreenResources)(pScreen))
       return FALSE;
 
-   if (!I830RandRCreateScreenResources (pScreen))
+   if (!xf86RandRCreateScreenResources (pScreen))
       return FALSE;
 
    return TRUE;
@@ -3157,10 +3157,11 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       xf86DisableRandR(); /* Disable built-in RandR extension */
       shadowSetup(pScreen);
       /* support all rotations */
+      xf86RandRInit (pScreen);
       if (IS_I965G(pI830)) {
-	 I830RandRInit(pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
+	 xf86RandRSetRotations (pScreen, RR_Rotate_0); /* only 0 degrees for I965G */
       } else {
-	 I830RandRInit(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
+	 xf86RandRSetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
       }
       pI830->PointerMoved = pScrn->PointerMoved;
       pScrn->PointerMoved = I830PointerMoved;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 19ea05c..7b48794 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -519,7 +519,7 @@ i830_set_xf86_modes_from_outputs(ScrnInf
 	}
     }
 
-    I830GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
+    xf86GetOriginalVirtualSize(pScrn, &originalVirtualX, &originalVirtualY);
 
     /* Disable modes in the XFree86 DDX list that are larger than the current
      * virtual size.
diff --git a/src/i830_randr.c b/src/i830_randr.c
index ec0a2ec..38ac320 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -39,11 +39,12 @@
 #include <randrstr.h>
 #include <X11/extensions/render.h>
 
-#include "i830.h"
-#include "i830_xf86Modes.h"
+#include "i830_xf86Crtc.h"
+#include "i830_randr.h"
 #include "i830_display.h"
+#include "i830.h"
 
-typedef struct _i830RandRInfo {
+typedef struct _xf86RandRInfo {
     int				    virtualX;
     int				    virtualY;
     int				    mmWidth;
@@ -55,18 +56,18 @@ typedef struct _i830RandRInfo {
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
 
 #ifdef RANDR_12_INTERFACE
-static Bool I830RandRInit12 (ScreenPtr pScreen);
-static Bool I830RandRCreateScreenResources12 (ScreenPtr pScreen);
+static Bool xf86RandRInit12 (ScreenPtr pScreen);
+static Bool xf86RandRCreateScreenResources12 (ScreenPtr pScreen);
 #endif
 
-static int	    i830RandRIndex;
-static int	    i830RandRGeneration;
+static int	    xf86RandRIndex;
+static int	    xf86RandRGeneration;
 
 #define XF86RANDRINFO(p) \
-	((XF86RandRInfoPtr)(p)->devPrivates[i830RandRIndex].ptr)
+	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandRIndex].ptr)
 
 static int
-I830RandRModeRefresh (DisplayModePtr mode)
+xf86RandRModeRefresh (DisplayModePtr mode)
 {
     if (mode->VRefresh)
 	return (int) (mode->VRefresh + 0.5);
@@ -75,7 +76,7 @@ I830RandRModeRefresh (DisplayModePtr mod
 }
 
 static Bool
-I830RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
 {
     RRScreenSizePtr	    pSize;
     ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
@@ -97,7 +98,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 
     for (mode = scrp->modes; ; mode = mode->next)
     {
-	int refresh = I830RandRModeRefresh (mode);
+	int refresh = xf86RandRModeRefresh (mode);
 	if (randrp->maxX == 0 || randrp->maxY == 0)
 	{
 		if (maxX < mode->HDisplay)
@@ -151,7 +152,7 @@ I830RandRGetInfo (ScreenPtr pScreen, Rot
 }
 
 static Bool
-I830RandRSetMode (ScreenPtr	    pScreen,
+xf86RandRSetMode (ScreenPtr	    pScreen,
 		  DisplayModePtr    mode,
 		  Bool		    useVirtual,
 		  int		    mmWidth,
@@ -240,7 +241,7 @@ I830RandRSetMode (ScreenPtr	    pScreen,
 }
 
 Bool
-I830RandRSetConfig (ScreenPtr		pScreen,
+xf86RandRSetConfig (ScreenPtr		pScreen,
 		    Rotation		rotation,
 		    int			rate,
 		    RRScreenSizePtr	pSize)
@@ -273,7 +274,7 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 	}
 	if (mode->HDisplay == pSize->width &&
 	    mode->VDisplay == pSize->height &&
-	    (rate == 0 || I830RandRModeRefresh (mode) == rate))
+	    (rate == 0 || xf86RandRModeRefresh (mode) == rate))
 	    break;
 	if (mode->next == scrp->modes)
 	{
@@ -299,7 +300,7 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 	randrp->maxY = maxY;
     }
 
-    if (!I830RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+    if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth,
 			   pSize->mmHeight)) {
         randrp->rotation = oldRotation;
 	return FALSE;
@@ -322,7 +323,7 @@ I830RandRSetConfig (ScreenPtr		pScreen,
 }
 
 Rotation
-I830GetRotation(ScreenPtr pScreen)
+xf86RandRGetRotation(ScreenPtr pScreen)
 {
     XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
 
@@ -330,19 +331,23 @@ I830GetRotation(ScreenPtr pScreen)
 }
 
 Bool
-I830RandRCreateScreenResources (ScreenPtr pScreen)
+xf86RandRCreateScreenResources (ScreenPtr pScreen)
 {
+#if 0
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
-    I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr		pI830 = I830PTR(pScrn);
+#endif
 #ifdef PANORAMIX
     /* XXX disable RandR when using Xinerama */
     if (!noPanoramiXExtension)
 	return TRUE;
 #endif
 #if RANDR_12_INTERFACE
-    if (I830RandRCreateScreenResources12 (pScreen))
+    if (xf86RandRCreateScreenResources12 (pScreen))
 	return TRUE;
 #endif
+#if 0
+    /* XXX deal with initial rotation */
     if (pI830->rotation != RR_Rotate_0) {
 	RRScreenSize p;
 	Rotation requestedRotation = pI830->rotation;
@@ -356,15 +361,16 @@ I830RandRCreateScreenResources (ScreenPt
 	p.mmHeight = pScreen->mmHeight;
 
 	pI830->starting = TRUE; /* abuse this for dual head & rotation */
-	I830RandRSetConfig (pScreen, requestedRotation, 0, &p);
+	xf86RandRSetConfig (pScreen, requestedRotation, 0, &p);
 	pI830->starting = FALSE;
     }
+#endif
     return TRUE;
 }
 
 
 Bool
-I830RandRInit (ScreenPtr    pScreen, int rotation)
+xf86RandRInit (ScreenPtr pScreen)
 {
     rrScrPrivPtr	rp;
     XF86RandRInfoPtr	randrp;
@@ -374,10 +380,10 @@ I830RandRInit (ScreenPtr    pScreen, int
     if (!noPanoramiXExtension)
 	return TRUE;
 #endif
-    if (i830RandRGeneration != serverGeneration)
+    if (xf86RandRGeneration != serverGeneration)
     {
-	i830RandRIndex = AllocateScreenPrivateIndex();
-	i830RandRGeneration = serverGeneration;
+	xf86RandRIndex = AllocateScreenPrivateIndex();
+	xf86RandRGeneration = serverGeneration;
     }
 
     randrp = xalloc (sizeof (XF86RandRInfoRec));
@@ -390,8 +396,8 @@ I830RandRInit (ScreenPtr    pScreen, int
 	return FALSE;
     }
     rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = I830RandRGetInfo;
-    rp->rrSetConfig = I830RandRSetConfig;
+    rp->rrGetInfo = xf86RandRGetInfo;
+    rp->rrSetConfig = xf86RandRSetConfig;
 
     randrp->virtualX = -1;
     randrp->virtualY = -1;
@@ -400,25 +406,33 @@ I830RandRInit (ScreenPtr    pScreen, int
 
     randrp->rotation = RR_Rotate_0; /* initial rotated mode */
 
-    randrp->supported_rotations = rotation;
+    randrp->supported_rotations = RR_Rotate_0;
 
     randrp->maxX = randrp->maxY = 0;
 
-    pScreen->devPrivates[i830RandRIndex].ptr = randrp;
+    pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
 
 #if RANDR_12_INTERFACE
-    if (!I830RandRInit12 (pScreen))
+    if (!xf86RandRInit12 (pScreen))
 	return FALSE;
 #endif
     return TRUE;
 }
 
 void
-I830GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+xf86RandRSetRotations (ScreenPtr pScreen, Rotation rotations)
+{
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+
+    randrp->supported_rotations = rotations;
+}
+
+void
+xf86GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
 {
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
 
-    if (i830RandRGeneration != serverGeneration ||
+    if (xf86RandRGeneration != serverGeneration ||
 	XF86RANDRINFO(pScreen)->virtualX == -1)
     {
 	*x = pScrn->virtualX;
@@ -433,7 +447,7 @@ I830GetOriginalVirtualSize(ScrnInfoPtr p
 
 #if RANDR_12_INTERFACE
 static Bool
-I830RandRScreenSetSize (ScreenPtr	pScreen,
+xf86RandRScreenSetSize (ScreenPtr	pScreen,
 			CARD16		width,
 			CARD16		height,
 			CARD32		mmWidth,
@@ -469,7 +483,7 @@ I830RandRScreenSetSize (ScreenPtr	pScree
 }
 
 static Bool
-I830RandRCrtcNotify (RRCrtcPtr	randr_crtc)
+xf86RandRCrtcNotify (RRCrtcPtr	randr_crtc)
 {
     ScreenPtr		pScreen = randr_crtc->pScreen;
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -518,7 +532,7 @@ I830RandRCrtcNotify (RRCrtcPtr	randr_crt
 }
 
 static Bool
-I830RandRCrtcSet (ScreenPtr	pScreen,
+xf86RandRCrtcSet (ScreenPtr	pScreen,
 		  RRCrtcPtr	randr_crtc,
 		  RRModePtr	randr_mode,
 		  int		x,
@@ -589,11 +603,11 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	}
 	i830DisableUnusedFunctions (pScrn);
     }
-    return I830RandRCrtcNotify (randr_crtc);
+    return xf86RandRCrtcNotify (randr_crtc);
 }
 
 static Bool
-I830RandRCrtcSetGamma (ScreenPtr    pScreen,
+xf86RandRCrtcSetGamma (ScreenPtr    pScreen,
 		       RRCrtcPtr    crtc)
 {
     return FALSE;
@@ -663,7 +677,7 @@ I830xf86RROutputSetModes (RROutputPtr ra
  * Mirror the current mode configuration to RandR
  */
 static Bool
-I830RandRSetInfo12 (ScrnInfoPtr pScrn)
+xf86RandRSetInfo12 (ScrnInfoPtr pScrn)
 {
     I830Ptr		    pI830 = I830PTR(pScrn);
     RROutputPtr		    clones[MAX_OUTPUTS];
@@ -773,16 +787,16 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
  * that to RandR
  */
 static Bool
-I830RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+xf86RandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
 
     i830_reprobe_output_modes(pScrn);
-    return I830RandRSetInfo12 (pScrn);
+    return xf86RandRSetInfo12 (pScrn);
 }
 
 static Bool
-I830RandRCreateObjects12 (ScrnInfoPtr pScrn)
+xf86RandRCreateObjects12 (ScrnInfoPtr pScrn)
 {
     I830Ptr		pI830 = I830PTR(pScrn);
     int			p;
@@ -804,7 +818,7 @@ I830RandRCreateObjects12 (ScrnInfoPtr pS
 }
 
 static Bool
-I830RandRCreateScreenResources12 (ScreenPtr pScreen)
+xf86RandRCreateScreenResources12 (ScreenPtr pScreen)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -852,7 +866,7 @@ I830RandRCreateScreenResources12 (Screen
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Setting screen physical size to %d x %d\n",
 		   mmWidth, mmHeight);
-	I830RandRScreenSetSize (pScreen,
+	xf86RandRScreenSetSize (pScreen,
 				width,
 				height,
 				mmWidth,
@@ -860,7 +874,7 @@ I830RandRCreateScreenResources12 (Screen
     }
 
     for (p = 0; p < pI830->xf86_config.num_crtc; p++)
-	I830RandRCrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
+	xf86RandRCrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -874,22 +888,22 @@ I830RandRCreateScreenResources12 (Screen
 }
 
 static void
-I830RandRPointerMoved (int scrnIndex, int x, int y)
+xf86RandRPointerMoved (int scrnIndex, int x, int y)
 {
 }
 
 static Bool
-I830RandRInit12 (ScreenPtr pScreen)
+xf86RandRInit12 (ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
 
-    rp->rrGetInfo = I830RandRGetInfo12;
-    rp->rrScreenSetSize = I830RandRScreenSetSize;
-    rp->rrCrtcSet = I830RandRCrtcSet;
-    rp->rrCrtcSetGamma = I830RandRCrtcSetGamma;
+    rp->rrGetInfo = xf86RandRGetInfo12;
+    rp->rrScreenSetSize = xf86RandRScreenSetSize;
+    rp->rrCrtcSet = xf86RandRCrtcSet;
+    rp->rrCrtcSetGamma = xf86RandRCrtcSetGamma;
     rp->rrSetConfig = NULL;
-    pScrn->PointerMoved = I830RandRPointerMoved;
+    pScrn->PointerMoved = xf86RandRPointerMoved;
     return TRUE;
 }
 
@@ -1155,7 +1169,7 @@ I830RRDefaultScreenLimits (RROutputPtr *
 #endif
 
 Bool
-I830RandRPreInit (ScrnInfoPtr pScrn)
+xf86RandRPreInit (ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 #if RANDR_12_INTERFACE
@@ -1174,13 +1188,13 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     i830_reprobe_output_modes(pScrn);
 
 #if RANDR_12_INTERFACE
-    if (!I830RandRCreateObjects12 (pScrn))
+    if (!xf86RandRCreateObjects12 (pScrn))
 	return FALSE;
 
     /*
      * Configure output modes
      */
-    if (!I830RandRSetInfo12 (pScrn))
+    if (!xf86RandRSetInfo12 (pScrn))
 	return FALSE;
     /*
      * With RandR info set up, let RandR choose
diff --git a/src/i830_randr.h b/src/i830_randr.h
new file mode 100644
index 0000000..8c6af92
--- /dev/null
+++ b/src/i830_randr.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _XF86_RANDR_H_
+#define _XF86_RANDR_H_
+#include <randrstr.h>
+#include <X11/extensions/render.h>
+
+Bool xf86RandRCreateScreenResources (ScreenPtr pScreen);
+Bool xf86RandRInit(ScreenPtr pScreen);
+void xf86RandRSetRotations (ScreenPtr pScreen, Rotation rotation);
+Bool xf86RandRSetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
+			RRScreenSizePtr pSize);
+Rotation xf86RandRGetRotation(ScreenPtr pScreen);
+void xf86GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+Bool xf86RandRPreInit (ScrnInfoPtr pScrn);
+
+#endif /* _XF86_RANDR_H_ */
diff --git a/src/i830_rotate.c b/src/i830_rotate.c
index 0471b55..1427c24 100644
--- a/src/i830_rotate.c
+++ b/src/i830_rotate.c
@@ -757,7 +757,7 @@ I830Rotate(ScrnInfoPtr pScrn, DisplayMod
       pScrn2 = pScrn;
    }
 
-   pI830->rotation = I830GetRotation(pScrn->pScreen);
+   pI830->rotation = xf86RandRGetRotation(pScrn->pScreen);
 
    /* Check if we've still got the same orientation, or same mode */
    if (pI830->rotation == oldRotation && pI830->currentMode == mode)
diff-tree 2c8c310bd8a105dbeda5c989dca31cc766eb6bb8 (from c421724d8151d1d4578468abdbe8fe1120e373ca)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Nov 27 22:18:59 2006 -0800

    Driver-independent code tracks num_crtc itself, don't do it in driver.
    
    Now that driver-independent code manages array of crtcs, let it track
    the count and just have the driver compute how many there are in
    a separate variable.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index 50a5da0..9207c92 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -675,12 +675,11 @@ static const xf86CrtcFuncsRec i830_crtc_
 };
 
 static void
-I830SetupCrtcs(ScrnInfoPtr pScrn)
+I830SetupCrtcs(ScrnInfoPtr pScrn, int num_pipe)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
     int	    p;
 
-    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
+    for (p = 0; p < num_pipe; p++)
     {
 	xf86CrtcPtr    crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
 	I830CrtcPrivatePtr  intel_crtc;
@@ -691,7 +690,6 @@ I830SetupCrtcs(ScrnInfoPtr pScrn)
 	intel_crtc->pipe = p;
 	
 	crtc->driver_private = intel_crtc;
-	pI830->xf86_config.crtc[p] = crtc;
     }
 }
     
@@ -835,6 +833,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    Bool enable;
    const char *chipname;
    int mem_skip;
+   int num_pipe;
 #ifdef XF86DRI
    unsigned long savedMMSize;
 #endif
@@ -1142,14 +1141,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
-      pI830->xf86_config.num_crtc = 1;
+      num_pipe = 1;
    else
    if (IS_MOBILE(pI830) || IS_I9XX(pI830))
-      pI830->xf86_config.num_crtc = 2;
+      num_pipe = 2;
    else
-      pI830->xf86_config.num_crtc = 1;
+      num_pipe = 1;
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
-	      pI830->xf86_config.num_crtc, pI830->xf86_config.num_crtc > 1 ? "s" : "");
+	      num_pipe, num_pipe > 1 ? "s" : "");
 
    /*
     * Get the pre-allocated (stolen) memory size.
@@ -1268,10 +1267,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 
    I830PreInitDDC(pScrn);
    I830SetupOutputs(pScrn);
-   I830SetupCrtcs(pScrn);
+   I830SetupCrtcs(pScrn, num_pipe);
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
-      if (pI830->xf86_config.num_crtc == 1) {
+      if (num_pipe == 1) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
  		 "Can't enable Clone Mode because this is a single pipe device\n");
          PreInitCleanup(pScrn);
@@ -1293,7 +1292,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
     */
    for (i = 0; i < pI830->xf86_config.num_output; i++) 
    {
-      xf86OutputPtr      output = pI830->xf86_config.output[i];
+      xf86OutputPtr	      output = pI830->xf86_config.output[i];
       I830OutputPrivatePtr    intel_output = output->driver_private;
       xf86CrtcPtr	      crtc;
       int		      p;
diff-tree c421724d8151d1d4578468abdbe8fe1120e373ca (from e8d1db326388c9a112f2b8e2eff5a81210b8d6e4)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Nov 27 22:15:40 2006 -0800

    Move #include "randrstr.h" from i830.h to i830_xf86Crtc.h
    
    As part of the separation of driver-dependent from driver-independent code,
    the interactions with RandR are moving entirely out of the driver, which
    means the driver shouldn't even know about RandR, while the
    driver-independent code does.

diff --git a/src/i830.h b/src/i830.h
index e88cd43..4e8e8de 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -58,7 +58,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "xf86int10.h"
 #include "vbe.h"
 #include "vgaHW.h"
-#include "randrstr.h"
 #include "i830_xf86Crtc.h"
 
 #ifdef XF86DRI
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 1f9a03e..2952c8d 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -23,6 +23,7 @@
 #define _XF86CRTC_H_
 
 #include <edid.h>
+#include "randrstr.h"
 #include "i830_xf86Modes.h"
 
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
diff-tree e8d1db326388c9a112f2b8e2eff5a81210b8d6e4 (from a0518f5a440630365b1d935b7c2d0725f326ad51)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Nov 27 12:01:47 2006 -0800

    Move crtc/output config to sub-structure.
    
    Place crtc/output in separate structure at head
    of driver private structure. Use this from the config code
    to make it driver-independent. Still lots of effectively driver
    independent code that continues to use driver dependent stuff,
    but that will change.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53a063f..5ec671f 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1098,6 +1098,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * This is used for load detection in combination with TVDAC_SENSE_MASK
  */
 # define TV_TEST_MODE_MONITOR_DETECT	(7 << 0)
+# define TV_TEST_MODE_MASK		(7 << 0)
 /** @} */
 
 /** @defgroup TV_DAC
diff --git a/src/i830.h b/src/i830.h
index 2f106c7..e88cd43 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -208,100 +208,6 @@ typedef struct _I830OutputPrivateRec {
 
 #define I830OutputPrivate(o) ((I830OutputPrivatePtr) (o)->driver_private)
 
-struct _I830OutputRec {
-   int type;
-   int pipe;
-   Bool enabled;
-   /**
-    * Marks that the output and associated pipe is temporarily enabled for
-    * load detection.
-    */
-   Bool load_detect_temp;
-
-   /**
-    * Turns the output on/off, or sets intermediate power levels if available.
-    *
-    * Unsupported intermediate modes drop to the lower power setting.  If the
-    * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
-    * disabled afterwards.
-    */
-   void (*dpms)(ScrnInfoPtr pScrn, I830OutputPtr output, int mode);
-
-   /**
-    * Saves the output's state for restoration on VT switch.
-    */
-   void (*save)(ScrnInfoPtr pScrn, I830OutputPtr output);
-
-   /**
-    * Restore's the output's state at VT switch.
-    */
-   void (*restore)(ScrnInfoPtr pScrn, I830OutputPtr output);
-
-   /**
-    * Callback for testing a video mode for a given output.
-    *
-    * This function should only check for cases where a mode can't be supported
-    * on the pipe specifically, and not represent generic CRTC limitations.
-    *
-    * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
-    */
-   int (*mode_valid)(ScrnInfoPtr pScrn, I830OutputPtr output,
-		     DisplayModePtr pMode);
-
-   /**
-    * Callback for setting up a video mode before any pipe/dpll changes.
-    *
-    * \param pMode the mode that will be set, or NULL if the mode to be set is
-    * unknown (such as the restore path of VT switching).
-    */
-   void (*pre_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
-			DisplayModePtr pMode);
-
-   /**
-    * Callback for setting up a video mode after the DPLL update but before
-    * the plane is enabled.
-    */
-   void (*post_set_mode)(ScrnInfoPtr pScrn, I830OutputPtr output,
-			 DisplayModePtr pMode);
-
-   /**
-    * Probe for a connected output, and return detect_status.
-    */
-   enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
-
-   /**
-    * Query the device for the modes it provides.
-    *
-    * This function may also update MonInfo, mm_width, and mm_height.
-    *
-    * \return singly-linked list of modes or NULL if no modes found.
-    */
-   DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output);
-
-   /**
-    * List of available modes on this output.
-    *
-    * This should be the list from get_modes(), plus perhaps additional
-    * compatible modes added later.
-    */
-   DisplayModePtr probed_modes;
-
-   /** EDID monitor information */
-   xf86MonPtr MonInfo;
-
-   /** Physical size of the output currently attached. */
-   int mm_width, mm_height;
-
-   I2CBusPtr pI2CBus;
-   I2CBusPtr pDDCBus;
-   struct _I830DVODriver *i2c_drv;
-   /** Output-private structure.  Should replace i2c_drv */
-   void *dev_priv;
-#ifdef RANDR_12_INTERFACE
-   RROutputPtr randr_output;
-#endif
-};
-
 typedef struct _I830PipeRec {
    Bool		  enabled;
    Bool		  gammaEnabled;
@@ -317,6 +223,9 @@ typedef struct _I830PipeRec {
 } I830PipeRec, *I830PipePtr;
 
 typedef struct _I830Rec {
+   /* Must be first */
+   xf86CrtcConfigRec	xf86_config;
+    
    unsigned char *MMIOBase;
    unsigned char *FbBase;
    int cpp;
@@ -333,9 +242,6 @@ typedef struct _I830Rec {
    int CloneVDisplay;
 
    I830EntPtr entityPrivate;	
-#if 0
-   int pipe, origPipe;
-#endif
    int init;
 
    unsigned int bufferOffset;		/* for I830SelectBuffer */
@@ -487,17 +393,6 @@ typedef struct _I830Rec {
 
    Bool checkDevices;
 
-   /* XXX outputs and crtcs need to move to ScrnInfoRec */
-   int num_outputs;
-/*   struct _I830OutputRec output[MAX_OUTPUTS]; */
-   I830_xf86OutputPtr	xf86_output[MAX_OUTPUTS];
-    
-   /* [0] is Pipe A, [1] is Pipe B. */
-   int num_pipes;
-   /* [0] is display plane A, [1] is display plane B. */
-/*   I830PipeRec	  pipes[MAX_DISPLAY_PIPES]; */
-   I830_xf86CrtcPtr  xf86_crtc[MAX_DISPLAY_PIPES];
-   
    /* Driver phase/state information */
    Bool preinit;
    Bool starting;
@@ -604,7 +499,7 @@ extern void I830PrintErrorState(ScrnInfo
 extern void I965PrintErrorState(ScrnInfoPtr pScrn);
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
-extern void I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force);
+extern void I830SetPipeCursor (xf86CrtcPtr crtc, Bool force);
 extern Bool I830CursorInit(ScreenPtr pScreen);
 extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
@@ -685,7 +580,7 @@ extern Bool I830I2CInit(ScrnInfoPtr pScr
 
 /* i830_display.c */
 Bool
-i830PipeHasType (I830_xf86CrtcPtr crtc, int type);
+i830PipeHasType (xf86CrtcPtr crtc, int type);
 
 /* i830_crt.c */
 void i830_crt_init(ScrnInfoPtr pScrn);
@@ -709,7 +604,7 @@ int I830ValidateXF86ModeList(ScrnInfoPtr
 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(I830_xf86OutputPtr output);
+DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
 
 /* i830_randr.c */
 Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 716afbc..37a5b3f 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -35,7 +35,7 @@
 #include "i830_display.h"
 
 static void
-i830_crt_dpms(I830_xf86OutputPtr output, int mode)
+i830_crt_dpms(xf86OutputPtr output, int mode)
 {
     ScrnInfoPtr	    pScrn = output->scrn;
     I830Ptr	    pI830 = I830PTR(pScrn);
@@ -64,7 +64,7 @@ i830_crt_dpms(I830_xf86OutputPtr output,
 }
 
 static void
-i830_crt_save (I830_xf86OutputPtr output)
+i830_crt_save (xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -73,7 +73,7 @@ i830_crt_save (I830_xf86OutputPtr output
 }
 
 static void
-i830_crt_restore (I830_xf86OutputPtr output)
+i830_crt_restore (xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -82,7 +82,7 @@ i830_crt_restore (I830_xf86OutputPtr out
 }
 
 static int
-i830_crt_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_crt_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
@@ -94,16 +94,16 @@ i830_crt_mode_valid(I830_xf86OutputPtr o
 }
 
 static void
-i830_crt_pre_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_crt_pre_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
 {
 }
 
 static void
-i830_crt_post_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_crt_post_set_mode (xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	    crtc = output->crtc;
+    xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    i830_crtc = crtc->driver_private;
     int			    dpll_md_reg;
     CARD32		    adpa, dpll_md;
@@ -146,7 +146,7 @@ i830_crt_post_set_mode (I830_xf86OutputP
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_hotplug(I830_xf86OutputPtr output)
+i830_crt_detect_hotplug(xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -185,8 +185,8 @@ i830_crt_detect_hotplug(I830_xf86OutputP
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_load (I830_xf86CrtcPtr	    crtc,
-		      I830_xf86OutputPtr    output)
+i830_crt_detect_load (xf86CrtcPtr	    crtc,
+		      xf86OutputPtr    output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -257,7 +257,7 @@ i830_crt_detect_load (I830_xf86CrtcPtr	 
  * \return FALSE if no DDC response was detected.
  */
 static Bool
-i830_crt_detect_ddc(I830_xf86OutputPtr output)
+i830_crt_detect_ddc(xf86OutputPtr output)
 {
     I830OutputPrivatePtr    i830_output = output->driver_private;
 
@@ -275,11 +275,11 @@ i830_crt_detect_ddc(I830_xf86OutputPtr o
  *        on active displays.
  */
 static enum detect_status
-i830_crt_detect(I830_xf86OutputPtr output)
+i830_crt_detect(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	    crtc;
+    xf86CrtcPtr	    crtc;
 
     if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
 	if (i830_crt_detect_hotplug(output))
@@ -329,7 +329,7 @@ i830_crt_detect(I830_xf86OutputPtr outpu
 }
 
 static DisplayModePtr
-i830_crt_get_modes(I830_xf86OutputPtr output)
+i830_crt_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr		pScrn = output->scrn;
     DisplayModePtr	modes;
@@ -361,13 +361,13 @@ i830_crt_get_modes(I830_xf86OutputPtr ou
 }
 
 static void
-i830_crt_destroy (I830_xf86OutputPtr output)
+i830_crt_destroy (xf86OutputPtr output)
 {
     if (output->driver_private)
 	xfree (output->driver_private);
 }
 
-static const I830_xf86OutputFuncsRec i830_crt_output_funcs = {
+static const xf86OutputFuncsRec i830_crt_output_funcs = {
     .dpms = i830_crt_dpms,
     .save = i830_crt_save,
     .restore = i830_crt_restore,
@@ -382,16 +382,16 @@ static const I830_xf86OutputFuncsRec i83
 void
 i830_crt_init(ScrnInfoPtr pScrn)
 {
-    I830_xf86OutputPtr	    output;
+    xf86OutputPtr	    output;
     I830OutputPrivatePtr    i830_output;
 
-    output = i830xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
+    output = xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
     if (!output)
 	return;
     i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
     if (!i830_output)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     i830_output->type = I830_OUTPUT_ANALOG;
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index a3526f8..e9ca8f1 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -80,7 +80,7 @@ static Bool I830UseHWCursorARGB(ScreenPt
 #endif
 
 static void
-I830SetPipeCursorBase (I830_xf86CrtcPtr crtc)
+I830SetPipeCursorBase (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr		pScrn = crtc->scrn;
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
@@ -89,7 +89,7 @@ I830SetPipeCursorBase (I830_xf86CrtcPtr 
     int			cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
     I830MemRange	*cursor_mem;
 
-    if (pipe >= pI830->num_pipes)
+    if (pipe >= pI830->xf86_config.num_crtc)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
@@ -105,7 +105,7 @@ I830SetPipeCursorBase (I830_xf86CrtcPtr 
 }
 
 void
-I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force)
+I830SetPipeCursor (xf86CrtcPtr crtc, Bool force)
 {
     ScrnInfoPtr		pScrn = crtc->scrn;
     I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
@@ -185,12 +185,12 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
    int i;
 
    DPRINTF(PFX, "I830InitHWCursor\n");
-   for (i = 0; i < pI830->num_pipes; i++) 
-      pI830->xf86_crtc[i]->cursorShown = FALSE;
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++) 
+      pI830->xf86_config.crtc[i]->cursorShown = FALSE;
 
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
-      for (i = 0; i < pI830->num_pipes; i++)
+      for (i = 0; i < pI830->xf86_config.num_crtc; i++)
       {
 	 int   cursor_control = i == 0 ? CURSOR_A_CONTROL : CURSOR_B_CONTROL;
 	 temp = INREG(cursor_control);
@@ -204,7 +204,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 	    temp |= CURSOR_MODE_64_4C_AX;
 	 /* Need to set control, then address. */
 	 OUTREG(cursor_control, temp);
-	 I830SetPipeCursorBase(pI830->xf86_crtc[i]);
+	 I830SetPipeCursorBase(pI830->xf86_config.crtc[i]);
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
@@ -217,7 +217,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
       /* This initialises the format and leave the cursor disabled. */
       OUTREG(CURSOR_CONTROL, temp);
       /* Need to set address and size after disabling. */
-      I830SetPipeCursorBase(pI830->xf86_crtc[0]);
+      I830SetPipeCursorBase(pI830->xf86_config.crtc[0]);
       temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
 	     ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
       OUTREG(CURSOR_SIZE, temp);
@@ -490,9 +490,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     x -= hotspotx;
     y -= hotspoty;
 
-    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
+    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
     {
-	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[pipe];
+	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[pipe];
 	DisplayModePtr	    mode = &crtc->curMode;
 	int		    thisx = x - crtc->x;
 	int		    thisy = y - crtc->y;
@@ -556,8 +556,8 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
 
     pI830->cursorOn = TRUE;
-    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
-	I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE);
+    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
+	I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
 }
 
 static void
@@ -569,8 +569,8 @@ I830HideCursor(ScrnInfoPtr pScrn)
    DPRINTF(PFX, "I830HideCursor\n");
 
    pI830->cursorOn = FALSE;
-    for (pipe = 0; pipe < pI830->num_pipes; pipe++)
-	I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE);
+    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
+	I830SetPipeCursor (pI830->xf86_config.crtc[pipe], TRUE);
 }
 
 static void
@@ -587,9 +587,9 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   for (pipe = 0; pipe < pI830->num_pipes; pipe++)
+   for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++)
    {
-      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[pipe];
+      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[pipe];
       int		pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0;
 
       if (crtc->enabled)
diff --git a/src/i830_display.c b/src/i830_display.c
index ba59f56..dd79a5e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -64,15 +64,15 @@ i830PrintPll(char *prefix, int refclk, i
  * Returns whether any output on the specified pipe is of the specified type
  */
 Bool
-i830PipeHasType (I830_xf86CrtcPtr crtc, int type)
+i830PipeHasType (xf86CrtcPtr crtc, int type)
 {
     ScrnInfoPtr	pScrn = crtc->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
     int		i;
 
-    for (i = 0; i < pI830->num_outputs; i++)
+    for (i = 0; i < pI830->xf86_config.num_output; i++)
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	xf86OutputPtr  output = pI830->xf86_config.output[i];
 	if (output->crtc == crtc)
 	{
 	    I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -91,7 +91,7 @@ i830PipeHasType (I830_xf86CrtcPtr crtc, 
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830PllIsValid(I830_xf86CrtcPtr crtc, int refclk, int m1, int m2,
+i830PllIsValid(xf86CrtcPtr crtc, int refclk, int m1, int m2,
 	       int n, int p1, int p2)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
@@ -177,7 +177,7 @@ i830PllIsValid(I830_xf86CrtcPtr crtc, in
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830FindBestPLL(I830_xf86CrtcPtr crtc, int target, int refclk,
+i830FindBestPLL(xf86CrtcPtr crtc, int target, int refclk,
 		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
@@ -262,7 +262,7 @@ i830WaitForVblank(ScrnInfoPtr pScreen)
 }
 
 void
-i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y)
+i830PipeSetBase(xf86CrtcPtr crtc, int x, int y)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -300,7 +300,7 @@ i830PipeSetBase(I830_xf86CrtcPtr crtc, i
  * - Closer in refresh rate to the requested mode.
  */
 DisplayModePtr
-i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode)
+i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode)
 {
     ScrnInfoPtr	pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -308,9 +308,9 @@ i830PipeFindClosestMode(I830_xf86CrtcPtr
     int i;
 
     /* Assume that there's only one output connected to the given CRTC. */
-    for (i = 0; i < pI830->num_outputs; i++) 
+    for (i = 0; i < pI830->xf86_config.num_output; i++) 
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	xf86OutputPtr  output = pI830->xf86_config.output[i];
 	if (output->crtc == crtc && output->probed_modes != NULL)
 	{
 	    pScan = output->probed_modes;
@@ -396,14 +396,14 @@ i830PipeFindClosestMode(I830_xf86CrtcPtr
  */
 
 Bool
-i830PipeInUse (I830_xf86CrtcPtr crtc)
+i830PipeInUse (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     int	i;
     
-    for (i = 0; i < pI830->num_outputs; i++)
-	if (pI830->xf86_output[i]->crtc == crtc)
+    for (i = 0; i < pI830->xf86_config.num_output; i++)
+	if (pI830->xf86_config.output[i]->crtc == crtc)
 	    return TRUE;
     return FALSE;
 }
@@ -417,7 +417,7 @@ i830PipeInUse (I830_xf86CrtcPtr crtc)
  * display data.
  */
 Bool
-i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode,
+i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
 		Bool plane_enable)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
@@ -469,9 +469,9 @@ i830PipeSetMode(I830_xf86CrtcPtr crtc, D
     didLock = I830DRILock(pScrn);
 #endif
     
-    for (i = 0; i < pI830->num_outputs; i++) 
+    for (i = 0; i < pI830->xf86_config.num_output; i++) 
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	xf86OutputPtr  output = pI830->xf86_config.output[i];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	if (output->crtc != crtc)
 	    continue;
@@ -694,8 +694,8 @@ i830PipeSetMode(I830_xf86CrtcPtr crtc, D
 	    OUTREG(PFIT_CONTROL, 0);
     }
 
-    for (i = 0; i < pI830->num_outputs; i++) {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr  output = pI830->xf86_config.output[i];
 	if (output->crtc == crtc)
 	    (*output->funcs->post_set_mode)(output, pMode);
     }
@@ -740,9 +740,9 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
-    for (o = 0; o < pI830->num_outputs; o++) 
+    for (o = 0; o < pI830->xf86_config.num_output; o++) 
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[o];
+	xf86OutputPtr  output = pI830->xf86_config.output[o];
 	if (!output->crtc)
 	    (*output->funcs->dpms)(output, DPMSModeOff);
     }
@@ -751,9 +751,9 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
      * internal TV) should have no outputs trying to pull data out of it, so
      * we're ready to turn those off.
      */
-    for (pipe = 0; pipe < pI830->num_pipes; pipe++) 
+    for (pipe = 0; pipe < pI830->xf86_config.num_crtc; pipe++) 
     {
-	I830_xf86CrtcPtr crtc = pI830->xf86_crtc[pipe];
+	xf86CrtcPtr crtc = pI830->xf86_config.crtc[pipe];
 	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
 	int		    pipe = intel_crtc->pipe;
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
@@ -807,9 +807,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     DPRINTF(PFX, "i830SetMode\n");
 
-    for (i = 0; i < pI830->num_pipes; i++)
+    for (i = 0; i < pI830->xf86_config.num_crtc; i++)
     {
-	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[i];
+	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[i];
 	ok = i830PipeSetMode(crtc,
 			     i830PipeFindClosestMode(crtc, pMode), 
 			     TRUE);
@@ -832,9 +832,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	/* If we might have enabled/disabled some pipes, we need to reset
 	 * cloning mode support.
 	 */
-	if (pI830->num_pipes >= 2 && 
-	    pI830->xf86_crtc[0]->enabled &&
-	    pI830->xf86_crtc[1]->enabled)
+	if (pI830->xf86_config.num_crtc >= 2 && 
+	    pI830->xf86_config.crtc[0]->enabled &&
+	    pI830->xf86_config.crtc[1]->enabled)
 	    pI830->Clone = TRUE;
 	else
 	    pI830->Clone = FALSE;
@@ -865,8 +865,8 @@ i830DescribeOutputConfiguration(ScrnInfo
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
 
-    for (i = 0; i < pI830->num_pipes; i++) {
-	I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i];
+    for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
+	xf86CrtcPtr crtc = pI830->xf86_config.crtc[i];
 	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
 	CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
 	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
@@ -896,9 +896,9 @@ i830DescribeOutputConfiguration(ScrnInfo
 	}
     }
 
-    for (i = 0; i < pI830->num_outputs; i++) {
-	I830_xf86OutputPtr	output = pI830->xf86_output[i];
-	I830_xf86CrtcPtr	crtc = output->crtc;
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr	output = pI830->xf86_config.output[i];
+	xf86CrtcPtr	crtc = output->crtc;
 	I830CrtcPrivatePtr	intel_crtc = crtc ? crtc->driver_private : NULL;
 	
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -922,26 +922,26 @@ i830DescribeOutputConfiguration(ScrnInfo
  * \return crtc, or NULL if no pipes are available.
  */
     
-I830_xf86CrtcPtr
-i830GetLoadDetectPipe(I830_xf86OutputPtr output)
+xf86CrtcPtr
+i830GetLoadDetectPipe(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
     I830OutputPrivatePtr    intel_output = output->driver_private;
-    I830_xf86CrtcPtr	    crtc;
+    xf86CrtcPtr	    crtc;
     int			    i;
 
     if (output->crtc) 
 	return output->crtc;
 
-    for (i = 0; i < pI830->num_pipes; i++)
-	if (!i830PipeInUse(pI830->xf86_crtc[i]))
+    for (i = 0; i < pI830->xf86_config.num_crtc; i++)
+	if (!i830PipeInUse(pI830->xf86_config.crtc[i]))
 	    break;
 
-    if (i == pI830->num_pipes)
+    if (i == pI830->xf86_config.num_crtc)
 	return NULL;
 
-    crtc = pI830->xf86_crtc[i];
+    crtc = pI830->xf86_config.crtc[i];
 
     output->crtc = crtc;
     intel_output->load_detect_temp = TRUE;
@@ -950,7 +950,7 @@ i830GetLoadDetectPipe(I830_xf86OutputPtr
 }
 
 void
-i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output)
+i830ReleaseLoadDetectPipe(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
diff --git a/src/i830_display.h b/src/i830_display.h
index 4409728..e491b74 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -27,14 +27,14 @@
 
 /* i830_display.c */
 DisplayModePtr
-i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode);
-Bool i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode, 
+i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
+Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, 
 		     Bool plane_enable);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
-void i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y);
+void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
-I830_xf86CrtcPtr i830GetLoadDetectPipe(I830_xf86OutputPtr output);
-void i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output);
-Bool i830PipeInUse(I830_xf86CrtcPtr crtc);
+xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
+void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
+Bool i830PipeInUse(xf86CrtcPtr crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index af34afc..d88b0bc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1513,7 +1513,7 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->num_pipes > 1 && pI830->xf86_crtc[1]->enabled)
+	    if (pI830->xf86_config.num_crtc > 1 && pI830->xf86_config.crtc[1]->enabled)
 		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
 	    else
 		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 4d6e816..50a5da0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -548,9 +548,9 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
    pI830 = I830PTR(pScrn);
 
-   for(p=0; p < pI830->num_pipes; p++) 
+   for(p=0; p < pI830->xf86_config.num_crtc; p++) 
    {
-      I830_xf86CrtcPtr	   crtc = pI830->xf86_crtc[p];
+      xf86CrtcPtr	   crtc = pI830->xf86_config.crtc[p];
       I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
 
       if (p == 0) {
@@ -671,7 +671,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
  * Setup the CRTCs
  */
 
-static const I830_xf86CrtcFuncsRec i830_crtc_funcs = {
+static const xf86CrtcFuncsRec i830_crtc_funcs = {
 };
 
 static void
@@ -680,9 +680,9 @@ I830SetupCrtcs(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     int	    p;
 
-    for (p = 0; p < pI830->num_pipes; p++)
+    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
     {
-	I830_xf86CrtcPtr    crtc = i830xf86CrtcCreate (pScrn, &i830_crtc_funcs);
+	xf86CrtcPtr    crtc = xf86CrtcCreate (pScrn, &i830_crtc_funcs);
 	I830CrtcPrivatePtr  intel_crtc;
 	
 	if (!crtc)
@@ -691,7 +691,7 @@ I830SetupCrtcs(ScrnInfoPtr pScrn)
 	intel_crtc->pipe = p;
 	
 	crtc->driver_private = intel_crtc;
-	pI830->xf86_crtc[p] = crtc;
+	pI830->xf86_config.crtc[p] = crtc;
     }
 }
     
@@ -1142,14 +1142,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G)
-      pI830->num_pipes = 1;
+      pI830->xf86_config.num_crtc = 1;
    else
    if (IS_MOBILE(pI830) || IS_I9XX(pI830))
-      pI830->num_pipes = 2;
+      pI830->xf86_config.num_crtc = 2;
    else
-      pI830->num_pipes = 1;
+      pI830->xf86_config.num_crtc = 1;
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n",
-	      pI830->num_pipes, pI830->num_pipes > 1 ? "s" : "");
+	      pI830->xf86_config.num_crtc, pI830->xf86_config.num_crtc > 1 ? "s" : "");
 
    /*
     * Get the pre-allocated (stolen) memory size.
@@ -1271,7 +1271,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    I830SetupCrtcs(pScrn);
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
-      if (pI830->num_pipes == 1) {
+      if (pI830->xf86_config.num_crtc == 1) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
  		 "Can't enable Clone Mode because this is a single pipe device\n");
          PreInitCleanup(pScrn);
@@ -1291,11 +1291,11 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Perform the pipe assignment of outputs. This is a kludge until
     * we have better configuration support in the generic RandR code
     */
-   for (i = 0; i < pI830->num_outputs; i++) 
+   for (i = 0; i < pI830->xf86_config.num_output; i++) 
    {
-      I830_xf86OutputPtr      output = pI830->xf86_output[i];
+      xf86OutputPtr      output = pI830->xf86_config.output[i];
       I830OutputPrivatePtr    intel_output = output->driver_private;
-      I830_xf86CrtcPtr	      crtc;
+      xf86CrtcPtr	      crtc;
       int		      p;
 
       output->crtc = NULL;
@@ -1303,7 +1303,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       switch (intel_output->type) {
       case I830_OUTPUT_LVDS:
 	 /* LVDS must live on pipe B for two-pipe devices */
-	 crtc = pI830->xf86_crtc[pI830->num_pipes - 1];
+	 crtc = pI830->xf86_config.crtc[pI830->xf86_config.num_crtc - 1];
 	 if (!i830PipeInUse (crtc))
 	    output->crtc = crtc;
 	 break;
@@ -1312,9 +1312,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       case I830_OUTPUT_SDVO:
 	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED) 
 	 {
-	    for (p = 0; p < pI830->num_pipes; p++)
+	    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
 	    {
-	       crtc = pI830->xf86_crtc[p];
+	       crtc = pI830->xf86_config.crtc[p];
 	       if (!i830PipeInUse(crtc))
 	       {
 		  output->crtc = crtc;
@@ -1324,7 +1324,7 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	 }
 	 break;
       case I830_OUTPUT_TVOUT:
-	 crtc = pI830->xf86_crtc[0];
+	 crtc = pI830->xf86_config.crtc[0];
 	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED &&
 	     !i830PipeInUse(crtc))
 	 {
@@ -1337,9 +1337,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   for (i = 0; i < pI830->num_pipes; i++) 
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++) 
    {
-      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
       crtc->enabled = i830PipeInUse(crtc);
    }
    
@@ -2074,7 +2074,7 @@ SaveHWState(ScrnInfoPtr pScrn)
    temp = INREG(PIPEACONF);
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", 
 	      (unsigned long) temp);
-   if (pI830->num_pipes == 2) {
+   if (pI830->xf86_config.num_crtc == 2) {
       temp = INREG(PIPEBCONF);
       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", 
 		 (unsigned long) temp);
@@ -2106,7 +2106,7 @@ SaveHWState(ScrnInfoPtr pScrn)
       pI830->savePaletteA[i] = INREG(PALETTE_A + (i << 2));
    }
 
-   if(pI830->num_pipes == 2) {
+   if(pI830->xf86_config.num_crtc == 2) {
       pI830->savePIPEBCONF = INREG(PIPEBCONF);
       pI830->savePIPEBSRC = INREG(PIPEBSRC);
       pI830->saveDSPBCNTR = INREG(DSPBCNTR);
@@ -2150,8 +2150,8 @@ SaveHWState(ScrnInfoPtr pScrn)
 
    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
 
-   for (i = 0; i < pI830->num_outputs; i++) {
-      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
       if (output->funcs->save)
 	 (*output->funcs->save) (output);
    }
@@ -2192,8 +2192,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(PIPEBCONF, temp & ~PIPEBCONF_ENABLE);
 
    /* Disable outputs if necessary */
-   for (i = 0; i < pI830->num_outputs; i++) {
-      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
       (*output->funcs->pre_set_mode) (output, NULL);
    }
 
@@ -2219,7 +2219,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
          OUTREG(PALETTE_A + (i << 2), pI830->savePaletteA[i]);
    }
 
-   if(pI830->num_pipes == 2) {
+   if(pI830->xf86_config.num_crtc == 2) {
       OUTREG(FPB0, pI830->saveFPB0);
       OUTREG(FPB1, pI830->saveFPB1);
       OUTREG(DPLL_B, pI830->saveDPLL_B);
@@ -2243,8 +2243,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
-   for (i = 0; i < pI830->num_outputs; i++) {
-      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
       (*output->funcs->restore) (output);
    }
 
@@ -3280,9 +3280,9 @@ i830AdjustFrame(int scrnIndex, int x, in
       pI830->AccelInfoRec->NeedToSync = FALSE;
    }
 
-   for (i = 0; i < pI830->num_pipes; i++)
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++)
    {
-      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
       if (crtc->enabled)
 	 i830PipeSetBase(crtc, x, y);
    }
@@ -3396,9 +3396,9 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   for (i = 0; i < pI830->num_pipes; i++)
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++)
    {
-      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+      xf86CrtcPtr	crtc = pI830->xf86_config.crtc[i];
 
       /* Mark that we'll need to re-set the mode for sure */
       memset(&crtc->curMode, 0, sizeof(crtc->curMode));
@@ -3566,7 +3566,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
    DPRINTF(PFX, "I830SaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on));
 
    if (pScrn->vtSema) {
-      for (i = 0; i < pI830->num_pipes; i++) {
+      for (i = 0; i < pI830->xf86_config.num_crtc; i++) {
         if (i == 0) {
 	    ctrl = DSPACNTR;
 	    base = DSPABASE;
@@ -3576,7 +3576,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
 	    base = DSPBADDR;
 	    surf = DSPBSURF;
         }
-        if (pI830->xf86_crtc[i]->enabled) {
+        if (pI830->xf86_config.crtc[i]->enabled) {
 	   temp = INREG(ctrl);
 	   if (on)
 	      temp |= DISPLAY_PLANE_ENABLE;
@@ -3613,15 +3613,15 @@ I830DisplayPowerManagementSet(ScrnInfoPt
    int i;
    CARD32 temp, ctrl, base;
 
-   for (i = 0; i < pI830->num_outputs; i++) {
-      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
+      xf86OutputPtr   output = pI830->xf86_config.output[i];
       
       (*output->funcs->dpms) (output, PowerManagementMode);
    }
 
-   for (i = 0; i < pI830->num_pipes; i++) 
+   for (i = 0; i < pI830->xf86_config.num_crtc; i++) 
    {
-      I830_xf86CrtcPtr	   crtc = pI830->xf86_crtc[i];
+      xf86CrtcPtr	   crtc = pI830->xf86_config.crtc[i];
       
       if (i == 0) {
          ctrl = DSPACNTR;
@@ -3835,7 +3835,7 @@ i830MonitorDetectDebugger(ScrnInfoPtr pS
    if (!pScrn->vtSema)
       return 1000;
 
-   for (i = 0; i < pI830->num_outputs; i++) {
+   for (i = 0; i < pI830->xf86_config.num_output; i++) {
       enum output_status ret;
       char *result;
 
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index b292190..6fe3157 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -57,7 +57,7 @@ struct _I830DVODriver i830_dvo_drivers[]
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
 
 static void
-i830_dvo_dpms(I830_xf86OutputPtr output, int mode)
+i830_dvo_dpms(xf86OutputPtr output, int mode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     if (mode == DPMSModeOn)
@@ -67,7 +67,7 @@ i830_dvo_dpms(I830_xf86OutputPtr output,
 }
 
 static void
-i830_dvo_save(I830_xf86OutputPtr output)
+i830_dvo_save(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -84,7 +84,7 @@ i830_dvo_save(I830_xf86OutputPtr output)
 }
 
 static void
-i830_dvo_restore(I830_xf86OutputPtr output)
+i830_dvo_restore(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -98,7 +98,7 @@ i830_dvo_restore(I830_xf86OutputPtr outp
 }
 
 static int
-i830_dvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     
@@ -114,7 +114,7 @@ i830_dvo_mode_valid(I830_xf86OutputPtr o
 }
 
 static void
-i830_dvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_dvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -126,11 +126,11 @@ i830_dvo_pre_set_mode(I830_xf86OutputPtr
 }
 
 static void
-i830_dvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_dvo_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	    crtc = output->crtc;
+    xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     int			    pipe = intel_crtc->pipe;
     CARD32		    dvo;
@@ -165,7 +165,7 @@ i830_dvo_post_set_mode(I830_xf86OutputPt
  * Unimplemented.
  */
 static enum detect_status
-i830_dvo_detect(I830_xf86OutputPtr output)
+i830_dvo_detect(xf86OutputPtr output)
 {
     return OUTPUT_STATUS_UNKNOWN;
 }
@@ -202,7 +202,7 @@ I830I2CDetectDVOControllers(ScrnInfoPtr 
 }
 
 static void
-i830_dvo_destroy (I830_xf86OutputPtr output)
+i830_dvo_destroy (xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
 
@@ -217,7 +217,7 @@ i830_dvo_destroy (I830_xf86OutputPtr out
     }
 }
 
-static const I830_xf86OutputFuncsRec i830_dvo_output_funcs = {
+static const xf86OutputFuncsRec i830_dvo_output_funcs = {
     .dpms = i830_dvo_dpms,
     .save = i830_dvo_save,
     .restore = i830_dvo_restore,
@@ -232,18 +232,18 @@ static const I830_xf86OutputFuncsRec i83
 void
 i830_dvo_init(ScrnInfoPtr pScrn)
 {
-    I830_xf86OutputPtr	    output;
+    xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     int			    ret;
 
-    output = i830xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
+    output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
 				   "ADD AGP card");
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
     if (!intel_output)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     intel_output->type = I830_OUTPUT_DVO;
@@ -253,14 +253,14 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
     if (!ret)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 
     ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
     if (!ret)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 
@@ -275,7 +275,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
     }
     else
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 }
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index e72b9e8..bfb4e14 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -73,7 +73,7 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 }
 
 static void
-i830_lvds_dpms (I830_xf86OutputPtr output, int mode)
+i830_lvds_dpms (xf86OutputPtr output, int mode)
 {
     ScrnInfoPtr	pScrn = output->scrn;
 
@@ -84,7 +84,7 @@ i830_lvds_dpms (I830_xf86OutputPtr outpu
 }
 
 static void
-i830_lvds_save (I830_xf86OutputPtr output)
+i830_lvds_save (xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -109,7 +109,7 @@ i830_lvds_save (I830_xf86OutputPtr outpu
 }
 
 static void
-i830_lvds_restore(I830_xf86OutputPtr output)
+i830_lvds_restore(xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -127,13 +127,13 @@ i830_lvds_restore(I830_xf86OutputPtr out
 }
 
 static int
-i830_lvds_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
    return MODE_OK;
 }
 
 static void
-i830_lvds_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_lvds_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     /* Always make sure the LVDS is off before we play with DPLLs and pipe
@@ -145,7 +145,7 @@ i830_lvds_pre_set_mode(I830_xf86OutputPt
 }
 
 static void
-i830_lvds_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_lvds_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830Ptr	pI830 = I830PTR(pScrn);
@@ -185,7 +185,7 @@ i830_lvds_post_set_mode(I830_xf86OutputP
  * been set up if the LVDS was actually connected anyway.
  */
 static enum detect_status
-i830_lvds_detect(I830_xf86OutputPtr output)
+i830_lvds_detect(xf86OutputPtr output)
 {
     return OUTPUT_STATUS_CONNECTED;
 }
@@ -194,7 +194,7 @@ i830_lvds_detect(I830_xf86OutputPtr outp
  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
  */
 static DisplayModePtr
-i830_lvds_get_modes(I830_xf86OutputPtr output)
+i830_lvds_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr	    pScrn = output->scrn;
     I830Ptr	    pI830 = I830PTR(pScrn);
@@ -225,7 +225,7 @@ i830_lvds_get_modes(I830_xf86OutputPtr o
 }
 
 static void
-i830_lvds_destroy (I830_xf86OutputPtr output)
+i830_lvds_destroy (xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
 
@@ -233,7 +233,7 @@ i830_lvds_destroy (I830_xf86OutputPtr ou
 	xfree (intel_output);
 }
 
-static const I830_xf86OutputFuncsRec i830_lvds_output_funcs = {
+static const xf86OutputFuncsRec i830_lvds_output_funcs = {
     .dpms = i830_lvds_dpms,
     .save = i830_lvds_save,
     .restore = i830_lvds_restore,
@@ -249,7 +249,7 @@ void
 i830_lvds_init(ScrnInfoPtr pScrn)
 {
     I830Ptr		    pI830 = I830PTR(pScrn);
-    I830_xf86OutputPtr	    output;
+    xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
 
 
@@ -286,13 +286,13 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	}
    }
 
-    output = i830xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel");
+    output = xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel");
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
     if (!intel_output)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     intel_output->type = I830_OUTPUT_LVDS;
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7d4bcba..19ea05c 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -427,9 +427,9 @@ i830_reprobe_output_modes(ScrnInfoPtr pS
     int i;
 
     /* Re-probe the list of modes for each output. */
-    for (i = 0; i < pI830->num_outputs; i++) 
+    for (i = 0; i < pI830->xf86_config.num_output; i++) 
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	xf86OutputPtr  output = pI830->xf86_config.output[i];
 	DisplayModePtr mode;
 
 	while (output->probed_modes != NULL)
@@ -511,8 +511,8 @@ i830_set_xf86_modes_from_outputs(ScrnInf
      * 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->num_outputs; i++) {
-	I830_xf86OutputPtr output = pI830->xf86_output[i];
+    for (i = 0; i < pI830->xf86_config.num_output; i++) {
+	xf86OutputPtr output = pI830->xf86_config.output[i];
 	if (output->probed_modes != NULL) {
 	    pScrn->modes = i830xf86DuplicateModes(pScrn, output->probed_modes);
 	    break;
@@ -564,8 +564,8 @@ i830_set_default_screen_size(ScrnInfoPtr
     /* 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++) {
-	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+    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)
@@ -615,7 +615,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 #define EDID_ATOM_NAME		"EDID_DATA"
 
 static void
-i830_ddc_set_edid_property(I830_xf86OutputPtr output, void *data, int data_len)
+i830_ddc_set_edid_property(xf86OutputPtr output, void *data, int data_len)
 {
     Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
 
@@ -636,7 +636,7 @@ i830_ddc_set_edid_property(I830_xf86Outp
  * Generic get_modes function using DDC, used by many outputs.
  */
 DisplayModePtr
-i830_ddc_get_modes(I830_xf86OutputPtr output)
+i830_ddc_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr	pScrn = output->scrn;
     I830OutputPrivatePtr intel_output = output->driver_private;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 59c07ff..ec0a2ec 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -481,8 +481,8 @@ I830RandRCrtcNotify (RRCrtcPtr	randr_crt
     int			numOutputs;
     RROutputPtr		randr_outputs[MAX_OUTPUTS];
     RROutputPtr		randr_output;
-    I830_xf86CrtcPtr	crtc = randr_crtc->devPrivate;
-    I830_xf86OutputPtr	output;
+    xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    xf86OutputPtr	output;
     int			i, j;
     DisplayModePtr	curMode = &crtc->curMode;
 
@@ -491,9 +491,9 @@ I830RandRCrtcNotify (RRCrtcPtr	randr_crt
     rotation = RR_Rotate_0;
     numOutputs = 0;
     randr_mode = NULL;
-    for (i = 0; i < pI830->num_outputs; i++)
+    for (i = 0; i < pI830->xf86_config.num_output; i++)
     {
-	output = pI830->xf86_output[i];
+	output = pI830->xf86_config.output[i];
 	if (output->crtc == crtc)
 	{
 	    randr_output = output->randr_output;
@@ -529,20 +529,20 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    xf86CrtcPtr	crtc = randr_crtc->devPrivate;
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
     int			o, ro;
-    I830_xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
+    xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
     Bool		save_enabled = crtc->enabled;
 
     if (!I830ModesEqual (&crtc->curMode, mode))
 	changed = TRUE;
     
-    for (o = 0; o < pI830->num_outputs; o++) 
+    for (o = 0; o < pI830->xf86_config.num_output; o++) 
     {
-	I830_xf86OutputPtr  output = pI830->xf86_output[o];
-	I830_xf86CrtcPtr    new_crtc;
+	xf86OutputPtr  output = pI830->xf86_config.output[o];
+	xf86CrtcPtr    new_crtc;
 
 	save_crtcs[o] = output->crtc;
 	
@@ -577,9 +577,9 @@ I830RandRCrtcSet (ScreenPtr	pScreen,
 	    if (!i830PipeSetMode (crtc, mode, TRUE))
 	    {
 		crtc->enabled = save_enabled;
-		for (o = 0; o < pI830->num_outputs; o++)
+		for (o = 0; o < pI830->xf86_config.num_output; o++)
 		{
-		    I830_xf86OutputPtr	output = pI830->xf86_output[o];
+		    xf86OutputPtr	output = pI830->xf86_config.output[o];
 		    output->crtc = save_crtcs[o];
 		}
 		return FALSE;
@@ -676,9 +676,9 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
     RRCrtcPtr		    randr_crtc;
     int			    nclone;
     
-    for (o = 0; o < pI830->num_outputs; o++)
+    for (o = 0; o < pI830->xf86_config.num_output; o++)
     {
-	I830_xf86OutputPtr	output = pI830->xf86_output[o];
+	xf86OutputPtr	output = pI830->xf86_config.output[o];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	/*
 	 * Valid crtcs
@@ -718,9 +718,9 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	    break;
 	}
 	ncrtc = 0;
-	for (p = 0; p < pI830->num_pipes; p++)
+	for (p = 0; p < pI830->xf86_config.num_crtc; p++)
 	    if (crtc_types & (1 << p))
-		crtcs[ncrtc++] = pI830->xf86_crtc[p]->randr_crtc;
+		crtcs[ncrtc++] = pI830->xf86_config.crtc[p]->randr_crtc;
 
 	if (output->crtc)
 	    randr_crtc = output->crtc->randr_crtc;
@@ -754,9 +754,9 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	 * Valid clones
 	 */
 	nclone = 0;
-	for (c = 0; c < pI830->num_outputs; c++)
+	for (c = 0; c < pI830->xf86_config.num_output; c++)
 	{
-	    I830_xf86OutputPtr	    clone = pI830->xf86_output[c];
+	    xf86OutputPtr	    clone = pI830->xf86_config.output[c];
 	    I830OutputPrivatePtr    intel_clone = clone->driver_private;
 	    
 	    if (o != c && ((1 << intel_clone->type) & clone_types))
@@ -793,9 +793,9 @@ I830RandRCreateObjects12 (ScrnInfoPtr pS
     /*
      * Configure crtcs
      */
-    for (p = 0; p < pI830->num_pipes; p++)
+    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
     {
-	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[p];
+	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[p];
 	
 	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
@@ -815,21 +815,21 @@ I830RandRCreateScreenResources12 (Screen
     /*
      * Attach RandR objects to screen
      */
-    for (p = 0; p < pI830->num_pipes; p++)
-	if (!RRCrtcAttachScreen (pI830->xf86_crtc[p]->randr_crtc, pScreen))
+    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->num_outputs; o++)
-	if (!RROutputAttachScreen (pI830->xf86_output[o]->randr_output, pScreen))
+    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->num_pipes; p++)
+    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
     {
-	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[p];
+	xf86CrtcPtr    crtc = pI830->xf86_config.crtc[p];
 	int		    crtc_width = crtc->x + crtc->curMode.HDisplay;
 	int		    crtc_height = crtc->y + crtc->curMode.VDisplay;
 	
@@ -859,8 +859,8 @@ I830RandRCreateScreenResources12 (Screen
 				mmHeight);
     }
 
-    for (p = 0; p < pI830->num_pipes; p++)
-	I830RandRCrtcNotify (pI830->xf86_crtc[p]->randr_crtc);
+    for (p = 0; p < pI830->xf86_config.num_crtc; p++)
+	I830RandRCrtcNotify (pI830->xf86_config.crtc[p]->randr_crtc);
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -963,7 +963,7 @@ static int
 I830RRPickCrtcs (RROutputPtr	*outputs,
 		 RRCrtcPtr	*best_crtcs,
 		 RRModePtr	*modes,
-		 int		num_outputs,
+		 int		num_output,
 		 int		n)
 {
     int		c, o, l;
@@ -975,7 +975,7 @@ I830RRPickCrtcs (RROutputPtr	*outputs,
     int		score;
     int		my_score;
     
-    if (n == num_outputs)
+    if (n == num_output)
 	return 0;
     output = outputs[n];
     
@@ -984,11 +984,11 @@ I830RRPickCrtcs (RROutputPtr	*outputs,
      */
     best_crtcs[n] = NULL;
     best_crtc = NULL;
-    best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_outputs, n+1);
+    best_score = I830RRPickCrtcs (outputs, best_crtcs, modes, num_output, n+1);
     if (modes[n] == NULL)
 	return best_score;
     
-    crtcs = xalloc (num_outputs * sizeof (RRCrtcPtr));
+    crtcs = xalloc (num_output * sizeof (RRCrtcPtr));
     if (!crtcs)
 	return best_score;
 
@@ -1034,12 +1034,12 @@ I830RRPickCrtcs (RROutputPtr	*outputs,
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr));
 	score = my_score + I830RRPickCrtcs (outputs, crtcs, modes,
-					    num_outputs, n+1);
+					    num_output, n+1);
 	if (score >= best_score)
 	{
 	    best_crtc = crtc;
 	    best_score = score;
-	    memcpy (best_crtcs, crtcs, num_outputs * sizeof (RRCrtcPtr));
+	    memcpy (best_crtcs, crtcs, num_output * sizeof (RRCrtcPtr));
 	}
     }
     xfree (crtcs);
@@ -1050,18 +1050,18 @@ static Bool
 I830RRInitialConfiguration (RROutputPtr *outputs,
 			    RRCrtcPtr	*crtcs,
 			    RRModePtr	*modes,
-			    int		num_outputs)
+			    int		num_output)
 {
     int		o;
     RRModePtr	target_mode = NULL;
 
-    for (o = 0; o < num_outputs; o++)
+    for (o = 0; o < num_output; o++)
 	modes[o] = NULL;
     
     /*
      * Let outputs with preferred modes drive screen size
      */
-    for (o = 0; o < num_outputs; o++)
+    for (o = 0; o < num_output; o++)
     {
 	RROutputPtr output = outputs[o];
 
@@ -1077,7 +1077,7 @@ I830RRInitialConfiguration (RROutputPtr 
     }
     if (!target_mode)
     {
-	for (o = 0; o < num_outputs; o++)
+	for (o = 0; o < num_output; o++)
 	{
 	    RROutputPtr output = outputs[o];
 	    if (output->connection != RR_Disconnected)
@@ -1091,7 +1091,7 @@ I830RRInitialConfiguration (RROutputPtr 
 	    }
 	}
     }
-    for (o = 0; o < num_outputs; o++)
+    for (o = 0; o < num_output; o++)
     {
 	RROutputPtr output = outputs[o];
 	
@@ -1099,7 +1099,7 @@ I830RRInitialConfiguration (RROutputPtr 
 	    modes[o] = I830ClosestMode (output, target_mode);
     }
 
-    if (!I830RRPickCrtcs (outputs, crtcs, modes, num_outputs, 0))
+    if (!I830RRPickCrtcs (outputs, crtcs, modes, num_output, 0))
 	return FALSE;
     
     return TRUE;
@@ -1111,7 +1111,7 @@ I830RRInitialConfiguration (RROutputPtr 
  */
 
 static void
-I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs,
+I830RRDefaultScreenLimits (RROutputPtr *outputs, int num_output,
 			   RRCrtcPtr *crtcs, int num_crtc,
 			   int *widthp, int *heightp)
 {
@@ -1126,7 +1126,7 @@ I830RRDefaultScreenLimits (RROutputPtr *
 	RRCrtcPtr   crtc = crtcs[c];
 	int	    crtc_width = 1600, crtc_height = 1200;
 
-	for (o = 0; o < num_outputs; o++) 
+	for (o = 0; o < num_output; o++) 
 	{
 	    RROutputPtr	output = outputs[o];
 
@@ -1168,7 +1168,7 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     int		c;
 #endif
     
-    if (pI830->num_outputs <= 0)
+    if (pI830->xf86_config.num_output <= 0)
 	return FALSE;
     
     i830_reprobe_output_modes(pScrn);
@@ -1186,17 +1186,17 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
      * With RandR info set up, let RandR choose
      * the initial configuration
      */
-    for (o = 0; o < pI830->num_outputs; o++)
-	outputs[o] = pI830->xf86_output[o]->randr_output;
-    for (c = 0; c < pI830->num_pipes; c++)
-	crtcs[c] = pI830->xf86_crtc[c]->randr_crtc;
+    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->num_outputs))
+				     pI830->xf86_config.num_output))
 	return FALSE;
     
-    I830RRDefaultScreenLimits (outputs, pI830->num_outputs, 
-			       crtcs, pI830->num_pipes,
+    I830RRDefaultScreenLimits (outputs, pI830->xf86_config.num_output, 
+			       crtcs, pI830->xf86_config.num_crtc,
 			       &width, &height);
     
     if (width > pScrn->virtualX)
@@ -1211,16 +1211,16 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     /* XXX override xf86 common frame computation code */
     pScrn->display->frameX0 = 0;
     pScrn->display->frameY0 = 0;
-    for (o = 0; o < pI830->num_outputs; o++)
+    for (o = 0; o < pI830->xf86_config.num_output; o++)
     {
-	I830_xf86OutputPtr  output = pI830->xf86_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)
 	{
-	    I830_xf86CrtcPtr    crtc = randr_crtc->devPrivate;
+	    xf86CrtcPtr    crtc = randr_crtc->devPrivate;
 	    
 	    mode = (DisplayModePtr) randr_mode->devPrivate;
 	    crtc->desiredMode = *mode;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index a8eba4c..c685a8d 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -80,7 +80,7 @@ struct i830_sdvo_priv {
 };
 
 /** Read a single byte from the given address on the SDVO device. */
-static Bool i830_sdvo_read_byte(I830_xf86OutputPtr output, int addr,
+static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
 				unsigned char *ch)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -96,7 +96,7 @@ static Bool i830_sdvo_read_byte(I830_xf8
 }
 
 /** Write a single byte to the given address on the SDVO device. */
-static Bool i830_sdvo_write_byte(I830_xf86OutputPtr output,
+static Bool i830_sdvo_write_byte(xf86OutputPtr output,
 				 int addr, unsigned char ch)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -166,7 +166,7 @@ static I2CSlaveAddr slaveAddr;
  * Writes out the data given in args (up to 8 bytes), followed by the opcode.
  */
 static void
-i830_sdvo_write_cmd(I830_xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
+i830_sdvo_write_cmd(xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
@@ -213,7 +213,7 @@ static const char *cmd_status_names[] = 
  * Reads back response_len bytes from the SDVO device, and returns the status.
  */
 static CARD8
-i830_sdvo_read_response(I830_xf86OutputPtr output, void *response, int response_len)
+i830_sdvo_read_response(xf86OutputPtr output, void *response, int response_len)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     int			    i;
@@ -262,13 +262,13 @@ i830_sdvo_get_pixel_multiplier(DisplayMo
  * STOP.  PROM access is terminated by accessing an internal register.
  */
 static void
-i830_sdvo_set_control_bus_switch(I830_xf86OutputPtr output, CARD8 target)
+i830_sdvo_set_control_bus_switch(xf86OutputPtr output, CARD8 target)
 {
     i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
 }
 
 static Bool
-i830_sdvo_set_target_input(I830_xf86OutputPtr output, Bool target_0, Bool target_1)
+i830_sdvo_set_target_input(xf86OutputPtr output, Bool target_0, Bool target_1)
 {
     struct i830_sdvo_set_target_input_args targets = {0};
     CARD8 status;
@@ -294,7 +294,7 @@ i830_sdvo_set_target_input(I830_xf86Outp
  * which should be checked against the docs.
  */
 static Bool
-i830_sdvo_get_trained_inputs(I830_xf86OutputPtr output, Bool *input_1, Bool *input_2)
+i830_sdvo_get_trained_inputs(xf86OutputPtr output, Bool *input_1, Bool *input_2)
 {
     struct i830_sdvo_get_trained_inputs_response response;
     CARD8 status;
@@ -312,7 +312,7 @@ i830_sdvo_get_trained_inputs(I830_xf86Ou
 }
 
 static Bool
-i830_sdvo_get_active_outputs(I830_xf86OutputPtr output,
+i830_sdvo_get_active_outputs(xf86OutputPtr output,
 			     CARD16 *outputs)
 {
     CARD8 status;
@@ -324,7 +324,7 @@ i830_sdvo_get_active_outputs(I830_xf86Ou
 }
 
 static Bool
-i830_sdvo_set_active_outputs(I830_xf86OutputPtr output,
+i830_sdvo_set_active_outputs(xf86OutputPtr output,
 			     CARD16 outputs)
 {
     CARD8 status;
@@ -340,7 +340,7 @@ i830_sdvo_set_active_outputs(I830_xf86Ou
  * Returns the pixel clock range limits of the current target input in kHz.
  */
 static Bool
-i830_sdvo_get_input_pixel_clock_range(I830_xf86OutputPtr output, int *clock_min,
+i830_sdvo_get_input_pixel_clock_range(xf86OutputPtr output, int *clock_min,
 				      int *clock_max)
 {
     struct i830_sdvo_pixel_clock_range clocks;
@@ -361,7 +361,7 @@ i830_sdvo_get_input_pixel_clock_range(I8
 }
 
 static Bool
-i830_sdvo_set_target_output(I830_xf86OutputPtr output, CARD16 outputs)
+i830_sdvo_set_target_output(xf86OutputPtr output, CARD16 outputs)
 {
     CARD8 status;
 
@@ -375,7 +375,7 @@ i830_sdvo_set_target_output(I830_xf86Out
 
 /** Fetches either input or output timings to *dtd, depending on cmd. */
 static Bool
-i830_sdvo_get_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
     CARD8 status;
 
@@ -395,20 +395,20 @@ i830_sdvo_get_timing(I830_xf86OutputPtr 
 }
 
 static Bool
-i830_sdvo_get_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_get_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
 /** Sets either input or output timings from *dtd, depending on cmd. */
 static Bool
-i830_sdvo_set_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_timing(xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
     CARD8 status;
 
@@ -426,20 +426,20 @@ i830_sdvo_set_timing(I830_xf86OutputPtr 
 }
 
 static Bool
-i830_sdvo_set_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_input_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_set_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
 #if 0
 static Bool
-i830_sdvo_create_preferred_input_timing(I830_xf86OutputPtr output, CARD16 clock,
+i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, CARD16 clock,
 					CARD16 width, CARD16 height)
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
@@ -483,7 +483,7 @@ i830_sdvo_get_preferred_input_timing(I83
 
 /** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
 static int
-i830_sdvo_get_clock_rate_mult(I830_xf86OutputPtr output)
+i830_sdvo_get_clock_rate_mult(xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
@@ -512,7 +512,7 @@ i830_sdvo_get_clock_rate_mult(I830_xf86O
  * is actually turned on.
  */
 static Bool
-i830_sdvo_set_clock_rate_mult(I830_xf86OutputPtr output, CARD8 val)
+i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, CARD8 val)
 {
     CARD8 status;
 
@@ -525,7 +525,7 @@ i830_sdvo_set_clock_rate_mult(I830_xf86O
 }
 
 static void
-i830_sdvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode)
+i830_sdvo_pre_set_mode(xf86OutputPtr output, DisplayModePtr mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -627,12 +627,12 @@ i830_sdvo_pre_set_mode(I830_xf86OutputPt
 }
 
 static void
-i830_sdvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode)
+i830_sdvo_post_set_mode(xf86OutputPtr output, DisplayModePtr mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
-    I830_xf86CrtcPtr	    crtc = output->crtc;
+    xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     I830Ptr pI830 = I830PTR(pScrn);
     Bool input1, input2;
@@ -690,7 +690,7 @@ i830_sdvo_post_set_mode(I830_xf86OutputP
 }
 
 static void
-i830_sdvo_dpms(I830_xf86OutputPtr output, int mode)
+i830_sdvo_dpms(xf86OutputPtr output, int mode)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -707,7 +707,7 @@ i830_sdvo_dpms(I830_xf86OutputPtr output
 }
 
 static void
-i830_sdvo_save(I830_xf86OutputPtr output)
+i830_sdvo_save(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -744,7 +744,7 @@ i830_sdvo_save(I830_xf86OutputPtr output
 }
 
 static void
-i830_sdvo_restore(I830_xf86OutputPtr output)
+i830_sdvo_restore(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    intel_output = output->driver_private;
@@ -779,7 +779,7 @@ i830_sdvo_restore(I830_xf86OutputPtr out
 }
 
 static int
-i830_sdvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_sdvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
@@ -797,7 +797,7 @@ i830_sdvo_mode_valid(I830_xf86OutputPtr 
 }
 
 static Bool
-i830_sdvo_get_capabilities(I830_xf86OutputPtr output, struct i830_sdvo_caps *caps)
+i830_sdvo_get_capabilities(xf86OutputPtr output, struct i830_sdvo_caps *caps)
 {
     CARD8 status;
 
@@ -813,9 +813,10 @@ i830_sdvo_get_capabilities(I830_xf86Outp
 static Bool
 i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, I2CByte *data, Bool last)
 {
-    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = output->pI2CBus, savebus;
-    Bool ret;
+    xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
+    Bool		    ret;
 
     savebus = d->pI2CBus;
     d->pI2CBus = i2cbus;
@@ -829,9 +830,10 @@ i830_sdvo_ddc_i2c_get_byte(I2CDevPtr d, 
 static Bool
 i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, I2CByte c)
 {
-    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = output->pI2CBus, savebus;
-    Bool ret;
+    xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
+    Bool		    ret;
 
     savebus = d->pI2CBus;
     d->pI2CBus = i2cbus;
@@ -851,7 +853,7 @@ i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, 
 static Bool
 i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
 {
-    I830_xf86OutputPtr	    output = b->DriverPrivate.ptr;
+    xf86OutputPtr	    output = b->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus;
 
@@ -863,7 +865,7 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int
 static void
 i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
 {
-    I830_xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    xf86OutputPtr	    output = d->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
 
@@ -900,7 +902,7 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I
 }
 
 static void
-i830_sdvo_dump_cmd(I830_xf86OutputPtr output, int opcode)
+i830_sdvo_dump_cmd(xf86OutputPtr output, int opcode)
 {
     CARD8		    response[8];
 
@@ -909,7 +911,7 @@ i830_sdvo_dump_cmd(I830_xf86OutputPtr ou
 }
 
 static void
-i830_sdvo_dump_device(I830_xf86OutputPtr output)
+i830_sdvo_dump_device(xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
@@ -944,9 +946,9 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     int	i;
 
-    for (i = 0; i < pI830->num_outputs; i++) 
+    for (i = 0; i < pI830->xf86_config.num_output; i++) 
     {
-	I830_xf86OutputPtr	output = pI830->xf86_output[i];
+	xf86OutputPtr	output = pI830->xf86_config.output[i];
 	I830OutputPrivatePtr	intel_output = output->driver_private;
 	
 	if (intel_output->type == I830_OUTPUT_SDVO)
@@ -964,7 +966,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
  * Takes 14ms on average on my i945G.
  */
 static enum detect_status
-i830_sdvo_detect(I830_xf86OutputPtr output)
+i830_sdvo_detect(xf86OutputPtr output)
 {
     CARD8 response[2];
     CARD8 status;
@@ -982,7 +984,7 @@ i830_sdvo_detect(I830_xf86OutputPtr outp
 }
 
 static void
-i830_sdvo_destroy (I830_xf86OutputPtr output)
+i830_sdvo_destroy (xf86OutputPtr output)
 {
     I830OutputPrivatePtr    intel_output = output->driver_private;
 
@@ -997,7 +999,7 @@ i830_sdvo_destroy (I830_xf86OutputPtr ou
     }
 }
 
-static const I830_xf86OutputFuncsRec i830_sdvo_output_funcs = {
+static const xf86OutputFuncsRec i830_sdvo_output_funcs = {
     .dpms = i830_sdvo_dpms,
     .save = i830_sdvo_save,
     .restore = i830_sdvo_restore,
@@ -1012,22 +1014,22 @@ static const I830_xf86OutputFuncsRec i83
 void
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
-    I830_xf86OutputPtr	    output;
+    xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     struct i830_sdvo_priv   *dev_priv;
     int			    i;
     unsigned char	    ch[0x40];
     I2CBusPtr		    i2cbus = NULL, ddcbus;
 
-    output = i830xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
-				   "ADD2 PCIE card");
+    output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
+			       "ADD2 PCIE card");
     if (!output)
 	return;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
 			      sizeof (struct i830_sdvo_priv), 1);
     if (!intel_output)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     output->driver_private = intel_output;
@@ -1045,7 +1047,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     if (i2cbus == NULL)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 
@@ -1065,7 +1067,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Failed to initialize %s I2C device\n",
 		   SDVO_NAME(dev_priv));
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 
@@ -1077,7 +1079,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     ddcbus = xf86CreateI2CBusRec();
     if (ddcbus == NULL) 
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     if (output_device == SDVOB)
@@ -1094,7 +1096,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     
     if (!xf86I2CBusInit(ddcbus)) 
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
 
@@ -1105,7 +1107,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
 	if (!i830_sdvo_read_byte(output, i, &ch[i])) {
-	    i830xf86OutputDestroy (output);
+	    xf86OutputDestroy (output);
 	    return;
 	}
     }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index ec78337..c219250 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -38,6 +38,7 @@
 #include "i830_display.h"
 
 enum tv_type {
+    TV_TYPE_NONE,
     TV_TYPE_UNKNOWN,
     TV_TYPE_COMPOSITE,
     TV_TYPE_SVIDEO,
@@ -46,6 +47,7 @@ enum tv_type {
 
 /** Private structure for the integrated TV support */
 struct i830_tv_priv {
+    int type;
     CARD32 save_TV_H_CTL_1;
     CARD32 save_TV_H_CTL_2;
     CARD32 save_TV_H_CTL_3;
@@ -141,69 +143,8 @@ const struct tv_mode {
     }
 };
 
-
-static int
-i830_tv_detect_type(I830_xf86OutputPtr output)
-{
-    ScrnInfoPtr		pScrn = output->scrn;
-    I830Ptr		pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	crtc = output->crtc;
-    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    CARD32 save_tv_ctl, save_tv_dac;
-    CARD32 tv_ctl, tv_dac;
-
-    save_tv_ctl = INREG(TV_CTL);
-    save_tv_dac = INREG(TV_DAC);
-
-    /* First, we have to disable the encoder but source from the right pipe,
-     * which is already enabled.
-     */
-    tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT);
-    if (intel_crtc->pipe == 1)
-	tv_ctl |= TV_ENC_PIPEB_SELECT;
-    OUTREG(TV_CTL, tv_ctl);
-
-    /* Then set the voltage overrides. */
-    tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V;
-    OUTREG(TV_DAC, tv_dac);
-
-    /* Enable sensing of the load. */
-    tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
-    OUTREG(TV_CTL, tv_ctl);
-
-    tv_dac |= TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | TVDAC_B_SENSE_CTL |
-        TVDAC_C_SENSE_CTL;
-    OUTREG(TV_DAC, tv_dac);
-
-    /* Wait for things to take effect. */
-    i830WaitForVblank(pScrn);
-
-    tv_dac = INREG(TV_DAC);
-
-    OUTREG(TV_DAC, save_tv_dac);
-    OUTREG(TV_CTL, save_tv_ctl);
-
-    if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Detected Composite TV connection\n");
-	return TV_TYPE_COMPOSITE;
-    } else if ((tv_dac & TVDAC_SENSE_MASK) == TVDAC_A_SENSE) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Detected S-Video TV connection\n");
-	return TV_TYPE_SVIDEO;
-    } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Detected Component TV connection\n");
-	return TV_TYPE_COMPONENT;
-    } else {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "Couldn't detect TV connection\n");
-	return TV_TYPE_UNKNOWN;
-    }
-}
-
 static void
-i830_tv_dpms(I830_xf86OutputPtr output, int mode)
+i830_tv_dpms(xf86OutputPtr output, int mode)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -221,7 +162,7 @@ i830_tv_dpms(I830_xf86OutputPtr output, 
 }
 
 static void
-i830_tv_save(I830_xf86OutputPtr output)
+i830_tv_save(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -247,7 +188,7 @@ i830_tv_save(I830_xf86OutputPtr output)
 }
 
 static void
-i830_tv_restore(I830_xf86OutputPtr output)
+i830_tv_restore(xf86OutputPtr output)
 {
     ScrnInfoPtr		    pScrn = output->scrn;
     I830Ptr		    pI830 = I830PTR(pScrn);
@@ -273,13 +214,13 @@ i830_tv_restore(I830_xf86OutputPtr outpu
 }
 
 static int
-i830_tv_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
 {
     return MODE_OK;
 }
 
 static void
-i830_tv_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_tv_pre_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -355,20 +296,22 @@ static const CARD32 v_chroma[43] = {
 };
 
 static void
-i830_tv_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
+i830_tv_post_set_mode(xf86OutputPtr output, DisplayModePtr pMode)
 {
-    ScrnInfoPtr pScrn = output->scrn;
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830_xf86CrtcPtr	crtc = output->crtc;
-    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
-    enum tv_type type;
-    const struct tv_mode *tv_mode;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    xf86CrtcPtr	    crtc = output->crtc;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    enum tv_type	    type;
+    const struct tv_mode    *tv_mode;
     const struct tv_sc_mode *sc_mode;
-    CARD32 tv_ctl, tv_filter_ctl;
-    CARD32 hctl1, hctl2, hctl3;
-    CARD32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
-    CARD32 scctl1, scctl2, scctl3;
-    int i;
+    CARD32		    tv_ctl, tv_filter_ctl;
+    CARD32		    hctl1, hctl2, hctl3;
+    CARD32		    vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
+    CARD32		    scctl1, scctl2, scctl3;
+    int			    i;
 
     /* Need to actually choose or construct the appropriate
      * mode.  For now, just set the first one in the list, with
@@ -377,7 +320,7 @@ i830_tv_post_set_mode(I830_xf86OutputPtr
     tv_mode = &tv_modes[0];
     sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
 
-    type = i830_tv_detect_type(output);
+    type = dev_priv->type;
 
     hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 	(tv_mode->htotal << TV_HTOTAL_SHIFT);
@@ -503,6 +446,99 @@ i830_tv_post_set_mode(I830_xf86OutputPtr
     OUTREG(TV_CTL, tv_ctl);
 }
 
+static const DisplayModeRec tvModes[] = {
+    {
+	.name = "NTSC 480i",
+	.Clock = 108000,
+	
+	.HDisplay   = 1024,
+	.HSyncStart = 1048,
+	.HSyncEnd   = 1184,
+	.HTotal     = 1344,
+
+	.VDisplay   = 768,
+	.VSyncStart = 771,
+	.VSyncEnd   = 777,
+	.VTotal     = 806,
+
+	.type       = M_T_DEFAULT
+    }
+};
+
+/**
+ * Detects TV presence by checking for load.
+ *
+ * Requires that the current pipe's DPLL is active.
+ 
+ * \return TRUE if TV is connected.
+ * \return FALSE if TV is disconnected.
+ */
+static int
+i830_tv_detect_type (xf86CrtcPtr    crtc,
+		     xf86OutputPtr  output)
+{
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
+    CARD32		    tv_ctl, save_tv_ctl;
+    CARD32		    tv_dac, save_tv_dac;
+    int			    type = TV_TYPE_UNKNOWN;
+
+    tv_dac = INREG(TV_DAC);
+    /*
+     * Detect TV by polling)
+     */
+    if (intel_output->load_detect_temp)
+    {
+	/* TV not currently running, prod it with destructive detect */
+	save_tv_dac = tv_dac;
+	tv_ctl = INREG(TV_CTL);
+	save_tv_ctl = tv_ctl;
+	tv_ctl &= ~TV_ENC_ENABLE;
+	tv_ctl &= ~TV_TEST_MODE_MASK;
+	tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+	tv_dac &= ~TVDAC_SENSE_MASK;
+	tv_dac |= (TVDAC_STATE_CHG_EN |
+		   TVDAC_A_SENSE_CTL |
+		   TVDAC_B_SENSE_CTL |
+		   TVDAC_C_SENSE_CTL);
+	tv_dac = DAC_CTL_OVERRIDE | DAC_A_0_7_V | DAC_B_0_7_V | DAC_C_0_7_V;
+	OUTREG(TV_CTL, tv_ctl);
+	OUTREG(TV_DAC, tv_dac);
+	i830WaitForVblank(pScrn);
+	tv_dac = INREG(TV_DAC);
+	OUTREG(TV_DAC, save_tv_dac);
+	OUTREG(TV_CTL, save_tv_ctl);
+    }
+    /*
+     *  A B C
+     *  0 1 1 Composite
+     *  1 0 X svideo
+     *  0 0 0 Component
+     */
+    if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Detected Composite TV connection\n");
+	type = TV_TYPE_COMPOSITE;
+    } else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Detected S-Video TV connection\n");
+	type = TV_TYPE_SVIDEO;
+    } else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Detected Component TV connection\n");
+	type = TV_TYPE_COMPONENT;
+    } else {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "Couldn't detect TV connection\n");
+	type = TV_TYPE_NONE;
+    }
+    
+    dev_priv->type = type;
+    return type;
+}
+
 /**
  * Detect the TV connection.
  *
@@ -510,10 +546,34 @@ i830_tv_post_set_mode(I830_xf86OutputPtr
  * we have a pipe programmed in order to probe the TV.
  */
 static enum detect_status
-i830_tv_detect(I830_xf86OutputPtr output)
+i830_tv_detect(xf86OutputPtr output)
 {
-    /* XXX need to load-detect */
-    return OUTPUT_STATUS_CONNECTED;
+    xf86CrtcPtr	    crtc;
+    DisplayModeRec	    mode;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    int			    type;
+
+    crtc = i830GetLoadDetectPipe (output);
+    if (!crtc)
+	return OUTPUT_STATUS_UNKNOWN;
+    
+    if (intel_output->load_detect_temp)
+    {
+	mode = tvModes[0];
+	I830xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	i830PipeSetMode (crtc, &mode, FALSE);
+    }
+    type = i830_tv_detect_type (crtc, output);
+    i830ReleaseLoadDetectPipe (output);
+    
+    switch (type) {
+    case TV_TYPE_NONE:
+	return OUTPUT_STATUS_DISCONNECTED;
+    case TV_TYPE_UNKNOWN:
+	return OUTPUT_STATUS_UNKNOWN;
+    default:
+	return OUTPUT_STATUS_CONNECTED;
+    }
 }
 
 /**
@@ -523,7 +583,7 @@ i830_tv_detect(I830_xf86OutputPtr output
  * how to probe modes off of TV connections.
  */
 static DisplayModePtr
-i830_tv_get_modes(I830_xf86OutputPtr output)
+i830_tv_get_modes(xf86OutputPtr output)
 {
     ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
@@ -565,13 +625,13 @@ i830_tv_get_modes(I830_xf86OutputPtr out
 }
 
 static void
-i830_tv_destroy (I830_xf86OutputPtr output)
+i830_tv_destroy (xf86OutputPtr output)
 {
     if (output->driver_private)
 	xfree (output->driver_private);
 }
 
-static const I830_xf86OutputFuncsRec i830_tv_output_funcs = {
+static const xf86OutputFuncsRec i830_tv_output_funcs = {
     .dpms = i830_tv_dpms,
     .save = i830_tv_save,
     .restore = i830_tv_restore,
@@ -587,15 +647,14 @@ void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
     I830Ptr		    pI830 = I830PTR(pScrn);
-    I830_xf86OutputPtr	    output;
+    xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     struct i830_tv_priv	    *dev_priv;
  
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
-    output = i830xf86OutputCreate (pScrn, &i830_tv_output_funcs,
-				   "TV");
+    output = xf86OutputCreate (pScrn, &i830_tv_output_funcs, "TV");
     
     if (!output)
 	return;
@@ -604,12 +663,13 @@ i830_tv_init(ScrnInfoPtr pScrn)
 			      sizeof (struct i830_tv_priv), 1);
     if (!intel_output)
     {
-	i830xf86OutputDestroy (output);
+	xf86OutputDestroy (output);
 	return;
     }
     dev_priv = (struct i830_tv_priv *) (intel_output + 1);
     intel_output->type = I830_OUTPUT_SDVO;
     intel_output->dev_priv = dev_priv;
+    dev_priv->type = TV_TYPE_UNKNOWN;
     
     output->driver_private = intel_output;
 }
diff --git a/src/i830_video.c b/src/i830_video.c
index 5ce2b5d..2f626b2 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -3595,7 +3595,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
    }
 
    /* Check we have an LFP connected */
-   if (i830PipeHasType (pI830->xf86_crtc[pPriv->pipe], I830_OUTPUT_LVDS)) 
+   if (i830PipeHasType (pI830->xf86_config.crtc[pPriv->pipe], I830_OUTPUT_LVDS)) 
    {
       size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
       hsize = (size >> 16) & 0x7FF;
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 630f3fa..2eb775b 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -31,57 +31,70 @@
 #include <stdio.h>
 
 #include "xf86.h"
-#include "i830.h"
-#include "i830_xf86Modes.h"
 #include "i830_xf86Crtc.h"
 
 /*
  * Crtc functions
  */
-I830_xf86CrtcPtr
-i830xf86CrtcCreate (ScrnInfoPtr			scrn,
-		    const I830_xf86CrtcFuncsRec	*funcs)
+xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr		scrn,
+		const xf86CrtcFuncsRec	*funcs)
 {
-    I830_xf86CrtcPtr	xf86_crtc;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CrtcPtr		crtc;
 
-    xf86_crtc = xcalloc (sizeof (I830_xf86CrtcRec), 1);
-    if (!xf86_crtc)
+    crtc = xcalloc (sizeof (xf86CrtcRec), 1);
+    if (!crtc)
 	return NULL;
-    xf86_crtc->scrn = scrn;
-    xf86_crtc->funcs = funcs;
+    crtc->scrn = scrn;
+    crtc->funcs = funcs;
 #ifdef RANDR_12_INTERFACE
-    xf86_crtc->randr_crtc = RRCrtcCreate (xf86_crtc);
-    if (!xf86_crtc->randr_crtc)
+    crtc->randr_crtc = RRCrtcCreate (crtc);
+    if (!crtc->randr_crtc)
     {
-	xfree (xf86_crtc);
+	xfree (crtc);
 	return NULL;
     }
 #endif
-    return xf86_crtc;
+    xf86_config->crtc[xf86_config->num_crtc++] = crtc;
+    return crtc;
 }
 
 void
-i830xf86CrtcDestroy (I830_xf86CrtcPtr xf86_crtc)
+xf86CrtcDestroy (xf86CrtcPtr crtc)
 {
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    int			c;
+    
+    (*crtc->funcs->destroy) (crtc);
 #ifdef RANDR_12_INTERFACE
-    RRCrtcDestroy (xf86_crtc->randr_crtc);
+    RRCrtcDestroy (crtc->randr_crtc);
 #endif
-    xfree (xf86_crtc);
+    for (c = 0; c < xf86_config->num_crtc; c++)
+	if (xf86_config->crtc[c] == crtc)
+	{
+	    memmove (&xf86_config->crtc[c],
+		     &xf86_config->crtc[c+1],
+		     xf86_config->num_crtc - (c + 1));
+	    xf86_config->num_crtc--;
+	    break;
+	}
+    xfree (crtc);
 }
 
 /*
  * Output functions
  */
-I830_xf86OutputPtr
-i830xf86OutputCreate (ScrnInfoPtr		    scrn,
-		      const I830_xf86OutputFuncsRec *funcs,
-		      const char		    *name)
+xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr		    scrn,
+		  const xf86OutputFuncsRec *funcs,
+		  const char		    *name)
 {
-    I830_xf86OutputPtr	output;
-    I830Ptr		pI830 = I830PTR(scrn);
+    xf86OutputPtr	output;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
     int			len = strlen (name);
 
-    output = xcalloc (sizeof (I830_xf86OutputRec) + len + 1, 1);
+    output = xcalloc (sizeof (xf86OutputRec) + len + 1, 1);
     if (!output)
 	return NULL;
     output->scrn = scrn;
@@ -96,16 +109,16 @@ i830xf86OutputCreate (ScrnInfoPtr		    s
 	return NULL;
     }
 #endif
-    pI830->xf86_output[pI830->num_outputs++] = output;
+    xf86_config->output[xf86_config->num_output++] = output;
     return output;
 }
 
 void
-i830xf86OutputDestroy (I830_xf86OutputPtr output)
+xf86OutputDestroy (xf86OutputPtr output)
 {
-    ScrnInfoPtr	scrn = output->scrn;
-    I830Ptr	pI830 = I830PTR(scrn);
-    int		o;
+    ScrnInfoPtr		scrn = output->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			o;
     
     (*output->funcs->destroy) (output);
 #ifdef RANDR_12_INTERFACE
@@ -113,13 +126,13 @@ i830xf86OutputDestroy (I830_xf86OutputPt
 #endif
     while (output->probed_modes)
 	xf86DeleteMode (&output->probed_modes, output->probed_modes);
-    for (o = 0; o < pI830->num_outputs; o++)
-	if (pI830->xf86_output[o] == output)
+    for (o = 0; o < xf86_config->num_output; o++)
+	if (xf86_config->output[o] == output)
 	{
-	    memmove (&pI830->xf86_output[o],
-		     &pI830->xf86_output[o+1],
-		     pI830->num_outputs - (o + 1));
-	    pI830->num_outputs--;
+	    memmove (&xf86_config->output[o],
+		     &xf86_config->output[o+1],
+		     xf86_config->num_output - (o + 1));
+	    xf86_config->num_output--;
 	    break;
 	}
     xfree (output);
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 32f84af..1f9a03e 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -19,15 +19,15 @@
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  */
-#ifndef _I830_XF86CRTC_H_
-#define _I830_XF86CRTC_H_
+#ifndef _XF86CRTC_H_
+#define _XF86CRTC_H_
 
 #include <edid.h>
 #include "i830_xf86Modes.h"
 
-typedef struct _I830_xf86Crtc I830_xf86CrtcRec, *I830_xf86CrtcPtr;
+typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
 
-typedef struct _I830_xf86CrtcFuncs {
+typedef struct _xf86CrtcFuncs {
    /**
     * Turns the crtc on/off, or sets intermediate power levels if available.
     *
@@ -36,33 +36,33 @@ typedef struct _I830_xf86CrtcFuncs {
     * disabled afterwards.
     */
    void
-    (*dpms)(I830_xf86CrtcPtr		crtc,
-	    int				mode);
+    (*dpms)(xf86CrtcPtr		crtc,
+	    int		    	mode);
 
    /**
     * Saves the crtc's state for restoration on VT switch.
     */
    void
-    (*save)(I830_xf86CrtcPtr		crtc);
+    (*save)(xf86CrtcPtr		crtc);
 
    /**
     * Restore's the crtc's state at VT switch.
     */
    void
-    (*restore)(I830_xf86CrtcPtr		crtc);
+    (*restore)(xf86CrtcPtr	crtc);
 
     /**
      * Clean up driver-specific bits of the crtc
      */
     void
-    (*destroy) (I830_xf86CrtcPtr	crtc);
-} I830_xf86CrtcFuncsRec, *I830_xf86CrtcFuncsPtr;
+    (*destroy) (xf86CrtcPtr	crtc);
+} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
-struct _I830_xf86Crtc {
+struct _xf86Crtc {
     /**
      * Associated ScrnInfo
      */
-    ScrnInfoPtr		scrn;
+    ScrnInfoPtr	    scrn;
     
     /**
      * Active state of this CRTC
@@ -104,7 +104,7 @@ struct _I830_xf86Crtc {
     DisplayModeRec  desiredMode;
     
     /** crtc-specific functions */
-    const I830_xf86CrtcFuncsRec *funcs;
+    const xf86CrtcFuncsRec *funcs;
 
     /**
      * Driver private
@@ -126,9 +126,9 @@ struct _I830_xf86Crtc {
 #endif
 };
 
-typedef struct _I830_xf86Output I830_xf86OutputRec, *I830_xf86OutputPtr;
+typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
 
-typedef struct _I830_xf86OutputFuncs {
+typedef struct _xf86OutputFuncs {
     /**
      * Turns the output on/off, or sets intermediate power levels if available.
      *
@@ -137,20 +137,20 @@ typedef struct _I830_xf86OutputFuncs {
      * disabled afterwards.
      */
     void
-    (*dpms)(I830_xf86OutputPtr	output,
+    (*dpms)(xf86OutputPtr	output,
 	    int			mode);
 
     /**
      * Saves the output's state for restoration on VT switch.
      */
     void
-    (*save)(I830_xf86OutputPtr		output);
+    (*save)(xf86OutputPtr	output);
 
     /**
      * Restore's the output's state at VT switch.
      */
     void
-    (*restore)(I830_xf86OutputPtr	output);
+    (*restore)(xf86OutputPtr	output);
 
     /**
      * Callback for testing a video mode for a given output.
@@ -161,8 +161,8 @@ typedef struct _I830_xf86OutputFuncs {
      * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
      */
     int
-    (*mode_valid)(I830_xf86OutputPtr	output,
-		  DisplayModePtr	pMode);
+    (*mode_valid)(xf86OutputPtr	    output,
+		  DisplayModePtr    pMode);
 
     /**
      * Callback for setting up a video mode before any crtc/dpll changes.
@@ -171,22 +171,22 @@ typedef struct _I830_xf86OutputFuncs {
      * unknown (such as the restore path of VT switching).
      */
     void
-    (*pre_set_mode)(I830_xf86OutputPtr  output,
-		    DisplayModePtr	pMode);
+    (*pre_set_mode)(xf86OutputPtr   output,
+		    DisplayModePtr  pMode);
 
     /**
      * Callback for setting up a video mode after the DPLL update but before
      * the plane is enabled.
      */
     void
-    (*post_set_mode)(I830_xf86OutputPtr	output,
-		     DisplayModePtr	pMode);
+    (*post_set_mode)(xf86OutputPtr  output,
+		     DisplayModePtr pMode);
 
     /**
      * Probe for a connected output, and return detect_status.
      */
     enum detect_status
-    (*detect)(I830_xf86OutputPtr	output);
+    (*detect)(xf86OutputPtr	    output);
 
     /**
      * Query the device for the modes it provides.
@@ -196,16 +196,16 @@ typedef struct _I830_xf86OutputFuncs {
      * \return singly-linked list of modes or NULL if no modes found.
      */
     DisplayModePtr
-    (*get_modes)(I830_xf86OutputPtr	output);
+    (*get_modes)(xf86OutputPtr	    output);
 
     /**
      * Clean up driver-specific bits of the output
      */
     void
-    (*destroy) (I830_xf86OutputPtr	output);
-} I830_xf86OutputFuncsRec, *I830_xf86OutputFuncsPtr;
+    (*destroy) (xf86OutputPtr	    output);
+} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
 
-struct _I830_xf86Output {
+struct _xf86Output {
     /**
      * Associated ScrnInfo
      */
@@ -215,7 +215,7 @@ struct _I830_xf86Output {
      *
      * If this output is not in use, this field will be NULL.
      */
-    I830_xf86CrtcPtr	crtc;
+    xf86CrtcPtr		crtc;
     /**
      * List of available modes on this output.
      *
@@ -234,7 +234,7 @@ struct _I830_xf86Output {
     char		*name;
 
     /** output-specific functions */
-    const I830_xf86OutputFuncsRec *funcs;
+    const xf86OutputFuncsRec *funcs;
 
     /** driver private information */
     void		*driver_private;
@@ -252,15 +252,28 @@ struct _I830_xf86Output {
 #endif
 };
 
+#define XF86_MAX_CRTC	4
+#define XF86_MAX_OUTPUT	16
+
+typedef struct _xf86CrtcConfig {
+   int			num_output;
+   xf86OutputPtr	output[XF86_MAX_OUTPUT];
+    
+   int			num_crtc;
+   xf86CrtcPtr		crtc[XF86_MAX_CRTC];
+} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
+
+#define XF86_CRTC_CONFIG_PTR(p)	((xf86CrtcConfigPtr) ((p)->driverPrivate))
+
 /*
  * Crtc functions
  */
-I830_xf86CrtcPtr
-i830xf86CrtcCreate (ScrnInfoPtr			scrn,
-		    const I830_xf86CrtcFuncsRec	*funcs);
+xf86CrtcPtr
+xf86CrtcCreate (ScrnInfoPtr		scrn,
+		const xf86CrtcFuncsRec	*funcs);
 
 void
-i830xf86CrtcDestroy (I830_xf86CrtcPtr		xf86_crtc);
+xf86CrtcDestroy (xf86CrtcPtr		crtc);
 
 
 /**
@@ -270,8 +283,8 @@ i830xf86CrtcDestroy (I830_xf86CrtcPtr		x
  * the specified output
  */
 
-I830_xf86CrtcPtr 
-i830xf86AllocCrtc (I830_xf86OutputPtr		output);
+xf86CrtcPtr 
+xf86AllocCrtc (xf86OutputPtr		output);
 
 /**
  * Free a crtc
@@ -280,17 +293,17 @@ i830xf86AllocCrtc (I830_xf86OutputPtr		o
  */
 
 void
-i830xf86FreeCrtc (I830_xf86CrtcPtr crtc);
+xf86FreeCrtc (xf86CrtcPtr		crtc);
 
 /*
  * Output functions
  */
-I830_xf86OutputPtr
-i830xf86OutputCreate (ScrnInfoPtr		    scrn,
-		      const I830_xf86OutputFuncsRec *funcs,
-		      const char		    *name);
+xf86OutputPtr
+xf86OutputCreate (ScrnInfoPtr		scrn,
+		      const xf86OutputFuncsRec *funcs,
+		      const char	*name);
 
 void
-i830xf86OutputDestroy (I830_xf86OutputPtr	xf86_output);
+xf86OutputDestroy (xf86OutputPtr	output);
 
-#endif /* _I830_XF86CRTC_H_ */
+#endif /* _XF86CRTC_H_ */
diff-tree a0518f5a440630365b1d935b7c2d0725f326ad51 (from a47c549df036990e29f05bc3df80e1a2ab9f3b3c)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Nov 26 19:44:38 2006 -0800

    Remove mode setting from load detect CRTC allocation.
    
    To share load-detect CRTC allocation with TV driver,
    move it to the output driver

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 3d75587..716afbc 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -296,7 +296,27 @@ i830_crt_detect(I830_xf86OutputPtr outpu
     
     if (crtc)
     {
-	Bool connected = i830_crt_detect_load(crtc, output);
+	/* VESA 640x480x72Hz mode to set on the pipe */
+	static DisplayModeRec   mode = {
+	    NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
+	    31500,
+	    640, 664, 704, 832, 0,
+	    480, 489, 491, 520, 0,
+	    V_NHSYNC | V_NVSYNC,
+	    0, 0,
+	    0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0,
+	    FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
+	};
+	Bool			connected;
+	I830OutputPrivatePtr	intel_output = output->driver_private;
+	
+	if (intel_output->load_detect_temp)
+	{
+	    I830xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
+	    i830PipeSetMode (crtc, &mode, FALSE);
+	}
+	connected = i830_crt_detect_load (crtc, output);
 
 	i830ReleaseLoadDetectPipe (output);
 	if (connected)
diff --git a/src/i830_display.c b/src/i830_display.c
index 9baa39b..ba59f56 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -930,18 +930,6 @@ i830GetLoadDetectPipe(I830_xf86OutputPtr
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I830_xf86CrtcPtr	    crtc;
     int			    i;
-    /* VESA 640x480x72Hz mode to set on the pipe */
-    static DisplayModeRec   mode = {
-	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
-	31500,
-	640, 664, 704, 832, 0,
-	480, 489, 491, 520, 0,
-	V_NHSYNC | V_NVSYNC,
-	0, 0,
-	0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0,
-	FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
-    };
 
     if (output->crtc) 
 	return output->crtc;
@@ -958,9 +946,6 @@ i830GetLoadDetectPipe(I830_xf86OutputPtr
     output->crtc = crtc;
     intel_output->load_detect_temp = TRUE;
 
-    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
-    i830PipeSetMode(crtc, &mode, FALSE);
-
     return crtc;
 }
 
diff-tree a47c549df036990e29f05bc3df80e1a2ab9f3b3c (from 2529863a1ade782819d76be2d0dc16e89028c1e3)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Nov 26 18:26:26 2006 -0800

    Clean up reworked data structure code so the server actually starts.
    
    Use i830GeLoadDetectPipe again (instead of missing xf86AllocCrtc).  Actually
    create new Crtc structures. Fix a few other NULL pointer dereferences.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 615e96a..3d75587 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -292,13 +292,13 @@ i830_crt_detect(I830_xf86OutputPtr outpu
 	return OUTPUT_STATUS_CONNECTED;
 
     /* Use the load-detect method if we have no other way of telling. */
-    crtc = i830xf86AllocCrtc (output);
+    crtc = i830GetLoadDetectPipe (output);
     
     if (crtc)
     {
 	Bool connected = i830_crt_detect_load(crtc, output);
 
-	i830xf86FreeCrtc (crtc);
+	i830ReleaseLoadDetectPipe (output);
 	if (connected)
 	    return OUTPUT_STATUS_CONNECTED;
 	else
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d4d5fbc..4d6e816 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -667,6 +667,34 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_tv_init(pScrn);
 }
 
+/**
+ * Setup the CRTCs
+ */
+
+static const I830_xf86CrtcFuncsRec i830_crtc_funcs = {
+};
+
+static void
+I830SetupCrtcs(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+    int	    p;
+
+    for (p = 0; p < pI830->num_pipes; p++)
+    {
+	I830_xf86CrtcPtr    crtc = i830xf86CrtcCreate (pScrn, &i830_crtc_funcs);
+	I830CrtcPrivatePtr  intel_crtc;
+	
+	if (!crtc)
+	    break;
+	intel_crtc = xnfcalloc (sizeof (I830CrtcPrivateRec), 1);
+	intel_crtc->pipe = p;
+	
+	crtc->driver_private = intel_crtc;
+	pI830->xf86_crtc[p] = crtc;
+    }
+}
+    
 static void 
 I830PreInitDDC(ScrnInfoPtr pScrn)
 {
@@ -685,8 +713,6 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
       if (xf86LoadSubModule(pScrn, "i2c")) {
 	 xf86LoaderReqSymLists(I810i2cSymbols, NULL);
 
-	 I830SetupOutputs(pScrn);
-
 	 pI830->ddc2 = TRUE;
       } else {
 	 pI830->ddc2 = FALSE;
@@ -1241,6 +1267,8 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 
    I830PreInitDDC(pScrn);
+   I830SetupOutputs(pScrn);
+   I830SetupCrtcs(pScrn);
 
    if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) {
       if (pI830->num_pipes == 1) {
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d6a3131..59c07ff 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -1215,17 +1215,17 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     {
 	I830_xf86OutputPtr  output = pI830->xf86_output[o];
 	RRModePtr	    randr_mode = output_modes[o];
+        RRCrtcPtr	    randr_crtc = output_crtcs[o];
 	DisplayModePtr	    mode;
-	RRCrtcPtr	    randr_crtc = output_crtcs[o];
-	I830_xf86CrtcPtr    crtc = randr_crtc->devPrivate;
 
-	if (randr_mode)
+	if (randr_mode && randr_crtc)
+	{
+	    I830_xf86CrtcPtr    crtc = randr_crtc->devPrivate;
+	    
 	    mode = (DisplayModePtr) randr_mode->devPrivate;
-	else
-	    mode = NULL;
-	if (mode)
 	    crtc->desiredMode = *mode;
-	output->crtc = crtc;
+	    output->crtc = crtc;
+	}
     }
 #endif
     i830_set_xf86_modes_from_outputs (pScrn);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index d0a3119..630f3fa 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -39,8 +39,8 @@
  * Crtc functions
  */
 I830_xf86CrtcPtr
-i830xf86CrtcCreate (ScrnInfoPtr		    scrn,
-		    I830_xf86CrtcFuncsPtr   funcs)
+i830xf86CrtcCreate (ScrnInfoPtr			scrn,
+		    const I830_xf86CrtcFuncsRec	*funcs)
 {
     I830_xf86CrtcPtr	xf86_crtc;
 
@@ -119,6 +119,7 @@ i830xf86OutputDestroy (I830_xf86OutputPt
 	    memmove (&pI830->xf86_output[o],
 		     &pI830->xf86_output[o+1],
 		     pI830->num_outputs - (o + 1));
+	    pI830->num_outputs--;
 	    break;
 	}
     xfree (output);
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 6a52517..32f84af 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -257,7 +257,7 @@ struct _I830_xf86Output {
  */
 I830_xf86CrtcPtr
 i830xf86CrtcCreate (ScrnInfoPtr			scrn,
-		    const I830_xf86CrtcFuncsPtr	funcs);
+		    const I830_xf86CrtcFuncsRec	*funcs);
 
 void
 i830xf86CrtcDestroy (I830_xf86CrtcPtr		xf86_crtc);
diff-tree 2529863a1ade782819d76be2d0dc16e89028c1e3 (from 9aca4e207440119f4280b78199a221f85d50c511)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Nov 26 16:44:17 2006 -0800

    Start output/crtc restructuring work. It compiles.
    
    Outputs and Crtcs are now split between 'generic'
    and 'driver specific' pieces in the hope that more code
    will be able to migrate to the xf86-generic layer.
    
    Right now, the code remains tangled together, significant
    work remains to tease the pieces apart. First the code
    needs to be made to actually work as-is though.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0fce5e4..0a14d1a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,8 @@ i810_drv_la_SOURCES = \
 	 i830_tv.c \
 	 i830_xf86Modes.h \
 	 i830_xf86Modes.c \
+	 i830_xf86Crtc.h \
+	 i830_xf86Crtc.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
diff --git a/src/i830.h b/src/i830.h
index 32a540e..2f106c7 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "vbe.h"
 #include "vgaHW.h"
 #include "randrstr.h"
+#include "i830_xf86Crtc.h"
 
 #ifdef XF86DRI
 #include "xf86drm.h"
@@ -188,6 +189,25 @@ enum detect_status {
    OUTPUT_STATUS_UNKNOWN
 };
 
+typedef struct _I830CrtcPrivateRec {
+    int			    pipe;
+    Bool		    gammaEnabled;
+} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
+
+#define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
+
+typedef struct _I830OutputPrivateRec {
+   int			    type;
+   I2CBusPtr		    pI2CBus;
+   I2CBusPtr		    pDDCBus;
+   struct _I830DVODriver    *i2c_drv;
+   Bool			    load_detect_temp;
+   /** Output-private structure.  Should replace i2c_drv */
+   void			    *dev_priv;
+} I830OutputPrivateRec, *I830OutputPrivatePtr;
+
+#define I830OutputPrivate(o) ((I830OutputPrivatePtr) (o)->driver_private)
+
 struct _I830OutputRec {
    int type;
    int pipe;
@@ -467,10 +487,16 @@ typedef struct _I830Rec {
 
    Bool checkDevices;
 
+   /* XXX outputs and crtcs need to move to ScrnInfoRec */
+   int num_outputs;
+/*   struct _I830OutputRec output[MAX_OUTPUTS]; */
+   I830_xf86OutputPtr	xf86_output[MAX_OUTPUTS];
+    
    /* [0] is Pipe A, [1] is Pipe B. */
    int num_pipes;
    /* [0] is display plane A, [1] is display plane B. */
-   I830PipeRec	  pipes[MAX_DISPLAY_PIPES];
+/*   I830PipeRec	  pipes[MAX_DISPLAY_PIPES]; */
+   I830_xf86CrtcPtr  xf86_crtc[MAX_DISPLAY_PIPES];
    
    /* Driver phase/state information */
    Bool preinit;
@@ -488,8 +514,6 @@ typedef struct _I830Rec {
    OsTimerPtr devicesTimer;
 
    int ddc2;
-   int num_outputs;
-   struct _I830OutputRec output[MAX_OUTPUTS];
 
    /* Panel size pulled from the BIOS */
    int PanelXRes, PanelYRes;
@@ -580,7 +604,7 @@ extern void I830PrintErrorState(ScrnInfo
 extern void I965PrintErrorState(ScrnInfoPtr pScrn);
 extern void I830Sync(ScrnInfoPtr pScrn);
 extern void I830InitHWCursor(ScrnInfoPtr pScrn);
-extern void I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force);
+extern void I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force);
 extern Bool I830CursorInit(ScreenPtr pScreen);
 extern void IntelEmitInvarientState(ScrnInfoPtr pScrn);
 extern void I830EmitInvarientState(ScrnInfoPtr pScrn);
@@ -661,7 +685,7 @@ extern Bool I830I2CInit(ScrnInfoPtr pScr
 
 /* i830_display.c */
 Bool
-i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type);
+i830PipeHasType (I830_xf86CrtcPtr crtc, int type);
 
 /* i830_crt.c */
 void i830_crt_init(ScrnInfoPtr pScrn);
@@ -685,7 +709,7 @@ int I830ValidateXF86ModeList(ScrnInfoPtr
 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(ScrnInfoPtr pScrn, I830OutputPtr output);
+DisplayModePtr i830_ddc_get_modes(I830_xf86OutputPtr output);
 
 /* i830_randr.c */
 Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
diff --git a/src/i830_crt.c b/src/i830_crt.c
index f067260..615e96a 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -35,10 +35,11 @@
 #include "i830_display.h"
 
 static void
-i830_crt_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+i830_crt_dpms(I830_xf86OutputPtr output, int mode)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 temp;
+    ScrnInfoPtr	    pScrn = output->scrn;
+    I830Ptr	    pI830 = I830PTR(pScrn);
+    CARD32	    temp;
 
     temp = INREG(ADPA);
     temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
@@ -63,24 +64,25 @@ i830_crt_dpms(ScrnInfoPtr pScrn, I830Out
 }
 
 static void
-i830_crt_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_crt_save (I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
 
     pI830->saveADPA = INREG(ADPA);
 }
 
 static void
-i830_crt_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_crt_restore (I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
 
     OUTREG(ADPA, pI830->saveADPA);
 }
 
 static int
-i830_crt_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
-		    DisplayModePtr pMode)
+i830_crt_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
@@ -92,19 +94,24 @@ i830_crt_mode_valid(ScrnInfoPtr pScrn, I
 }
 
 static void
-i830_crt_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		      DisplayModePtr pMode)
+i830_crt_pre_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
 }
 
 static void
-i830_crt_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		       DisplayModePtr pMode)
+i830_crt_post_set_mode (I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    int	    dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
-    CARD32  adpa, dpll_md;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830_xf86CrtcPtr	    crtc = output->crtc;
+    I830CrtcPrivatePtr	    i830_crtc = crtc->driver_private;
+    int			    dpll_md_reg;
+    CARD32		    adpa, dpll_md;
 
+    if (i830_crtc->pipe == 0) 
+	dpll_md_reg = DPLL_A_MD;
+    else
+	dpll_md_reg = DPLL_B_MD;
     /*
      * Disable separate mode multiplier used when cloning SDVO to CRT
      * XXX this needs to be adjusted when we really are cloning
@@ -122,7 +129,7 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn
     if (pMode->Flags & V_PVSYNC)
 	adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
-    if (output->pipe == 0)
+    if (i830_crtc->pipe == 0)
 	adpa |= ADPA_PIPE_A_SELECT;
     else
 	adpa |= ADPA_PIPE_B_SELECT;
@@ -139,12 +146,13 @@ i830_crt_post_set_mode(ScrnInfoPtr pScrn
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_hotplug(ScrnInfoPtr pScrn)
+i830_crt_detect_hotplug(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 temp;
-    const int timeout_ms = 1000;
-    int starttime, curtime;
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
+    CARD32	temp;
+    const int	timeout_ms = 1000;
+    int		starttime, curtime;
 
     temp = INREG(PORT_HOTPLUG_EN);
 
@@ -177,20 +185,25 @@ i830_crt_detect_hotplug(ScrnInfoPtr pScr
  * \return FALSE if CRT is disconnected.
  */
 static Bool
-i830_crt_detect_load(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_crt_detect_load (I830_xf86CrtcPtr	    crtc,
+		      I830_xf86OutputPtr    output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 save_adpa, adpa, pipeconf, bclrpat;
-    CARD8 st00;
-    int pipeconf_reg, bclrpat_reg, dpll_reg;
-    int pipe;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr	    i830_crtc = I830CrtcPrivate(crtc);
+    CARD32		    save_adpa, adpa, pipeconf, bclrpat;
+    CARD8		    st00;
+    int			    pipeconf_reg, bclrpat_reg, dpll_reg;
+    int			    pipe = i830_crtc->pipe;
 
-    pipe = output->pipe;
-    if (pipe == 0) {
+    if (pipe == 0) 
+    {
 	bclrpat_reg = BCLRPAT_A;
 	pipeconf_reg = PIPEACONF;
 	dpll_reg = DPLL_A;
-    } else {
+    }
+    else 
+    {
 	bclrpat_reg = BCLRPAT_B;
 	pipeconf_reg = PIPEBCONF;
 	dpll_reg = DPLL_B;
@@ -244,17 +257,15 @@ i830_crt_detect_load(ScrnInfoPtr pScrn, 
  * \return FALSE if no DDC response was detected.
  */
 static Bool
-i830_crt_detect_ddc(ScrnInfoPtr pScrn)
+i830_crt_detect_ddc(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct _I830OutputRec *output;
+    I830OutputPrivatePtr    i830_output = output->driver_private;
 
-    output = &pI830->output[0];
     /* CRT should always be at 0, but check anyway */
-    if (output->type != I830_OUTPUT_ANALOG)
+    if (i830_output->type != I830_OUTPUT_ANALOG)
 	return FALSE;
 
-    return xf86I2CProbeAddress(output->pDDCBus, 0x00A0);
+    return xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
 }
 
 /**
@@ -264,25 +275,30 @@ i830_crt_detect_ddc(ScrnInfoPtr pScrn)
  *        on active displays.
  */
 static enum detect_status
-i830_crt_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_crt_detect(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830_xf86CrtcPtr	    crtc;
 
     if (IS_I945G(pI830) || IS_I945GM(pI830) || IS_I965G(pI830)) {
-	if (i830_crt_detect_hotplug(pScrn))
+	if (i830_crt_detect_hotplug(output))
 	    return OUTPUT_STATUS_CONNECTED;
 	else
 	    return OUTPUT_STATUS_DISCONNECTED;
     }
 
-    if (i830_crt_detect_ddc(pScrn))
+    if (i830_crt_detect_ddc(output))
 	return OUTPUT_STATUS_CONNECTED;
 
     /* Use the load-detect method if we have no other way of telling. */
-    if (i830GetLoadDetectPipe(pScrn, output) != -1) {
-	Bool connected = i830_crt_detect_load(pScrn, output);
+    crtc = i830xf86AllocCrtc (output);
+    
+    if (crtc)
+    {
+	Bool connected = i830_crt_detect_load(crtc, output);
 
-	i830ReleaseLoadDetectPipe(pScrn, output);
+	i830xf86FreeCrtc (crtc);
 	if (connected)
 	    return OUTPUT_STATUS_CONNECTED;
 	else
@@ -293,16 +309,17 @@ i830_crt_detect(ScrnInfoPtr pScrn, I830O
 }
 
 static DisplayModePtr
-i830_crt_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_crt_get_modes(I830_xf86OutputPtr output)
 {
-    DisplayModePtr modes;
+    ScrnInfoPtr		pScrn = output->scrn;
+    DisplayModePtr	modes;
     MonRec fixed_mon;
 
-    modes = i830_ddc_get_modes(pScrn, output);
+    modes = i830_ddc_get_modes(output);
     if (modes != NULL)
 	return modes;
 
-    if (output->detect(pScrn, output) == OUTPUT_STATUS_DISCONNECTED)
+    if ((*output->funcs->detect)(output) == OUTPUT_STATUS_DISCONNECTED)
 	return NULL;
 
     /* We've got a potentially-connected monitor that we can't DDC.  Return a
@@ -323,24 +340,43 @@ i830_crt_get_modes(ScrnInfoPtr pScrn, I8
     return modes;
 }
 
+static void
+i830_crt_destroy (I830_xf86OutputPtr output)
+{
+    if (output->driver_private)
+	xfree (output->driver_private);
+}
+
+static const I830_xf86OutputFuncsRec i830_crt_output_funcs = {
+    .dpms = i830_crt_dpms,
+    .save = i830_crt_save,
+    .restore = i830_crt_restore,
+    .mode_valid = i830_crt_mode_valid,
+    .pre_set_mode = i830_crt_pre_set_mode,
+    .post_set_mode = i830_crt_post_set_mode,
+    .detect = i830_crt_detect,
+    .get_modes = i830_crt_get_modes,
+    .destroy = i830_crt_destroy
+};
+
 void
 i830_crt_init(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    I830_xf86OutputPtr	    output;
+    I830OutputPrivatePtr    i830_output;
 
-    pI830->output[pI830->num_outputs].type = I830_OUTPUT_ANALOG;
-    pI830->output[pI830->num_outputs].dpms = i830_crt_dpms;
-    pI830->output[pI830->num_outputs].save = i830_crt_save;
-    pI830->output[pI830->num_outputs].restore = i830_crt_restore;
-    pI830->output[pI830->num_outputs].mode_valid = i830_crt_mode_valid;
-    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_crt_get_modes;
+    output = i830xf86OutputCreate (pScrn, &i830_crt_output_funcs, "VGA");
+    if (!output)
+	return;
+    i830_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+    if (!i830_output)
+    {
+	i830xf86OutputDestroy (output);
+	return;
+    }
+    i830_output->type = I830_OUTPUT_ANALOG;
+    output->driver_private = i830_output;
 
     /* Set up the DDC bus. */
-    I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
-		GPIOA, "CRTDDC_A");
-
-    pI830->num_outputs++;
+    I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
 }
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 517bd3e..a3526f8 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -80,11 +80,14 @@ static Bool I830UseHWCursorARGB(ScreenPt
 #endif
 
 static void
-I830SetPipeCursorBase (ScrnInfoPtr pScrn, int pipe)
+I830SetPipeCursorBase (I830_xf86CrtcPtr crtc)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
-    I830MemRange *cursor_mem;
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int			pipe = intel_crtc->pipe;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    int			cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
+    I830MemRange	*cursor_mem;
 
     if (pipe >= pI830->num_pipes)
 	FatalError("Bad pipe number for cursor base setting\n");
@@ -102,18 +105,20 @@ I830SetPipeCursorBase (ScrnInfoPtr pScrn
 }
 
 void
-I830SetPipeCursor (ScrnInfoPtr pScrn, int pipe, Bool force)
+I830SetPipeCursor (I830_xf86CrtcPtr crtc, Bool force)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   I830PipePtr pI830Pipe = &pI830->pipes[pipe];
-   CARD32 temp;
-    Bool show;
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int			pipe = intel_crtc->pipe;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    CARD32		temp;
+    Bool		show;
     
-    if (!pI830Pipe->enabled)
+    if (!crtc->enabled)
 	return;
 
-    show = pI830->cursorOn && pI830Pipe->cursorInRange;
-    if (show && (force || !pI830Pipe->cursorShown))
+    show = pI830->cursorOn && crtc->cursorInRange;
+    if (show && (force || !crtc->cursorShown))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
 	    int	cursor_control;
@@ -125,7 +130,7 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 	    if (pI830->CursorIsARGB) {
 		temp |= CURSOR_MODE_64_ARGB_AX;
-		if (pI830Pipe->gammaEnabled)
+		if (intel_crtc->gammaEnabled)
 		    temp |= MCURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_MODE_64_4C_AX;
@@ -139,15 +144,15 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp |= CURSOR_ENABLE;
 	    if (pI830->CursorIsARGB) {
 		temp |= CURSOR_FORMAT_ARGB;
-		if (pI830Pipe->gammaEnabled)
+		if (intel_crtc->gammaEnabled)
 		    temp |= CURSOR_GAMMA_ENABLE;
 	    } else
 		temp |= CURSOR_FORMAT_3C;
 	    OUTREG(CURSOR_CONTROL, temp);
 	}
-	pI830Pipe->cursorShown = TRUE;
+	crtc->cursorShown = TRUE;
     }
-    else if (!show && (force || pI830Pipe->cursorShown))
+    else if (!show && (force || crtc->cursorShown))
     {
 	if (IS_MOBILE(pI830) || IS_I9XX(pI830)) 
 	{
@@ -165,11 +170,11 @@ I830SetPipeCursor (ScrnInfoPtr pScrn, in
 	    temp &= ~(CURSOR_ENABLE|CURSOR_GAMMA_ENABLE);
 	    OUTREG(CURSOR_CONTROL, temp);
 	}
-	pI830Pipe->cursorShown = FALSE;
+	crtc->cursorShown = FALSE;
     }
 
     /* Flush cursor changes. */
-    I830SetPipeCursorBase(pScrn, pipe);
+    I830SetPipeCursorBase(crtc);
 }
 
 void
@@ -181,7 +186,8 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 
    DPRINTF(PFX, "I830InitHWCursor\n");
    for (i = 0; i < pI830->num_pipes; i++) 
-      pI830->pipes[i].cursorShown = FALSE;
+      pI830->xf86_crtc[i]->cursorShown = FALSE;
+
    /* Initialise the HW cursor registers, leaving the cursor hidden. */
    if (IS_MOBILE(pI830) || IS_I9XX(pI830)) {
       for (i = 0; i < pI830->num_pipes; i++)
@@ -198,7 +204,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
 	    temp |= CURSOR_MODE_64_4C_AX;
 	 /* Need to set control, then address. */
 	 OUTREG(cursor_control, temp);
-	 I830SetPipeCursorBase(pScrn, i);
+	 I830SetPipeCursorBase(pI830->xf86_crtc[i]);
       }
    } else {
       temp = INREG(CURSOR_CONTROL);
@@ -211,7 +217,7 @@ I830InitHWCursor(ScrnInfoPtr pScrn)
       /* This initialises the format and leave the cursor disabled. */
       OUTREG(CURSOR_CONTROL, temp);
       /* Need to set address and size after disabling. */
-      I830SetPipeCursorBase(pScrn, 0);
+      I830SetPipeCursorBase(pI830->xf86_crtc[0]);
       temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) |
 	     ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT);
       OUTREG(CURSOR_SIZE, temp);
@@ -486,12 +492,12 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 
     for (pipe = 0; pipe < pI830->num_pipes; pipe++)
     {
-	I830PipePtr	pI830Pipe = &pI830->pipes[pipe];
-	DisplayModePtr	mode = &pI830Pipe->curMode;
-	int		thisx = x - pI830Pipe->x;
-	int		thisy = y - pI830Pipe->y;
+	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[pipe];
+	DisplayModePtr	    mode = &crtc->curMode;
+	int		    thisx = x - crtc->x;
+	int		    thisy = y - crtc->y;
 
-	if (!pI830Pipe->enabled)
+	if (!crtc->enabled)
 	    continue;
 
 	/*
@@ -527,9 +533,9 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	if (pipe == 1)
 	    OUTREG(CURSOR_B_POSITION, temp);
 
-	pI830Pipe->cursorInRange = inrange;
+	crtc->cursorInRange = inrange;
 	
-        I830SetPipeCursor (pScrn, pipe, FALSE);
+        I830SetPipeCursor (crtc, FALSE);
     }
 }
 
@@ -551,7 +557,7 @@ I830ShowCursor(ScrnInfoPtr pScrn)
 
     pI830->cursorOn = TRUE;
     for (pipe = 0; pipe < pI830->num_pipes; pipe++)
-	I830SetPipeCursor (pScrn, pipe, TRUE);
+	I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE);
 }
 
 static void
@@ -564,13 +570,14 @@ I830HideCursor(ScrnInfoPtr pScrn)
 
    pI830->cursorOn = FALSE;
     for (pipe = 0; pipe < pI830->num_pipes; pipe++)
-	I830SetPipeCursor (pScrn, pipe, TRUE);
+	I830SetPipeCursor (pI830->xf86_crtc[pipe], TRUE);
 }
 
 static void
 I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   int pipe; 
 
 #ifdef ARGB_CURSOR
     /* Don't recolour cursors set with SetCursorARGB. */
@@ -580,18 +587,17 @@ I830SetCursorColors(ScrnInfoPtr pScrn, i
 
    DPRINTF(PFX, "I830SetCursorColors\n");
 
-   if (pI830->pipes[0].enabled)
+   for (pipe = 0; pipe < pI830->num_pipes; pipe++)
    {
-       OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff);
-       OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff);
-       OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff);
-       OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff);
-   }
-   if (pI830->pipes[1].enabled)
-   {
-      OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff);
-      OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff);
-      OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff);
-      OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff);
+      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[pipe];
+      int		pal0 = pipe == 0 ? CURSOR_A_PALETTE0 : CURSOR_B_PALETTE0;
+
+      if (crtc->enabled)
+      {
+	 OUTREG(pal0 +  0, bg & 0x00ffffff);
+	 OUTREG(pal0 +  4, fg & 0x00ffffff);
+	 OUTREG(pal0 +  8, fg & 0x00ffffff);
+	 OUTREG(pal0 + 12, bg & 0x00ffffff);
+      }
    }
 }
diff --git a/src/i830_display.c b/src/i830_display.c
index 04f85cc..9baa39b 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -61,20 +61,25 @@ i830PrintPll(char *prefix, int refclk, i
 }
 
 /**
- * Returns whether any output on the specified pipe is an LVDS output
+ * Returns whether any output on the specified pipe is of the specified type
  */
 Bool
-i830PipeHasType (ScrnInfoPtr pScrn, int pipe, int type)
+i830PipeHasType (I830_xf86CrtcPtr crtc, int type)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    int	    i;
+    ScrnInfoPtr	pScrn = crtc->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
+    int		i;
 
     for (i = 0; i < pI830->num_outputs; i++)
-	if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
+    {
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	if (output->crtc == crtc)
 	{
-	    if (pI830->output[i].type == type)
+	    I830OutputPrivatePtr    intel_output = output->driver_private;
+	    if (intel_output->type == type)
 		return TRUE;
 	}
+    }
     return FALSE;
 }
 
@@ -86,9 +91,10 @@ i830PipeHasType (ScrnInfoPtr pScrn, int 
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830PllIsValid(ScrnInfoPtr pScrn, int pipe, int refclk, int m1, int m2,
+i830PllIsValid(I830_xf86CrtcPtr crtc, int refclk, int m1, int m2,
 	       int n, int p1, int p2)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     int p, m, vco, dotclock;
     int min_m1, max_m1, min_m2, max_m2, min_m, max_m, min_n, max_n;
@@ -105,7 +111,7 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pi
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
+	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
 	    min_p = 7;
 	    max_p = 98;
 	} else {
@@ -171,9 +177,10 @@ i830PllIsValid(ScrnInfoPtr pScrn, int pi
  * clk = refclk * (5 * m1 + m2) / n / (p1 * p2)
  */
 static Bool
-i830FindBestPLL(ScrnInfoPtr pScrn, int pipe, int target, int refclk,
+i830FindBestPLL(I830_xf86CrtcPtr crtc, int target, int refclk,
 		int *outm1, int *outm2, int *outn, int *outp1, int *outp2)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     int m1, m2, n, p1, p2;
     int err = target;
@@ -188,7 +195,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int p
 	max_n = 8;
 	min_p1 = 1;
 	max_p1 = 8;
-	if (i830PipeHasType (pScrn, pipe, I830_OUTPUT_LVDS)) {
+	if (i830PipeHasType (crtc, I830_OUTPUT_LVDS)) {
 	    /* The single-channel range is 25-112Mhz, and dual-channel
 	     * is 80-224Mhz.  Prefer single channel as much as possible.
 	     */
@@ -224,7 +231,7 @@ i830FindBestPLL(ScrnInfoPtr pScrn, int p
 		for (p1 = min_p1; p1 <= max_p1; p1++) {
 		    int clock, this_err;
 
-		    if (!i830PllIsValid(pScrn, pipe, refclk, m1, m2, n,
+		    if (!i830PllIsValid(crtc, refclk, m1, m2, n,
 					p1, p2)) {
 			continue;
 		    }
@@ -255,10 +262,12 @@ i830WaitForVblank(ScrnInfoPtr pScreen)
 }
 
 void
-i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y)
+i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
-    I830PipePtr pI830Pipe = &pI830->pipes[pipe];
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
     unsigned long Start;
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
@@ -277,8 +286,8 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
     }
 
-    pI830Pipe->x = x;
-    pI830Pipe->y = y;
+    crtc->x = x;
+    crtc->y = y;
 }
 
 /**
@@ -291,19 +300,21 @@ i830PipeSetBase(ScrnInfoPtr pScrn, int p
  * - Closer in refresh rate to the requested mode.
  */
 DisplayModePtr
-i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode)
+i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode)
 {
+    ScrnInfoPtr	pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     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].enabled &&
-	    pI830->output[i].probed_modes != NULL)
+    for (i = 0; i < pI830->num_outputs; i++) 
+    {
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	if (output->crtc == crtc && output->probed_modes != NULL)
 	{
-	    pScan = pI830->output[i].probed_modes;
+	    pScan = output->probed_modes;
+	    break;
 	}
     }
 
@@ -311,9 +322,10 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
      * spam the desired mode in.
      */
     if (pScan == NULL) {
+	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "No pipe mode list for pipe %d,"
-		   "continuing with desired mode\n", pipe);
+		   "continuing with desired mode\n", intel_crtc->pipe);
 	return pMode;
     }
 
@@ -367,6 +379,8 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
 		   "	continuing with desired mode %dx%d@%.1f\n",
 		   pMode->HDisplay, pMode->VDisplay, pMode->VRefresh);
     } else if (!I830ModesEqual(pBest, pMode)) {
+	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
+	int		    pipe = intel_crtc->pipe;
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		   "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 "
 		   "mode %dx%d@%.1f\n", pipe,
@@ -382,13 +396,14 @@ i830PipeFindClosestMode(ScrnInfoPtr pScr
  */
 
 Bool
-i830PipeInUse (ScrnInfoPtr pScrn, int pipe)
+i830PipeInUse (I830_xf86CrtcPtr crtc)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     int	i;
     
     for (i = 0; i < pI830->num_outputs; i++)
-	if (pI830->output[i].enabled && pI830->output[i].pipe == pipe)
+	if (pI830->xf86_output[i]->crtc == crtc)
 	    return TRUE;
     return FALSE;
 }
@@ -402,11 +417,13 @@ i830PipeInUse (ScrnInfoPtr pScrn, int pi
  * display data.
  */
 Bool
-i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode,
 		Bool plane_enable)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
-    I830PipePtr pI830Pipe = &pI830->pipes[pipe];
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    int pipe = intel_crtc->pipe;
     int m1 = 0, m2 = 0, n = 0, p1 = 0, p2 = 0;
     CARD32 dpll = 0, fp = 0, temp;
     CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
@@ -434,28 +451,34 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     Bool didLock = FALSE;
 #endif
 
-    if (I830ModesEqual(&pI830Pipe->curMode, pMode))
+    if (I830ModesEqual(&crtc->curMode, pMode))
 	return TRUE;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n",
 	       pMode->Clock);
 
-    pI830->pipes[pipe].enabled = i830PipeInUse (pScrn, pipe);
+    crtc->enabled = i830PipeInUse (crtc);
     
-    if (!pI830->pipes[pipe].enabled)
+    if (!crtc->enabled)
+    {
+	/* XXX disable crtc? */
 	return TRUE;
+    }
 
 #ifdef XF86DRI
     didLock = I830DRILock(pScrn);
 #endif
     
-    for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].pipe != pipe || !pI830->output[i].enabled)
+    for (i = 0; i < pI830->num_outputs; i++) 
+    {
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	I830OutputPrivatePtr	intel_output = output->driver_private;
+	if (output->crtc != crtc)
 	    continue;
 
-	pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], pMode);
+	(*output->funcs->pre_set_mode)(output, pMode);
 	
-	switch (pI830->output[i].type) {
+	switch (intel_output->type) {
 	case I830_OUTPUT_LVDS:
 	    is_lvds = TRUE;
 	    break;
@@ -549,7 +572,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     } else {
 	refclk = 48000;
     }
-    ok = i830FindBestPLL(pScrn, pipe, pixel_clock, refclk, &m1, &m2, &n,
+    ok = i830FindBestPLL(crtc, pixel_clock, refclk, &m1, &m2, &n,
 			 &p1, &p2);
     if (!ok) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -636,7 +659,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	FatalError("unknown display bpp\n");
     }
 
-    if (pI830Pipe->gammaEnabled) {
+    if (intel_crtc->gammaEnabled) {
  	dspcntr |= DISPPLANE_GAMMA_ENABLE;
     }
 
@@ -672,8 +695,9 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].pipe == pipe)
-	    pI830->output[i].post_set_mode(pScrn, &pI830->output[i], pMode);
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
+	if (output->crtc == crtc)
+	    (*output->funcs->post_set_mode)(output, pMode);
     }
 
     OUTREG(htot_reg, htot);
@@ -685,7 +709,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
     OUTREG(dspstride_reg, pScrn->displayWidth * pI830->cpp);
     OUTREG(dspsize_reg, dspsize);
     OUTREG(dsppos_reg, 0);
-    i830PipeSetBase(pScrn, pipe, pI830Pipe->x, pI830Pipe->y);
+    i830PipeSetBase(crtc, crtc->x, crtc->y);
     OUTREG(pipesrc_reg, pipesrc);
 
     /* Then, turn the pipe on first */
@@ -697,7 +721,7 @@ i830PipeSetMode(ScrnInfoPtr pScrn, Displ
 	OUTREG(dspcntr_reg, dspcntr);
     }
 
-    pI830Pipe->curMode = *pMode;
+    crtc->curMode = *pMode;
 
     ret = TRUE;
 done:
@@ -712,28 +736,33 @@ void
 i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
-    int output, pipe;
+    int o, pipe;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
 
-    for (output = 0; output < pI830->num_outputs; output++) {
-	if (!pI830->output[output].enabled)
-	    pI830->output[output].dpms(pScrn, &pI830->output[output], DPMSModeOff);
+    for (o = 0; o < pI830->num_outputs; o++) 
+    {
+	I830_xf86OutputPtr  output = pI830->xf86_output[o];
+	if (!output->crtc)
+	    (*output->funcs->dpms)(output, DPMSModeOff);
     }
 
     /* Now, any unused plane, pipe, and DPLL (FIXME: except for DVO, i915
      * internal TV) should have no outputs trying to pull data out of it, so
      * we're ready to turn those off.
      */
-    for (pipe = 0; pipe < pI830->num_pipes; pipe++) {
-	I830PipePtr pI830Pipe = &pI830->pipes[pipe];
+    for (pipe = 0; pipe < pI830->num_pipes; pipe++) 
+    {
+	I830_xf86CrtcPtr crtc = pI830->xf86_crtc[pipe];
+	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
+	int		    pipe = intel_crtc->pipe;
 	int	    dspcntr_reg = pipe == 0 ? DSPACNTR : DSPBCNTR;
 	int	    pipeconf_reg = pipe == 0 ? PIPEACONF : PIPEBCONF;
 	int	    dpll_reg = pipe == 0 ? DPLL_A : DPLL_B;
 	CARD32	    dspcntr, pipeconf, dpll;
 	char	    *pipe_name = pipe == 0 ? "A" : "B";
 
-	if (pI830Pipe->enabled)
+	if (crtc->enabled)
 	    continue;
 	
 	dspcntr = INREG(dspcntr_reg);
@@ -761,7 +790,7 @@ i830DisableUnusedFunctions(ScrnInfoPtr p
 	    OUTREG(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
 	}
 
-	memset(&pI830Pipe->curMode, 0, sizeof(pI830Pipe->curMode));
+	memset(&crtc->curMode, 0, sizeof(crtc->curMode));
     }
 }
 
@@ -780,9 +809,10 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     for (i = 0; i < pI830->num_pipes; i++)
     {
-	ok = i830PipeSetMode(pScrn, 
-			     i830PipeFindClosestMode(pScrn, i, pMode), 
-			     i, TRUE);
+	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[i];
+	ok = i830PipeSetMode(crtc,
+			     i830PipeFindClosestMode(crtc, pMode), 
+			     TRUE);
 	if (!ok)
 	    goto done;
     }
@@ -802,7 +832,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	/* If we might have enabled/disabled some pipes, we need to reset
 	 * cloning mode support.
 	 */
-	if (pI830->pipes[0].enabled && pI830->pipes[1].enabled)
+	if (pI830->num_pipes >= 2 && 
+	    pI830->xf86_crtc[0]->enabled &&
+	    pI830->xf86_crtc[1]->enabled)
 	    pI830->Clone = TRUE;
 	else
 	    pI830->Clone = FALSE;
@@ -834,6 +866,7 @@ i830DescribeOutputConfiguration(ScrnInfo
     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output configuration:\n");
 
     for (i = 0; i < pI830->num_pipes; i++) {
+	I830_xf86CrtcPtr crtc = pI830->xf86_crtc[i];
 	CARD32 dspcntr = INREG(DSPACNTR + (DSPBCNTR - DSPACNTR) * i);
 	CARD32 pipeconf = INREG(PIPEACONF + (PIPEBCONF - PIPEACONF) * i);
 	Bool hw_plane_enable = (dspcntr & DISPLAY_PLANE_ENABLE) != 0;
@@ -841,53 +874,37 @@ i830DescribeOutputConfiguration(ScrnInfo
 
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Pipe %c is %s\n",
-		   'A' + i, pI830->pipes[i].enabled ? "on" : "off");
+		   'A' + i, crtc->enabled ? "on" : "off");
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		   "  Display plane %c is now %s and connected to pipe %c.\n",
 		   'A' + i,
-		   pI830->pipes[i].enabled ? "enabled" : "disabled",
+		   crtc->enabled ? "enabled" : "disabled",
 		   dspcntr & DISPPLANE_SEL_PIPE_MASK ? 'B' : 'A');
-	if (hw_pipe_enable != pI830->pipes[i].enabled) {
+	if (hw_pipe_enable != crtc->enabled) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "  Hardware claims pipe %c is %s while software "
 		       "believes it is %s\n",
 		       'A' + i, hw_pipe_enable ? "on" : "off",
-		       pI830->pipes[i].enabled ? "on" : "off");
+		       crtc->enabled ? "on" : "off");
 	}
-	if (hw_plane_enable != pI830->pipes[i].enabled) {
+	if (hw_plane_enable != crtc->enabled) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		       "  Hardware claims plane %c is %s while software "
 		       "believes it is %s\n",
 		       'A' + i, hw_plane_enable ? "on" : "off",
-		       pI830->pipes[i].enabled ? "on" : "off");
+		       crtc->enabled ? "on" : "off");
 	}
     }
 
     for (i = 0; i < pI830->num_outputs; i++) {
-	const char *name = NULL;
-
-	switch (pI830->output[i].type) {
-	case I830_OUTPUT_ANALOG:
-	    name = "CRT";
-	    break;
-	case I830_OUTPUT_LVDS:
-	    name = "LVDS";
-	    break;
-	case I830_OUTPUT_SDVO:
-	    name = "SDVO";
-	    break;
-	case I830_OUTPUT_DVO:
-	    name = "DVO";
-	    break;
-	case I830_OUTPUT_TVOUT:
-	    name = "TV";
-	    break;
-	}
-
+	I830_xf86OutputPtr	output = pI830->xf86_output[i];
+	I830_xf86CrtcPtr	crtc = output->crtc;
+	I830CrtcPrivatePtr	intel_crtc = crtc ? crtc->driver_private : NULL;
+	
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "  Output %s is %sabled and connected to pipe %c\n",
-		   name, pI830->output[i].enabled ? "en" : "dis",
-		   pI830->output[i].pipe == 0 ? 'A' : 'B');
+		   "  Output %s is connected to pipe %s\n",
+		   output->name, intel_crtc == NULL ? "none" :
+		   (intel_crtc->pipe == 0 ? "A" : "B"));
     }
 }
 
@@ -902,15 +919,19 @@ i830DescribeOutputConfiguration(ScrnInfo
  * configured for it.  In the future, it could choose to temporarily disable
  * some outputs to free up a pipe for its use.
  *
- * \return monitor number, or -1 if no pipes are available.
+ * \return crtc, or NULL if no pipes are available.
  */
-int
-i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+    
+I830_xf86CrtcPtr
+i830GetLoadDetectPipe(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    int i;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I830_xf86CrtcPtr	    crtc;
+    int			    i;
     /* VESA 640x480x72Hz mode to set on the pipe */
-    DisplayModeRec mode = {
+    static DisplayModeRec   mode = {
 	NULL, NULL, "640x480", MODE_OK, M_T_DEFAULT,
 	31500,
 	640, 664, 704, 832, 0,
@@ -922,54 +943,37 @@ i830GetLoadDetectPipe(ScrnInfoPtr pScrn,
 	FALSE, FALSE, 0, NULL, 0, 0.0, 0.0
     };
 
-    /* If the output is not marked disabled, check if it's already assigned
-     * to an active pipe, and is alone on that pipe.  If so, we're done.
-     */
-    if (output->enabled) {
-	int pipeconf_reg = (output->pipe == 0) ? PIPEACONF : PIPEBCONF;
-
-	if (INREG(pipeconf_reg) & PIPEACONF_ENABLE) {
-	    /* Actually, maybe we don't need to be all alone on the pipe.
-	     * The worst that should happen is false positives.  Need to test,
-	     * but actually fixing this during server startup is messy.
-	     */
-#if 0
-	    for (i = 0; i < pI830->num_outputs; i++) {
-		if (&pI830->output[i] != output &&
-		    pI830->output[i].pipe == output->pipe)
-		{
-		    return -1;
-		}
-	    }
-#endif
-	    return output->pipe;
-	}
-    }
+    if (output->crtc) 
+	return output->crtc;
 
     for (i = 0; i < pI830->num_pipes; i++)
-	if (!i830PipeInUse(pScrn, i))
+	if (!i830PipeInUse(pI830->xf86_crtc[i]))
 	    break;
 
     if (i == pI830->num_pipes)
-	return -1;
+	return NULL;
 
-    output->load_detect_temp = TRUE;
-    output->pipe = i;
-    output->enabled = TRUE;
+    crtc = pI830->xf86_crtc[i];
 
-    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
+    output->crtc = crtc;
+    intel_output->load_detect_temp = TRUE;
 
-    i830PipeSetMode(pScrn, &mode, i, FALSE);
+    I830xf86SetModeCrtc(&mode, INTERLACE_HALVE_V);
+    i830PipeSetMode(crtc, &mode, FALSE);
 
-    return i;
+    return crtc;
 }
 
 void
-i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output)
 {
-    if (output->load_detect_temp) {
-	output->enabled = FALSE;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    
+    if (intel_output->load_detect_temp) 
+    {
+	output->crtc = NULL;
+	intel_output->load_detect_temp = FALSE;
 	i830DisableUnusedFunctions(pScrn);
-	output->load_detect_temp = FALSE;
     }
 }
diff --git a/src/i830_display.h b/src/i830_display.h
index 361a3c6..4409728 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -27,14 +27,14 @@
 
 /* i830_display.c */
 DisplayModePtr
-i830PipeFindClosestMode(ScrnInfoPtr pScrn, int pipe, DisplayModePtr pMode);
-Bool i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe,
+i830PipeFindClosestMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode);
+Bool i830PipeSetMode(I830_xf86CrtcPtr crtc, DisplayModePtr pMode, 
 		     Bool plane_enable);
 void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
 Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
-void i830PipeSetBase(ScrnInfoPtr pScrn, int pipe, int x, int y);
+void i830PipeSetBase(I830_xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
-int i830GetLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
-void i830ReleaseLoadDetectPipe(ScrnInfoPtr pScrn, I830OutputPtr output);
-Bool i830PipeInUse(ScrnInfoPtr pScrn, int pipe);
+I830_xf86CrtcPtr i830GetLoadDetectPipe(I830_xf86OutputPtr output);
+void i830ReleaseLoadDetectPipe(I830_xf86OutputPtr output);
+Bool i830PipeInUse(I830_xf86CrtcPtr crtc);
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 3b02918..af34afc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1513,13 +1513,9 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
 
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
-	    if (pI830->pipes[1].enabled) {
-		if (pI830->drmMinor >= 6)
-		    pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
-		else
-		    pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+	    if (pI830->num_pipes > 1 && pI830->xf86_crtc[1]->enabled)
 		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
-	    } else
+	    else
 		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
 	} else {
 	    pipe.pipe = 0;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0ae1ee6..d4d5fbc 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -548,8 +548,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
    DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors);
    pI830 = I830PTR(pScrn);
 
-   for(p=0; p < pI830->num_pipes; p++) {
-      I830PipePtr pI830Pipe = &pI830->pipes[p];
+   for(p=0; p < pI830->num_pipes; p++) 
+   {
+      I830_xf86CrtcPtr	   crtc = pI830->xf86_crtc[p];
+      I830CrtcPrivatePtr   intel_crtc = crtc->driver_private;
 
       if (p == 0) {
          palreg = PALETTE_A;
@@ -563,10 +565,10 @@ I830LoadPalette(ScrnInfoPtr pScrn, int n
 	 dspsurf = DSPBSURF;
       }
 
-      if (pI830Pipe->enabled == 0)
+      if (crtc->enabled == 0)
 	 continue;  
 
-      pI830Pipe->gammaEnabled = 1;
+      intel_crtc->gammaEnabled = 1;
       
       /* To ensure gamma is enabled we need to turn off and on the plane */
       temp = INREG(dspreg);
@@ -1261,33 +1263,44 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Perform the pipe assignment of outputs. This is a kludge until
     * we have better configuration support in the generic RandR code
     */
-   for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].enabled = FALSE;
+   for (i = 0; i < pI830->num_outputs; i++) 
+   {
+      I830_xf86OutputPtr      output = pI830->xf86_output[i];
+      I830OutputPrivatePtr    intel_output = output->driver_private;
+      I830_xf86CrtcPtr	      crtc;
+      int		      p;
 
-      switch (pI830->output[i].type) {
+      output->crtc = NULL;
+
+      switch (intel_output->type) {
       case I830_OUTPUT_LVDS:
 	 /* LVDS must live on pipe B for two-pipe devices */
-	 pI830->output[i].pipe = pI830->num_pipes - 1;
-	 pI830->output[i].enabled = TRUE;
+	 crtc = pI830->xf86_crtc[pI830->num_pipes - 1];
+	 if (!i830PipeInUse (crtc))
+	    output->crtc = crtc;
 	 break;
       case I830_OUTPUT_ANALOG:
       case I830_OUTPUT_DVO:
       case I830_OUTPUT_SDVO:
-	 if (pI830->output[i].detect(pScrn, &pI830->output[i]) !=
-	     OUTPUT_STATUS_DISCONNECTED) {
-	    if (!i830PipeInUse(pScrn, 0)) {
-	       pI830->output[i].pipe = 0;
-	       pI830->output[i].enabled = TRUE;
-	    } else if (!i830PipeInUse(pScrn, 1)) {
-	       pI830->output[i].pipe = 1;
-	       pI830->output[i].enabled = TRUE;
+	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED) 
+	 {
+	    for (p = 0; p < pI830->num_pipes; p++)
+	    {
+	       crtc = pI830->xf86_crtc[p];
+	       if (!i830PipeInUse(crtc))
+	       {
+		  output->crtc = crtc;
+		  break;
+	       }
 	    }
 	 }
 	 break;
       case I830_OUTPUT_TVOUT:
-         if (!i830PipeInUse(pScrn, 0)) {
-	    pI830->output[i].pipe = 0;
-	    pI830->output[i].enabled = TRUE;
+	 crtc = pI830->xf86_crtc[0];
+	 if ((*output->funcs->detect)(output) != OUTPUT_STATUS_DISCONNECTED &&
+	     !i830PipeInUse(crtc))
+	 {
+	    output->crtc = crtc;
 	 }
 	 break;
       default:
@@ -1296,10 +1309,12 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
       }
    }
 
-   for (i = 0; i < pI830->num_pipes; i++) {
-      pI830->pipes[i].enabled = i830PipeInUse(pScrn, i);
+   for (i = 0; i < pI830->num_pipes; i++) 
+   {
+      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+      crtc->enabled = i830PipeInUse(crtc);
    }
-
+   
    pI830->rotation = RR_Rotate_0;
    if ((s = xf86GetOptValString(pI830->Options, OPTION_ROTATE))) {
       pI830->InitialRotation = 0;
@@ -2108,8 +2123,9 @@ SaveHWState(ScrnInfoPtr pScrn)
    pI830->savePFIT_CONTROL = INREG(PFIT_CONTROL);
 
    for (i = 0; i < pI830->num_outputs; i++) {
-      if (pI830->output[i].save != NULL)
-	 pI830->output[i].save(pScrn, &pI830->output[i]);
+      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+      if (output->funcs->save)
+	 (*output->funcs->save) (output);
    }
 
    vgaHWUnlock(hwp);
@@ -2149,7 +2165,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
 
    /* Disable outputs if necessary */
    for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].pre_set_mode(pScrn, &pI830->output[i], NULL);
+      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+      (*output->funcs->pre_set_mode) (output, NULL);
    }
 
    i830WaitForVblank(pScrn);
@@ -2199,7 +2216,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
    OUTREG(PFIT_CONTROL, pI830->savePFIT_CONTROL);
 
    for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].restore(pScrn, &pI830->output[i]);
+      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+      (*output->funcs->restore) (output);
    }
 
    if (IS_I965G(pI830)) {
@@ -3235,8 +3253,11 @@ i830AdjustFrame(int scrnIndex, int x, in
    }
 
    for (i = 0; i < pI830->num_pipes; i++)
-      if (pI830->pipes[i].enabled)
-	 i830PipeSetBase(pScrn, i, x, y);
+   {
+      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+      if (crtc->enabled)
+	 i830PipeSetBase(crtc, x, y);
+   }
 }
 
 static void
@@ -3349,17 +3370,17 @@ I830EnterVT(int scrnIndex, int flags)
 
    for (i = 0; i < pI830->num_pipes; i++)
    {
-      I830PipePtr pipe = &pI830->pipes[i];
+      I830_xf86CrtcPtr	crtc = pI830->xf86_crtc[i];
+
       /* Mark that we'll need to re-set the mode for sure */
-      memset(&pipe->curMode, 0, sizeof(pipe->curMode));
-      if (!pipe->desiredMode.CrtcHDisplay)
-      {
-	 pipe->desiredMode = *i830PipeFindClosestMode (pScrn, i,
-						       pScrn->currentMode);
-      }
-      if (!i830PipeSetMode (pScrn, &pipe->desiredMode, i, TRUE))
+      memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+      if (!crtc->desiredMode.CrtcHDisplay)
+	 crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
+      
+      if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE))
 	 return FALSE;
-      i830PipeSetBase(pScrn, i, pipe->x, pipe->y);
+      
+      i830PipeSetBase(crtc, crtc->x, crtc->y);
    }
 
    i830DisableUnusedFunctions(pScrn);
@@ -3527,7 +3548,7 @@ I830SaveScreen(ScreenPtr pScreen, int mo
 	    base = DSPBADDR;
 	    surf = DSPBSURF;
         }
-        if (pI830->pipes[i].enabled) {
+        if (pI830->xf86_crtc[i]->enabled) {
 	   temp = INREG(ctrl);
 	   if (on)
 	      temp |= DISPLAY_PLANE_ENABLE;
@@ -3565,10 +3586,15 @@ I830DisplayPowerManagementSet(ScrnInfoPt
    CARD32 temp, ctrl, base;
 
    for (i = 0; i < pI830->num_outputs; i++) {
-      pI830->output[i].dpms(pScrn, &pI830->output[i], PowerManagementMode);
+      I830_xf86OutputPtr   output = pI830->xf86_output[i];
+      
+      (*output->funcs->dpms) (output, PowerManagementMode);
    }
 
-   for (i = 0; i < pI830->num_pipes; i++) {
+   for (i = 0; i < pI830->num_pipes; i++) 
+   {
+      I830_xf86CrtcPtr	   crtc = pI830->xf86_crtc[i];
+      
       if (i == 0) {
          ctrl = DSPACNTR;
          base = DSPABASE;
@@ -3576,7 +3602,8 @@ I830DisplayPowerManagementSet(ScrnInfoPt
          ctrl = DSPBCNTR;
          base = DSPBADDR;
       }
-      if (pI830->pipes[i].enabled) {
+      /* XXX pipe disable too? */
+      if (crtc->enabled) {
 	   temp = INREG(ctrl);
 	   if (PowerManagementMode == DPMSModeOn)
 	      temp |= DISPLAY_PLANE_ENABLE;
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 31fb76b..b292190 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -57,18 +57,21 @@ struct _I830DVODriver i830_dvo_drivers[]
 #define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
 
 static void
-i830_dvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+i830_dvo_dpms(I830_xf86OutputPtr output, int mode)
 {
+    I830OutputPrivatePtr    intel_output = output->driver_private;
     if (mode == DPMSModeOn)
-	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, TRUE);
+	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, TRUE);
     else
-	output->i2c_drv->vid_rec->Power(output->i2c_drv->dev_priv, FALSE);
+	(*intel_output->i2c_drv->vid_rec->Power)(intel_output->i2c_drv->dev_priv, FALSE);
 }
 
 static void
-i830_dvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_dvo_save(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
 
     /* Each output should probably just save the registers it touches, but for
      * now, use more overkill.
@@ -77,61 +80,68 @@ i830_dvo_save(ScrnInfoPtr pScrn, I830Out
     pI830->saveDVOB = INREG(DVOB);
     pI830->saveDVOC = INREG(DVOC);
 
-    output->i2c_drv->vid_rec->SaveRegs(output->i2c_drv->dev_priv);
+    (*intel_output->i2c_drv->vid_rec->SaveRegs)(intel_output->i2c_drv->dev_priv);
 }
 
 static void
-i830_dvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_dvo_restore(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
 
     OUTREG(DVOA, pI830->saveDVOA);
     OUTREG(DVOB, pI830->saveDVOB);
     OUTREG(DVOC, pI830->saveDVOC);
 
-    output->i2c_drv->vid_rec->RestoreRegs(output->i2c_drv->dev_priv);
+    (*intel_output->i2c_drv->vid_rec->RestoreRegs)(intel_output->i2c_drv->dev_priv);
 }
 
 static int
-i830_dvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
-		    DisplayModePtr pMode)
+i830_dvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    
     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))
+    if ((*intel_output->i2c_drv->vid_rec->ModeValid)(intel_output->i2c_drv->dev_priv, pMode))
 	return MODE_OK;
     else
 	return MODE_BAD;
 }
 
 static void
-i830_dvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		      DisplayModePtr pMode)
+i830_dvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
 
-    output->i2c_drv->vid_rec->Mode(output->i2c_drv->dev_priv, pMode);
+    (*intel_output->i2c_drv->vid_rec->Mode)(intel_output->i2c_drv->dev_priv, pMode);
 
     OUTREG(DVOC, INREG(DVOC) & ~DVO_ENABLE);
 }
 
 static void
-i830_dvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		       DisplayModePtr pMode)
+i830_dvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 dvo;
-    int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830_xf86CrtcPtr	    crtc = output->crtc;
+    I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
+    int			    pipe = intel_crtc->pipe;
+    CARD32		    dvo;
+    int			    dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 
     /* Save the data order, since I don't know what it should be set to. */
     dvo = INREG(DVOC) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
     dvo |= DVO_ENABLE;
     dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE | DVO_BLANK_ACTIVE_HIGH;
 
-    if (output->pipe == 1)
+    if (pipe == 1)
 	dvo |= DVO_PIPE_B_SELECT;
 
     if (pMode->Flags & V_PHSYNC)
@@ -155,7 +165,7 @@ i830_dvo_post_set_mode(ScrnInfoPtr pScrn
  * Unimplemented.
  */
 static enum detect_status
-i830_dvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_dvo_detect(I830_xf86OutputPtr output)
 {
     return OUTPUT_STATUS_UNKNOWN;
 }
@@ -191,46 +201,81 @@ I830I2CDetectDVOControllers(ScrnInfoPtr 
     return FALSE;
 }
 
+static void
+i830_dvo_destroy (I830_xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+
+    if (intel_output)
+    {
+	if (intel_output->pI2CBus)
+	    xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
+	if (intel_output->pDDCBus)
+	    xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
+	/* XXX sub module cleanup? */
+	xfree (intel_output);
+    }
+}
+
+static const I830_xf86OutputFuncsRec i830_dvo_output_funcs = {
+    .dpms = i830_dvo_dpms,
+    .save = i830_dvo_save,
+    .restore = i830_dvo_restore,
+    .mode_valid = i830_dvo_mode_valid,
+    .pre_set_mode = i830_dvo_pre_set_mode,
+    .post_set_mode = i830_dvo_post_set_mode,
+    .detect = i830_dvo_detect,
+    .get_modes = i830_ddc_get_modes,
+    .destroy = i830_dvo_destroy
+};
+
 void
 i830_dvo_init(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool ret;
-    int i = pI830->num_outputs;
-
-    pI830->output[i].type = I830_OUTPUT_DVO;
-    pI830->output[i].dpms = i830_dvo_dpms;
-    pI830->output[i].save = i830_dvo_save;
-    pI830->output[i].restore = i830_dvo_restore;
-    pI830->output[i].mode_valid  = i830_dvo_mode_valid;
-    pI830->output[i].pre_set_mode  = i830_dvo_pre_set_mode;
-    pI830->output[i].post_set_mode  = i830_dvo_post_set_mode;
-    pI830->output[i].detect  = i830_dvo_detect;
-    pI830->output[i].get_modes = i830_ddc_get_modes;
-
+    I830_xf86OutputPtr	    output;
+    I830OutputPrivatePtr    intel_output;
+    int			    ret;
+
+    output = i830xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
+				   "ADD AGP card");
+    if (!output)
+	return;
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+    if (!intel_output)
+    {
+	i830xf86OutputDestroy (output);
+	return;
+    }
+    intel_output->type = I830_OUTPUT_DVO;
+    output->driver_private = intel_output;
+    
     /* Set up the I2C and DDC buses */
-    ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
+    ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
     if (!ret)
+    {
+	i830xf86OutputDestroy (output);
 	return;
+    }
 
-    ret = I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
-    if (!ret) {
-	xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
+    ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
+    if (!ret)
+    {
+	i830xf86OutputDestroy (output);
 	return;
     }
 
     /* Now, try to find a controller */
-    ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
-				      &pI830->output[i].i2c_drv);
-    if (ret) {
+    ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus,
+				      &intel_output->i2c_drv);
+    if (ret)
+    {
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
-		   pI830->output[i].i2c_drv->modulename,
-		   pI830->output[i].pI2CBus->DriverPrivate.uval);
-    } else {
-	xf86DestroyI2CBusRec(pI830->output[i].pI2CBus, TRUE, TRUE);
-	xf86DestroyI2CBusRec(pI830->output[i].pDDCBus, TRUE, TRUE);
+		   intel_output->i2c_drv->modulename,
+		   intel_output->pI2CBus->DriverPrivate.uval);
+    }
+    else
+    {
+	i830xf86OutputDestroy (output);
 	return;
     }
-
-    pI830->num_outputs++;
 }
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index ea45420..e72b9e8 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -73,8 +73,10 @@ i830SetLVDSPanelPower(ScrnInfoPtr pScrn,
 }
 
 static void
-i830_lvds_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+i830_lvds_dpms (I830_xf86OutputPtr output, int mode)
 {
+    ScrnInfoPtr	pScrn = output->scrn;
+
     if (mode == DPMSModeOn)
 	i830SetLVDSPanelPower(pScrn, TRUE);
     else
@@ -82,9 +84,10 @@ i830_lvds_dpms(ScrnInfoPtr pScrn, I830Ou
 }
 
 static void
-i830_lvds_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_lvds_save (I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
 
     pI830->savePP_ON = INREG(LVDSPP_ON);
     pI830->savePP_OFF = INREG(LVDSPP_OFF);
@@ -106,9 +109,10 @@ i830_lvds_save(ScrnInfoPtr pScrn, I830Ou
 }
 
 static void
-i830_lvds_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_lvds_restore(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
 
     OUTREG(BLC_PWM_CTL, pI830->saveBLC_PWM_CTL);
     OUTREG(LVDSPP_ON, pI830->savePP_ON);
@@ -123,16 +127,15 @@ i830_lvds_restore(ScrnInfoPtr pScrn, I83
 }
 
 static int
-i830_lvds_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
-		    DisplayModePtr pMode)
+i830_lvds_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
    return MODE_OK;
 }
 
 static void
-i830_lvds_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		       DisplayModePtr pMode)
+i830_lvds_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
+    ScrnInfoPtr	pScrn = output->scrn;
     /* Always make sure the LVDS is off before we play with DPLLs and pipe
      * configuration.  We can skip this in some cases (for example, going
      * between hi-res modes with automatic panel scaling are fine), but be
@@ -142,11 +145,11 @@ i830_lvds_pre_set_mode(ScrnInfoPtr pScrn
 }
 
 static void
-i830_lvds_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-			DisplayModePtr pMode)
+i830_lvds_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    CARD32  pfit_control;
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(pScrn);
+    CARD32	pfit_control;
 
     /* Enable automatic panel scaling so that non-native modes fill the
      * screen.  Should be enabled before the pipe is enabled, according to
@@ -182,7 +185,7 @@ i830_lvds_post_set_mode(ScrnInfoPtr pScr
  * been set up if the LVDS was actually connected anyway.
  */
 static enum detect_status
-i830_lvds_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_lvds_detect(I830_xf86OutputPtr output)
 {
     return OUTPUT_STATUS_CONNECTED;
 }
@@ -191,13 +194,14 @@ i830_lvds_detect(ScrnInfoPtr pScrn, I830
  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
  */
 static DisplayModePtr
-i830_lvds_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_lvds_get_modes(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    DisplayModePtr modes, new;
-    char stmp[32];
+    ScrnInfoPtr	    pScrn = output->scrn;
+    I830Ptr	    pI830 = I830PTR(pScrn);
+    DisplayModePtr  modes, new;
+    char	    stmp[32];
 
-    modes = i830_ddc_get_modes(pScrn, output);
+    modes = i830_ddc_get_modes(output);
     if (modes != NULL)
 	return modes;
 
@@ -220,10 +224,34 @@ i830_lvds_get_modes(ScrnInfoPtr pScrn, I
     return new;
 }
 
+static void
+i830_lvds_destroy (I830_xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+
+    if (intel_output)
+	xfree (intel_output);
+}
+
+static const I830_xf86OutputFuncsRec i830_lvds_output_funcs = {
+    .dpms = i830_lvds_dpms,
+    .save = i830_lvds_save,
+    .restore = i830_lvds_restore,
+    .mode_valid = i830_lvds_mode_valid,
+    .pre_set_mode = i830_lvds_pre_set_mode,
+    .post_set_mode = i830_lvds_post_set_mode,
+    .detect = i830_lvds_detect,
+    .get_modes = i830_lvds_get_modes,
+    .destroy = i830_lvds_destroy
+};
+
 void
 i830_lvds_init(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830_xf86OutputPtr	    output;
+    I830OutputPrivatePtr    intel_output;
+
 
     /* Get the LVDS fixed mode out of the BIOS.  We should support LVDS with
      * the BIOS being unavailable or broken, but lack the configuration options
@@ -258,21 +286,20 @@ i830_lvds_init(ScrnInfoPtr pScrn)
 	}
    }
 
-    pI830->output[pI830->num_outputs].type = I830_OUTPUT_LVDS;
-    pI830->output[pI830->num_outputs].dpms = i830_lvds_dpms;
-    pI830->output[pI830->num_outputs].save = i830_lvds_save;
-    pI830->output[pI830->num_outputs].restore = i830_lvds_restore;
-    pI830->output[pI830->num_outputs].mode_valid = i830_lvds_mode_valid;
-    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;
-    pI830->output[pI830->num_outputs].get_modes = i830_lvds_get_modes;
+    output = i830xf86OutputCreate (pScrn, &i830_lvds_output_funcs, "Built-in LCD panel");
+    if (!output)
+	return;
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec), 1);
+    if (!intel_output)
+    {
+	i830xf86OutputDestroy (output);
+	return;
+    }
+    intel_output->type = I830_OUTPUT_LVDS;
+    output->driver_private = intel_output;
 
     /* Set up the LVDS DDC channel.  Most panels won't support it, but it can
      * be useful if available.
      */
-    I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
-		GPIOC, "LVDSDDC_C");
-
-    pI830->num_outputs++;
+    I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOC, "LVDSDDC_C");
 }
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 7fdd40e..7d4bcba 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -427,47 +427,44 @@ i830_reprobe_output_modes(ScrnInfoPtr pS
     int i;
 
     /* Re-probe the list of modes for each output. */
-    for (i = 0; i < pI830->num_outputs; i++) {
+    for (i = 0; i < pI830->num_outputs; i++) 
+    {
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
 	DisplayModePtr mode;
 
-	while (pI830->output[i].probed_modes != NULL) {
-	    xf86DeleteMode(&pI830->output[i].probed_modes,
-			   pI830->output[i].probed_modes);
-	}
+	while (output->probed_modes != NULL)
+	    xf86DeleteMode(&output->probed_modes, output->probed_modes);
 
-	pI830->output[i].probed_modes =
-	    pI830->output[i].get_modes(pScrn, &pI830->output[i]);
+	output->probed_modes = (*output->funcs->get_modes) (output);
 
 	/* Set the DDC properties to whatever first output has DDC information.
 	 */
-	if (pI830->output[i].MonInfo != NULL && !properties_set) {
-	    xf86SetDDCproperties(pScrn, pI830->output[i].MonInfo);
+	if (output->MonInfo != NULL && !properties_set) {
+	    xf86SetDDCproperties(pScrn, output->MonInfo);
 	    properties_set = TRUE;
 	}
 
-	if (pI830->output[i].probed_modes != NULL) {
+	if (output->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);
+	    i830xf86ValidateModesUserConfig(pScrn, output->probed_modes);
+	    i830xf86PruneInvalidModes(pScrn, &output->probed_modes, FALSE);
 	}
 
 #ifdef DEBUG_REPROBE
-	if (pI830->output[i].probed_modes != NULL) {
+	if (output->probed_modes != NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "Printing probed modes for output %s\n",
-		       i830_output_type_names[pI830->output[i].type]);
+		       output->name);
 	} else {
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "No remaining probed modes for output %s\n",
-		       i830_output_type_names[pI830->output[i].type]);
+		       output->name);
 	}
 #endif
-	for (mode = pI830->output[i].probed_modes; mode != NULL;
-	     mode = mode->next)
+	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.
@@ -515,9 +512,9 @@ i830_set_xf86_modes_from_outputs(ScrnInf
      * care about enough to make some sort of unioned list.
      */
     for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].probed_modes != NULL) {
-	    pScrn->modes =
-		i830xf86DuplicateModes(pScrn, pI830->output[i].probed_modes);
+	I830_xf86OutputPtr output = pI830->xf86_output[i];
+	if (output->probed_modes != NULL) {
+	    pScrn->modes = i830xf86DuplicateModes(pScrn, output->probed_modes);
 	    break;
 	}
     }
@@ -568,10 +565,10 @@ i830_set_default_screen_size(ScrnInfoPtr
      * set for the currently-connected outputs.
      */
     for (i = 0; i < pI830->num_outputs; i++) {
+	I830_xf86OutputPtr  output = pI830->xf86_output[i];
 	DisplayModePtr mode;
 
-	for (mode = pI830->output[i].probed_modes; mode != NULL;
-	     mode = mode->next)
+	for (mode = output->probed_modes; mode != NULL; mode = mode->next)
 	{
 	    if (mode->HDisplay > maxX)
 		maxX = mode->HDisplay;
@@ -618,8 +615,7 @@ I830ValidateXF86ModeList(ScrnInfoPtr pSc
 #define EDID_ATOM_NAME		"EDID_DATA"
 
 static void
-i830_ddc_set_edid_property(ScrnInfoPtr pScrn, I830OutputPtr output,
-			   void *data, int data_len)
+i830_ddc_set_edid_property(I830_xf86OutputPtr output, void *data, int data_len)
 {
     Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME), TRUE);
 
@@ -640,16 +636,18 @@ i830_ddc_set_edid_property(ScrnInfoPtr p
  * Generic get_modes function using DDC, used by many outputs.
  */
 DisplayModePtr
-i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_ddc_get_modes(I830_xf86OutputPtr output)
 {
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
     xf86MonPtr ddc_mon;
     DisplayModePtr ddc_modes, mode;
     int i;
 
-    ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
+    ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, intel_output->pDDCBus);
     if (ddc_mon == NULL) {
 #ifdef RANDR_12_INTERFACE
-	i830_ddc_set_edid_property(pScrn, output, NULL, 0);
+	i830_ddc_set_edid_property(output, NULL, 0);
 #endif
 	return NULL;
     }
@@ -660,24 +658,23 @@ i830_ddc_get_modes(ScrnInfoPtr pScrn, I8
 
 #ifdef RANDR_12_INTERFACE
     if (output->MonInfo->ver.version == 1) {
-	i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 128);
+	i830_ddc_set_edid_property(output, ddc_mon->rawData, 128);
     } else if (output->MonInfo->ver.version == 2) {
-	i830_ddc_set_edid_property(pScrn, output, ddc_mon->rawData, 256);
+	i830_ddc_set_edid_property(output, ddc_mon->rawData, 256);
     } else {
-	i830_ddc_set_edid_property(pScrn, output, NULL, 0);
+	i830_ddc_set_edid_property(output, NULL, 0);
     }
 #endif
 
     /* Debug info for now, at least */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n",
-	       i830_output_type_names[output->type]);
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
     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);
+	int status = (*output->funcs->mode_valid)(output, mode);
 
 	if (status != MODE_OK)
 	    mode->status = status;
diff --git a/src/i830_randr.c b/src/i830_randr.c
index a530ffb..d6a3131 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -52,9 +52,6 @@ typedef struct _i830RandRInfo {
     int				    maxY;
     Rotation			    rotation; /* current mode */
     Rotation                        supported_rotations; /* driver supported */
-#ifdef RANDR_12_INTERFACE
-    DisplayModePtr  		    modes[MAX_DISPLAY_PIPES];
-#endif
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
 
 #ifdef RANDR_12_INTERFACE
@@ -472,151 +469,127 @@ I830RandRScreenSetSize (ScreenPtr	pScree
 }
 
 static Bool
-I830RandRCrtcNotify (RRCrtcPtr	crtc)
+I830RandRCrtcNotify (RRCrtcPtr	randr_crtc)
 {
-    ScreenPtr		pScreen = crtc->pScreen;
+    ScreenPtr		pScreen = randr_crtc->pScreen;
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
-    RRModePtr		mode = NULL;
+    RRModePtr		randr_mode = NULL;
     int			x;
     int			y;
     Rotation		rotation;
     int			numOutputs;
-    RROutputPtr		outputs[MAX_OUTPUTS];
-    struct _I830OutputRec   *output;
-    RROutputPtr		rrout;
-    int			pipe = (int) crtc->devPrivate;
-    I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
+    RROutputPtr		randr_outputs[MAX_OUTPUTS];
+    RROutputPtr		randr_output;
+    I830_xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    I830_xf86OutputPtr	output;
     int			i, j;
-    DisplayModePtr	pipeMode = &pI830Pipe->curMode;
+    DisplayModePtr	curMode = &crtc->curMode;
 
-    x = pI830Pipe->x;
-    y = pI830Pipe->y;
+    x = crtc->x;
+    y = crtc->y;
     rotation = RR_Rotate_0;
     numOutputs = 0;
-    mode = NULL;
+    randr_mode = NULL;
     for (i = 0; i < pI830->num_outputs; i++)
     {
-	output = &pI830->output[i];
-	if (output->enabled && output->pipe == pipe)
+	output = pI830->xf86_output[i];
+	if (output->crtc == crtc)
 	{
-	    rrout = output->randr_output;
-	    outputs[numOutputs++] = rrout;
+	    randr_output = output->randr_output;
+	    randr_outputs[numOutputs++] = randr_output;
 	    /*
 	     * We make copies of modes, so pointer equality 
 	     * isn't sufficient
 	     */
-	    for (j = 0; j < rrout->numModes; j++)
+	    for (j = 0; j < randr_output->numModes; j++)
 	    {
-		DisplayModePtr	outMode = rrout->modes[j]->devPrivate;
-		if (I830ModesEqual(pipeMode, outMode))
+		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
+		if (I830ModesEqual(curMode, outMode))
 		{
-		    mode = rrout->modes[j];
+		    randr_mode = randr_output->modes[j];
 		    break;
 		}
 	    }
 	}
     }
-    return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+    return RRCrtcNotify (randr_crtc, randr_mode, x, y,
+			 rotation, numOutputs, randr_outputs);
 }
 
 static Bool
 I830RandRCrtcSet (ScreenPtr	pScreen,
-		  RRCrtcPtr	crtc,
-		  RRModePtr	mode,
+		  RRCrtcPtr	randr_crtc,
+		  RRModePtr	randr_mode,
 		  int		x,
 		  int		y,
 		  Rotation	rotation,
 		  int		num_randr_outputs,
 		  RROutputPtr	*randr_outputs)
 {
-    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     I830Ptr		pI830 = I830PTR(pScrn);
-    int			pipe = (int) (crtc->devPrivate);
-    I830PipePtr		pI830Pipe = &pI830->pipes[pipe];
-    DisplayModePtr	display_mode = mode ? mode->devPrivate : NULL;
+    I830_xf86CrtcPtr	crtc = randr_crtc->devPrivate;
+    DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
-    Bool		disable = FALSE;
     int			o, ro;
-    struct {
-	int pipe;
-	int enabled;
-    }			save_output[MAX_OUTPUTS];
-    Bool		save_enabled = pI830Pipe->enabled;
+    I830_xf86CrtcPtr	save_crtcs[MAX_OUTPUTS];
+    Bool		save_enabled = crtc->enabled;
 
-    if (display_mode != randrp->modes[pipe])
-    {
+    if (!I830ModesEqual (&crtc->curMode, mode))
 	changed = TRUE;
-	if (!display_mode)
-	    disable = TRUE;
-    }
     
     for (o = 0; o < pI830->num_outputs; o++) 
     {
-	I830OutputPtr	output = &pI830->output[o];
-	RROutputPtr	randr_output = NULL;
+	I830_xf86OutputPtr  output = pI830->xf86_output[o];
+	I830_xf86CrtcPtr    new_crtc;
+
+	save_crtcs[o] = output->crtc;
 	
-	save_output[o].enabled = output->enabled;
-	save_output[o].pipe = output->pipe;
+	if (output->crtc == crtc)
+	    new_crtc = NULL;
+	else
+	    new_crtc = output->crtc;
 	for (ro = 0; ro < num_randr_outputs; ro++) 
-	{
 	    if (output->randr_output == randr_outputs[ro])
 	    {
-		randr_output = randr_outputs[ro];
+		new_crtc = crtc;
 		break;
 	    }
-	}
-	if (randr_output)
-	{
-	    if (output->pipe != pipe || !output->enabled)
-	    {
-		output->pipe = pipe;
-		output->enabled = TRUE;
-		changed = TRUE;
-	    }
-	}
-	else
+	if (new_crtc != output->crtc)
 	{
-	    /* Disable outputs which were on this pipe */
-	    if (output->enabled && output->pipe == pipe)
-	    {
-		output->enabled = FALSE;
-		changed = TRUE;
-		disable = TRUE;
-	    }
+	    changed = TRUE;
+	    output->crtc = new_crtc;
 	}
     }
     if (changed)
     {
-	pI830Pipe->enabled = mode != NULL;
+	crtc->enabled = mode != NULL;
+	
 	/* Sync the engine before adjust mode */
 	if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
 	    (*pI830->AccelInfoRec->Sync)(pScrn);
 	    pI830->AccelInfoRec->NeedToSync = FALSE;
 	}
 
-	if (display_mode)
+	if (mode)
 	{
-	    if (!i830PipeSetMode (pScrn, display_mode, pipe, TRUE))
+	    if (!i830PipeSetMode (crtc, mode, TRUE))
 	    {
-		pI830Pipe->enabled = save_enabled;
+		crtc->enabled = save_enabled;
 		for (o = 0; o < pI830->num_outputs; o++)
 		{
-		    I830OutputPtr	output = &pI830->output[o];
-		    output->enabled = save_output[o].enabled;
-		    output->pipe = save_output[o].pipe;
+		    I830_xf86OutputPtr	output = pI830->xf86_output[o];
+		    output->crtc = save_crtcs[o];
 		}
 		return FALSE;
 	    }
-	    pI830Pipe->desiredMode = *display_mode;
-	    i830PipeSetBase(pScrn, pipe, x, y);
+	    crtc->desiredMode = *mode;
+	    i830PipeSetBase(crtc, x, y);
 	}
-	randrp->modes[pipe] = display_mode;
-	if (disable)
-	    i830DisableUnusedFunctions (pScrn);
+	i830DisableUnusedFunctions (pScrn);
     }
-    return I830RandRCrtcNotify (crtc);
+    return I830RandRCrtcNotify (randr_crtc);
 }
 
 static Bool
@@ -696,23 +669,21 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
     RROutputPtr		    clones[MAX_OUTPUTS];
     RRCrtcPtr		    crtcs[MAX_DISPLAY_PIPES];
     int			    ncrtc;
-    I830OutputPtr	    output;
     int			    o, c, p;
     int			    clone_types;
     int			    crtc_types;
     int			    subpixel;
     RRCrtcPtr		    randr_crtc;
-    RROutputPtr		    randr_output;
     int			    nclone;
     
     for (o = 0; o < pI830->num_outputs; o++)
     {
-	output = &pI830->output[o];
-	randr_output = output->randr_output;
+	I830_xf86OutputPtr	output = pI830->xf86_output[o];
+	I830OutputPrivatePtr	intel_output = output->driver_private;
 	/*
 	 * Valid crtcs
 	 */
-	switch (output->type) {
+	switch (intel_output->type) {
 	case I830_OUTPUT_DVO:
 	case I830_OUTPUT_SDVO:
 	    crtc_types = ((1 << 0)|
@@ -749,10 +720,10 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	ncrtc = 0;
 	for (p = 0; p < pI830->num_pipes; p++)
 	    if (crtc_types & (1 << p))
-		crtcs[ncrtc++] = pI830->pipes[p].randr_crtc;
+		crtcs[ncrtc++] = pI830->xf86_crtc[p]->randr_crtc;
 
-	if (output->enabled)
-	    randr_crtc = pI830->pipes[output->pipe].randr_crtc;
+	if (output->crtc)
+	    randr_crtc = output->crtc->randr_crtc;
 	else
 	    randr_crtc = NULL;
 
@@ -765,7 +736,7 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 				output->mm_height);
 	I830xf86RROutputSetModes (output->randr_output, output->probed_modes);
 
-	switch (output->detect(pScrn, output)) {
+	switch ((*output->funcs->detect)(output)) {
 	case OUTPUT_STATUS_CONNECTED:
 	    RROutputSetConnection (output->randr_output, RR_Connected);
 	    break;
@@ -785,8 +756,11 @@ I830RandRSetInfo12 (ScrnInfoPtr pScrn)
 	nclone = 0;
 	for (c = 0; c < pI830->num_outputs; c++)
 	{
-	    if (o != c && ((1 << pI830->output[c].type) & clone_types))
-		clones[nclone++] = pI830->output[c].randr_output;
+	    I830_xf86OutputPtr	    clone = pI830->xf86_output[c];
+	    I830OutputPrivatePtr    intel_clone = clone->driver_private;
+	    
+	    if (o != c && ((1 << intel_clone->type) & clone_types))
+		clones[nclone++] = clone->randr_output;
 	}
 	if (!RROutputSetClones (output->randr_output, clones, nclone))
 	    return FALSE;
@@ -812,35 +786,20 @@ I830RandRCreateObjects12 (ScrnInfoPtr pS
 {
     I830Ptr		pI830 = I830PTR(pScrn);
     int			p;
-    int			o;
     
     if (!RRInit ())
 	return FALSE;
 
     /*
-     * Create RandR resources, then probe them
+     * Configure crtcs
      */
     for (p = 0; p < pI830->num_pipes; p++)
     {
-	I830PipePtr pipe = &pI830->pipes[p];
-	RRCrtcPtr   randr_crtc = RRCrtcCreate ((void *) p);
+	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[p];
 	
-	if (!randr_crtc)
-	    return FALSE;
-	RRCrtcGammaSetSize (randr_crtc, 256);
-	pipe->randr_crtc = randr_crtc;
+	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
 
-    for (o = 0; o < pI830->num_outputs; o++)
-    {
-	I830OutputPtr	output = &pI830->output[o];
-	const char	*name = i830_output_type_names[output->type];
-	RROutputPtr	randr_output = RROutputCreate (name, strlen (name),
-						       (void *) o);
-	if (!randr_output)
-	    return FALSE;
-	output->randr_output = randr_output;
-    }
     return TRUE;
 }
 
@@ -857,11 +816,11 @@ I830RandRCreateScreenResources12 (Screen
      * Attach RandR objects to screen
      */
     for (p = 0; p < pI830->num_pipes; p++)
-	if (!RRCrtcAttachScreen (pI830->pipes[p].randr_crtc, pScreen))
+	if (!RRCrtcAttachScreen (pI830->xf86_crtc[p]->randr_crtc, pScreen))
 	    return FALSE;
 
     for (o = 0; o < pI830->num_outputs; o++)
-	if (!RROutputAttachScreen (pI830->output[o].randr_output, pScreen))
+	if (!RROutputAttachScreen (pI830->xf86_output[o]->randr_output, pScreen))
 	    return FALSE;
 
     /*
@@ -870,13 +829,14 @@ I830RandRCreateScreenResources12 (Screen
     width = 0; height = 0;
     for (p = 0; p < pI830->num_pipes; p++)
     {
-	I830PipePtr pipe = &pI830->pipes[p];
-	int	    pipe_width = pipe->x + pipe->curMode.HDisplay;
-	int	    pipe_height = pipe->y + pipe->curMode.VDisplay;
-	if (pipe->enabled && pipe_width > width)
-	    width = pipe_width;
-	if (pipe->enabled && pipe_height > height)
-	    height = pipe_height;
+	I830_xf86CrtcPtr    crtc = pI830->xf86_crtc[p];
+	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;
+	if (crtc->enabled && crtc_height > height)
+	    height = crtc_height;
     }
     
     if (width && height)
@@ -900,7 +860,7 @@ I830RandRCreateScreenResources12 (Screen
     }
 
     for (p = 0; p < pI830->num_pipes; p++)
-	I830RandRCrtcNotify (pI830->pipes[p].randr_crtc);
+	I830RandRCrtcNotify (pI830->xf86_crtc[p]->randr_crtc);
     
     if (randrp->virtualX == -1 || randrp->virtualY == -1)
     {
@@ -1227,9 +1187,9 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
      * the initial configuration
      */
     for (o = 0; o < pI830->num_outputs; o++)
-	outputs[o] = pI830->output[o].randr_output;
+	outputs[o] = pI830->xf86_output[o]->randr_output;
     for (c = 0; c < pI830->num_pipes; c++)
-	crtcs[c] = pI830->pipes[c].randr_crtc;
+	crtcs[c] = pI830->xf86_crtc[c]->randr_crtc;
     
     if (!I830RRInitialConfiguration (outputs, output_crtcs, output_modes,
 				     pI830->num_outputs))
@@ -1253,30 +1213,19 @@ I830RandRPreInit (ScrnInfoPtr pScrn)
     pScrn->display->frameY0 = 0;
     for (o = 0; o < pI830->num_outputs; o++)
     {
-	RRModePtr	randr_mode = output_modes[o];
-	DisplayModePtr	mode;
-	RRCrtcPtr	randr_crtc = output_crtcs[o];
-	int		pipe;
-	Bool		enabled;
+	I830_xf86OutputPtr  output = pI830->xf86_output[o];
+	RRModePtr	    randr_mode = output_modes[o];
+	DisplayModePtr	    mode;
+	RRCrtcPtr	    randr_crtc = output_crtcs[o];
+	I830_xf86CrtcPtr    crtc = randr_crtc->devPrivate;
 
 	if (randr_mode)
 	    mode = (DisplayModePtr) randr_mode->devPrivate;
 	else
 	    mode = NULL;
-	if (randr_crtc)
-	{
-	    pipe = (int) randr_crtc->devPrivate;
-	    enabled = TRUE;
-	}
-	else
-	{
-	    pipe = 0;
-	    enabled = FALSE;
-	}
 	if (mode)
-	    pI830->pipes[pipe].desiredMode = *mode;
-	pI830->output[o].pipe = pipe;
-	pI830->output[o].enabled = enabled;
+	    crtc->desiredMode = *mode;
+	output->crtc = crtc;
     }
 #endif
     i830_set_xf86_modes_from_outputs (pScrn);
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index fedb8a6..a8eba4c 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -80,30 +80,32 @@ struct i830_sdvo_priv {
 };
 
 /** Read a single byte from the given address on the SDVO device. */
-static Bool i830_sdvo_read_byte(I830OutputPtr output, int addr,
+static Bool i830_sdvo_read_byte(I830_xf86OutputPtr output, int addr,
 				unsigned char *ch)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
     if (!xf86I2CReadByte(&dev_priv->d, addr, ch)) {
-	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
 		   "Unable to read from %s slave %d.\n",
-		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+		   intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
     return TRUE;
 }
 
 /** Write a single byte to the given address on the SDVO device. */
-static Bool i830_sdvo_write_byte(I830OutputPtr output,
+static Bool i830_sdvo_write_byte(I830_xf86OutputPtr output,
 				 int addr, unsigned char ch)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
     if (!xf86I2CWriteByte(&dev_priv->d, addr, ch)) {
-	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
 		   "Unable to write to %s Slave %d.\n",
-		   output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
+		   intel_output->pI2CBus->BusName, dev_priv->d.SlaveAddr);
 	return FALSE;
     }
     return TRUE;
@@ -164,16 +166,17 @@ static I2CSlaveAddr slaveAddr;
  * Writes out the data given in args (up to 8 bytes), followed by the opcode.
  */
 static void
-i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len)
+i830_sdvo_write_cmd(I830_xf86OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
-    int i;
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    int			    i;
 
     if (slaveAddr && slaveAddr != dev_priv->d.SlaveAddr)
 	ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr);
 
     /* Write the SDVO command logging */
-    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd);
+    xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd);
     for (i = 0; i < args_len; i++)
 	LogWrite(1, "%02X ", ((CARD8 *)args)[i]);
     for (; i < 8; i++)
@@ -210,10 +213,11 @@ static const char *cmd_status_names[] = 
  * Reads back response_len bytes from the SDVO device, and returns the status.
  */
 static CARD8
-i830_sdvo_read_response(I830OutputPtr output, void *response, int response_len)
+i830_sdvo_read_response(I830_xf86OutputPtr output, void *response, int response_len)
 {
-    int i;
-    CARD8 status;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    int			    i;
+    CARD8		    status;
 
     /* Read the command response */
     for (i = 0; i < response_len; i++) {
@@ -225,8 +229,8 @@ i830_sdvo_read_response(I830OutputPtr ou
     i830_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
 
     /* Write the SDVO command logging */
-    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO,
-	       "%s: R: ", SDVO_NAME(SDVO_PRIV(output)));
+    xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO,
+	       "%s: R: ", SDVO_NAME(SDVO_PRIV(intel_output)));
     for (i = 0; i < response_len; i++)
 	LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
     for (; i < 8; i++)
@@ -258,13 +262,13 @@ i830_sdvo_get_pixel_multiplier(DisplayMo
  * STOP.  PROM access is terminated by accessing an internal register.
  */
 static void
-i830_sdvo_set_control_bus_switch(I830OutputPtr output, CARD8 target)
+i830_sdvo_set_control_bus_switch(I830_xf86OutputPtr output, CARD8 target)
 {
     i830_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
 }
 
 static Bool
-i830_sdvo_set_target_input(I830OutputPtr output, Bool target_0, Bool target_1)
+i830_sdvo_set_target_input(I830_xf86OutputPtr output, Bool target_0, Bool target_1)
 {
     struct i830_sdvo_set_target_input_args targets = {0};
     CARD8 status;
@@ -290,7 +294,7 @@ i830_sdvo_set_target_input(I830OutputPtr
  * which should be checked against the docs.
  */
 static Bool
-i830_sdvo_get_trained_inputs(I830OutputPtr output, Bool *input_1, Bool *input_2)
+i830_sdvo_get_trained_inputs(I830_xf86OutputPtr output, Bool *input_1, Bool *input_2)
 {
     struct i830_sdvo_get_trained_inputs_response response;
     CARD8 status;
@@ -308,7 +312,7 @@ i830_sdvo_get_trained_inputs(I830OutputP
 }
 
 static Bool
-i830_sdvo_get_active_outputs(I830OutputPtr output,
+i830_sdvo_get_active_outputs(I830_xf86OutputPtr output,
 			     CARD16 *outputs)
 {
     CARD8 status;
@@ -320,7 +324,7 @@ i830_sdvo_get_active_outputs(I830OutputP
 }
 
 static Bool
-i830_sdvo_set_active_outputs(I830OutputPtr output,
+i830_sdvo_set_active_outputs(I830_xf86OutputPtr output,
 			     CARD16 outputs)
 {
     CARD8 status;
@@ -336,7 +340,7 @@ i830_sdvo_set_active_outputs(I830OutputP
  * Returns the pixel clock range limits of the current target input in kHz.
  */
 static Bool
-i830_sdvo_get_input_pixel_clock_range(I830OutputPtr output, int *clock_min,
+i830_sdvo_get_input_pixel_clock_range(I830_xf86OutputPtr output, int *clock_min,
 				      int *clock_max)
 {
     struct i830_sdvo_pixel_clock_range clocks;
@@ -357,7 +361,7 @@ i830_sdvo_get_input_pixel_clock_range(I8
 }
 
 static Bool
-i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs)
+i830_sdvo_set_target_output(I830_xf86OutputPtr output, CARD16 outputs)
 {
     CARD8 status;
 
@@ -371,7 +375,7 @@ i830_sdvo_set_target_output(I830OutputPt
 
 /** Fetches either input or output timings to *dtd, depending on cmd. */
 static Bool
-i830_sdvo_get_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
     CARD8 status;
 
@@ -391,20 +395,20 @@ i830_sdvo_get_timing(I830OutputPtr outpu
 }
 
 static Bool
-i830_sdvo_get_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_get_timing(output, SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_get_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_get_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_get_timing(output, SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
 /** Sets either input or output timings from *dtd, depending on cmd. */
 static Bool
-i830_sdvo_set_timing(I830OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_timing(I830_xf86OutputPtr output, CARD8 cmd, struct i830_sdvo_dtd *dtd)
 {
     CARD8 status;
 
@@ -422,20 +426,20 @@ i830_sdvo_set_timing(I830OutputPtr outpu
 }
 
 static Bool
-i830_sdvo_set_input_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_input_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_set_timing(output, SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
 }
 
 static Bool
-i830_sdvo_set_output_timing(I830OutputPtr output, struct i830_sdvo_dtd *dtd)
+i830_sdvo_set_output_timing(I830_xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
 {
     return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
 #if 0
 static Bool
-i830_sdvo_create_preferred_input_timing(I830OutputPtr output, CARD16 clock,
+i830_sdvo_create_preferred_input_timing(I830_xf86OutputPtr output, CARD16 clock,
 					CARD16 width, CARD16 height)
 {
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
@@ -479,9 +483,10 @@ i830_sdvo_get_preferred_input_timing(I83
 
 /** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
 static int
-i830_sdvo_get_clock_rate_mult(I830OutputPtr output)
+i830_sdvo_get_clock_rate_mult(I830_xf86OutputPtr output)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     CARD8 response;
     CARD8 status;
 
@@ -507,7 +512,7 @@ i830_sdvo_get_clock_rate_mult(I830Output
  * is actually turned on.
  */
 static Bool
-i830_sdvo_set_clock_rate_mult(I830OutputPtr output, CARD8 val)
+i830_sdvo_set_clock_rate_mult(I830_xf86OutputPtr output, CARD8 val)
 {
     CARD8 status;
 
@@ -520,11 +525,12 @@ i830_sdvo_set_clock_rate_mult(I830Output
 }
 
 static void
-i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		       DisplayModePtr mode)
+i830_sdvo_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     CARD16 width;
     CARD16 height;
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
@@ -621,15 +627,18 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 }
 
 static void
-i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-			DisplayModePtr mode)
+i830_sdvo_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr mode)
 {
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    I830_xf86CrtcPtr	    crtc = output->crtc;
+    I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     Bool input1, input2;
     CARD32 dpll, sdvox;
-    int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
-    int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+    int dpll_reg = (intel_crtc->pipe == 0) ? DPLL_A : DPLL_B;
+    int dpll_md_reg = (intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
     int i;
     CARD8 status;
@@ -645,7 +654,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 	break;
     }
     sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
-    if (output->pipe == 1)
+    if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
     dpll = INREG(dpll_reg);
@@ -681,10 +690,12 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
 }
 
 static void
-i830_sdvo_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+i830_sdvo_dpms(I830_xf86OutputPtr output, int mode)
 {
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     if (mode != DPMSModeOn) {
 	i830_sdvo_set_active_outputs(output, 0);
@@ -696,11 +707,13 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830Ou
 }
 
 static void
-i830_sdvo_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_sdvo_save(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-    int o;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    int			    o;
 
     /* XXX: We should save the in/out mapping. */
 
@@ -731,11 +744,13 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
 }
 
 static void
-i830_sdvo_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_sdvo_restore(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
-    int o;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    int			    o;
 
     if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
        i830_sdvo_set_target_input(output, TRUE, FALSE);
@@ -764,10 +779,10 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
 }
 
 static int
-i830_sdvo_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
-		     DisplayModePtr pMode)
+i830_sdvo_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
@@ -782,7 +797,7 @@ i830_sdvo_mode_valid(ScrnInfoPtr pScrn, 
 }
 
 static Bool
-i830_sdvo_get_capabilities(I830OutputPtr output, struct i830_sdvo_caps *caps)
+i830_sdvo_get_capabilities(I830_xf86OutputPtr output, struct i830_sdvo_caps *caps)
 {
     CARD8 status;
 
@@ -836,8 +851,9 @@ i830_sdvo_ddc_i2c_put_byte(I2CDevPtr d, 
 static Bool
 i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
 {
-    I830OutputPtr output = b->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = output->pI2CBus;
+    I830_xf86OutputPtr	    output = b->DriverPrivate.ptr;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I2CBusPtr		    i2cbus = intel_output->pI2CBus;
 
     i830_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
     return i2cbus->I2CStart(i2cbus, timeout);
@@ -847,8 +863,9 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int
 static void
 i830_sdvo_ddc_i2c_stop(I2CDevPtr d)
 {
-    I830OutputPtr output = d->pI2CBus->DriverPrivate.ptr;
-    I2CBusPtr i2cbus = output->pI2CBus, savebus;
+    I830_xf86OutputPtr	    output = d->DriverPrivate.ptr;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    I2CBusPtr		    i2cbus = intel_output->pI2CBus, savebus;
 
     savebus = d->pI2CBus;
     d->pI2CBus = i2cbus;
@@ -883,18 +900,19 @@ i830_sdvo_ddc_i2c_address(I2CDevPtr d, I
 }
 
 static void
-i830_sdvo_dump_cmd(I830OutputPtr output, int opcode)
+i830_sdvo_dump_cmd(I830_xf86OutputPtr output, int opcode)
 {
-    CARD8 response[8];
+    CARD8		    response[8];
 
     i830_sdvo_write_cmd(output, opcode, NULL, 0);
     i830_sdvo_read_response(output, response, 8);
 }
 
 static void
-i830_sdvo_dump_device(I830OutputPtr output)
+i830_sdvo_dump_device(I830_xf86OutputPtr output)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
     ErrorF("Dump %s\n", dev_priv->d.DevName);
     i830_sdvo_dump_cmd(output, SDVO_CMD_GET_DEVICE_CAPS);
@@ -926,9 +944,13 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
     I830Ptr pI830 = I830PTR(pScrn);
     int	i;
 
-    for (i = 0; i < pI830->num_outputs; i++) {
-	if (pI830->output[i].type == I830_OUTPUT_SDVO)
-	    i830_sdvo_dump_device(&pI830->output[i]);
+    for (i = 0; i < pI830->num_outputs; i++) 
+    {
+	I830_xf86OutputPtr	output = pI830->xf86_output[i];
+	I830OutputPrivatePtr	intel_output = output->driver_private;
+	
+	if (intel_output->type == I830_OUTPUT_SDVO)
+	    i830_sdvo_dump_device(output);
     }
 }
 
@@ -942,7 +964,7 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
  * Takes 14ms on average on my i945G.
  */
 static enum detect_status
-i830_sdvo_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_sdvo_detect(I830_xf86OutputPtr output)
 {
     CARD8 response[2];
     CARD8 status;
@@ -959,25 +981,59 @@ i830_sdvo_detect(ScrnInfoPtr pScrn, I830
 	return OUTPUT_STATUS_DISCONNECTED;
 }
 
+static void
+i830_sdvo_destroy (I830_xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+
+    if (intel_output)
+    {
+	struct i830_sdvo_priv	*dev_priv = intel_output->dev_priv;
+	
+	xf86DestroyI2CBusRec (intel_output->pDDCBus, FALSE, FALSE);
+	xf86DestroyI2CDevRec (&dev_priv->d, FALSE);
+	xf86DestroyI2CBusRec (dev_priv->d.pI2CBus, TRUE, TRUE);
+	xfree (intel_output);
+    }
+}
+
+static const I830_xf86OutputFuncsRec i830_sdvo_output_funcs = {
+    .dpms = i830_sdvo_dpms,
+    .save = i830_sdvo_save,
+    .restore = i830_sdvo_restore,
+    .mode_valid = i830_sdvo_mode_valid,
+    .pre_set_mode = i830_sdvo_pre_set_mode,
+    .post_set_mode = i830_sdvo_post_set_mode,
+    .detect = i830_sdvo_detect,
+    .get_modes = i830_ddc_get_modes,
+    .destroy = i830_sdvo_destroy
+};
+
 void
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830OutputPtr output = &pI830->output[pI830->num_outputs];
-    struct i830_sdvo_priv *dev_priv;
-    int i;
-    unsigned char ch[0x40];
-    I2CBusPtr i2cbus = NULL, ddcbus;
-
-    output->type = I830_OUTPUT_SDVO;
-    output->dpms = i830_sdvo_dpms;
-    output->save = i830_sdvo_save;
-    output->restore = i830_sdvo_restore;
-    output->mode_valid = i830_sdvo_mode_valid;
-    output->pre_set_mode = i830_sdvo_pre_set_mode;
-    output->post_set_mode = i830_sdvo_post_set_mode;
-    output->detect = i830_sdvo_detect;
-    output->get_modes = i830_ddc_get_modes;
+    I830_xf86OutputPtr	    output;
+    I830OutputPrivatePtr    intel_output;
+    struct i830_sdvo_priv   *dev_priv;
+    int			    i;
+    unsigned char	    ch[0x40];
+    I2CBusPtr		    i2cbus = NULL, ddcbus;
+
+    output = i830xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,
+				   "ADD2 PCIE card");
+    if (!output)
+	return;
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+			      sizeof (struct i830_sdvo_priv), 1);
+    if (!intel_output)
+    {
+	i830xf86OutputDestroy (output);
+	return;
+    }
+    output->driver_private = intel_output;
+    
+    dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
+    intel_output->type = I830_OUTPUT_SDVO;
 
     /* While it's the same bus, we just initialize a new copy to avoid trouble
      * with tracking refcounting ourselves, since the XFree86 DDX bits don't.
@@ -988,12 +1044,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	I830I2CInit(pScrn, &i2cbus, GPIOE, "SDVOCTRL_E for SDVOC");
 
     if (i2cbus == NULL)
-	return;
-
-    /* Allocate the SDVO output private data */
-    dev_priv = xcalloc(1, sizeof(struct i830_sdvo_priv));
-    if (dev_priv == NULL) {
-	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
+    {
+	i830xf86OutputDestroy (output);
 	return;
     }
 
@@ -1008,12 +1060,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     dev_priv->d.DriverPrivate.ptr = output;
     dev_priv->output_device = output_device;
 
-    if (!xf86I2CDevInit(&dev_priv->d)) {
+    if (!xf86I2CDevInit(&dev_priv->d)) 
+    {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Failed to initialize %s I2C device\n",
 		   SDVO_NAME(dev_priv));
-	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(dev_priv);
+	i830xf86OutputDestroy (output);
 	return;
     }
 
@@ -1023,10 +1075,9 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
      * Start, extra attempts should be harmless.
      */
     ddcbus = xf86CreateI2CBusRec();
-    if (ddcbus == NULL) {
-	xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
-	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(dev_priv);
+    if (ddcbus == NULL) 
+    {
+	i830xf86OutputDestroy (output);
 	return;
     }
     if (output_device == SDVOB)
@@ -1039,25 +1090,22 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
     ddcbus->I2CStart = i830_sdvo_ddc_i2c_start;
     ddcbus->I2CStop = i830_sdvo_ddc_i2c_stop;
     ddcbus->I2CAddress = i830_sdvo_ddc_i2c_address;
-    ddcbus->DriverPrivate.ptr = &pI830->output[pI830->num_outputs];
-    if (!xf86I2CBusInit(ddcbus)) {
-	xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
-	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	xfree(dev_priv);
+    ddcbus->DriverPrivate.ptr = output;
+    
+    if (!xf86I2CBusInit(ddcbus)) 
+    {
+	i830xf86OutputDestroy (output);
 	return;
     }
 
-    output->pI2CBus = i2cbus;
-    output->pDDCBus = ddcbus;
-    output->dev_priv = dev_priv;
+    intel_output->pI2CBus = i2cbus;
+    intel_output->pDDCBus = ddcbus;
+    intel_output->dev_priv = dev_priv;
 
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
 	if (!i830_sdvo_read_byte(output, i, &ch[i])) {
-	    xf86DestroyI2CBusRec(output->pDDCBus, FALSE, FALSE);
-	    xf86DestroyI2CDevRec(&dev_priv->d, FALSE);
-	    xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
-	    xfree(dev_priv);
+	    i830xf86OutputDestroy (output);
 	    return;
 	}
     }
@@ -1074,7 +1122,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	unsigned char	bytes[2];
 
 	memcpy (bytes, &dev_priv->caps.output_flags, 2);
-	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_ERROR,
 		   "%s: No active TMDS outputs (0x%02x%02x)\n",
 		   SDVO_NAME(dev_priv),
 		   bytes[0], bytes[1]);
@@ -1100,6 +1148,4 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
 	       dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N',
 	       dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N');
-
-    pI830->num_outputs++;
 }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index f938d5c..ec78337 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -143,11 +143,14 @@ const struct tv_mode {
 
 
 static int
-i830_tv_detect_type(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_tv_detect_type(I830_xf86OutputPtr output)
 {
+    ScrnInfoPtr		pScrn = output->scrn;
+    I830Ptr		pI830 = I830PTR(pScrn);
+    I830_xf86CrtcPtr	crtc = output->crtc;
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     CARD32 save_tv_ctl, save_tv_dac;
     CARD32 tv_ctl, tv_dac;
-    I830Ptr pI830 = I830PTR(pScrn);
 
     save_tv_ctl = INREG(TV_CTL);
     save_tv_dac = INREG(TV_DAC);
@@ -156,7 +159,7 @@ i830_tv_detect_type(ScrnInfoPtr pScrn, I
      * which is already enabled.
      */
     tv_ctl = INREG(TV_CTL) & ~(TV_ENC_ENABLE | TV_ENC_PIPEB_SELECT);
-    if (output->pipe == 1)
+    if (intel_crtc->pipe == 1)
 	tv_ctl |= TV_ENC_PIPEB_SELECT;
     OUTREG(TV_CTL, tv_ctl);
 
@@ -200,8 +203,9 @@ i830_tv_detect_type(ScrnInfoPtr pScrn, I
 }
 
 static void
-i830_tv_dpms(ScrnInfoPtr pScrn, I830OutputPtr output, int mode)
+i830_tv_dpms(I830_xf86OutputPtr output, int mode)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
 
     switch(mode) {
@@ -217,10 +221,12 @@ i830_tv_dpms(ScrnInfoPtr pScrn, I830Outp
 }
 
 static void
-i830_tv_save(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_tv_save(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_tv_priv *dev_priv = output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
 
     dev_priv->save_TV_H_CTL_1 = INREG(TV_H_CTL_1);
     dev_priv->save_TV_H_CTL_2 = INREG(TV_H_CTL_2);
@@ -241,10 +247,12 @@ i830_tv_save(ScrnInfoPtr pScrn, I830Outp
 }
 
 static void
-i830_tv_restore(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_tv_restore(I830_xf86OutputPtr output)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    struct i830_tv_priv *dev_priv = output->dev_priv;
+    ScrnInfoPtr		    pScrn = output->scrn;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_tv_priv	    *dev_priv = intel_output->dev_priv;
 
     OUTREG(TV_H_CTL_1, dev_priv->save_TV_H_CTL_1);
     OUTREG(TV_H_CTL_2, dev_priv->save_TV_H_CTL_2);
@@ -265,16 +273,15 @@ i830_tv_restore(ScrnInfoPtr pScrn, I830O
 }
 
 static int
-i830_tv_mode_valid(ScrnInfoPtr pScrn, I830OutputPtr output,
-		   DisplayModePtr pMode)
+i830_tv_mode_valid(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
     return MODE_OK;
 }
 
 static void
-i830_tv_pre_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		     DisplayModePtr pMode)
+i830_tv_pre_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
 
     /* Disable the encoder while we set up the pipe. */
@@ -348,10 +355,12 @@ static const CARD32 v_chroma[43] = {
 };
 
 static void
-i830_tv_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
-		      DisplayModePtr pMode)
+i830_tv_post_set_mode(I830_xf86OutputPtr output, DisplayModePtr pMode)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
+    I830_xf86CrtcPtr	crtc = output->crtc;
+    I830CrtcPrivatePtr	intel_crtc = crtc->driver_private;
     enum tv_type type;
     const struct tv_mode *tv_mode;
     const struct tv_sc_mode *sc_mode;
@@ -368,7 +377,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
     tv_mode = &tv_modes[0];
     sc_mode = &tv_sc_modes[TV_SC_NTSC_MJ];
 
-    type = i830_tv_detect_type(pScrn, output);
+    type = i830_tv_detect_type(output);
 
     hctl1 = (tv_mode->hsync_end << TV_HSYNC_END_SHIFT) |
 	(tv_mode->htotal << TV_HTOTAL_SHIFT);
@@ -408,7 +417,7 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
 	(tv_mode->vburst_end_f4 << TV_VBURST_END_F4_SHIFT);
 
     tv_ctl = TV_ENC_ENABLE;
-    if (output->pipe == 1)
+    if (intel_crtc->pipe == 1)
 	tv_ctl |= TV_ENC_PIPEB_SELECT;
 
     switch (type) {
@@ -501,8 +510,9 @@ i830_tv_post_set_mode(ScrnInfoPtr pScrn,
  * we have a pipe programmed in order to probe the TV.
  */
 static enum detect_status
-i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_tv_detect(I830_xf86OutputPtr output)
 {
+    /* XXX need to load-detect */
     return OUTPUT_STATUS_CONNECTED;
 }
 
@@ -513,8 +523,9 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830Ou
  * how to probe modes off of TV connections.
  */
 static DisplayModePtr
-i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
+i830_tv_get_modes(I830_xf86OutputPtr output)
 {
+    ScrnInfoPtr pScrn = output->scrn;
     I830Ptr pI830 = I830PTR(pScrn);
     DisplayModePtr new;
     char stmp[32];
@@ -553,36 +564,52 @@ i830_tv_get_modes(ScrnInfoPtr pScrn, I83
     return new;
 }
 
+static void
+i830_tv_destroy (I830_xf86OutputPtr output)
+{
+    if (output->driver_private)
+	xfree (output->driver_private);
+}
+
+static const I830_xf86OutputFuncsRec i830_tv_output_funcs = {
+    .dpms = i830_tv_dpms,
+    .save = i830_tv_save,
+    .restore = i830_tv_restore,
+    .mode_valid = i830_tv_mode_valid,
+    .pre_set_mode = i830_tv_pre_set_mode,
+    .post_set_mode = i830_tv_post_set_mode,
+    .detect = i830_tv_detect,
+    .get_modes = i830_tv_get_modes,
+    .destroy = i830_tv_destroy
+};
+
 void
 i830_tv_init(ScrnInfoPtr pScrn)
 {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830OutputPtr output = &pI830->output[pI830->num_outputs];
-    struct i830_tv_priv *dev_priv;
+    I830Ptr		    pI830 = I830PTR(pScrn);
+    I830_xf86OutputPtr	    output;
+    I830OutputPrivatePtr    intel_output;
+    struct i830_tv_priv	    *dev_priv;
  
     if ((INREG(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 	return;
 
-    output->type = I830_OUTPUT_TVOUT;
-    output->pipe = 0;
-    output->enabled = FALSE;
-    output->load_detect_temp = FALSE;
+    output = i830xf86OutputCreate (pScrn, &i830_tv_output_funcs,
+				   "TV");
     
-    output->dpms = i830_tv_dpms;
-    output->save = i830_tv_save;
-    output->restore = i830_tv_restore;
-    output->mode_valid = i830_tv_mode_valid;
-    output->pre_set_mode = i830_tv_pre_set_mode;
-    output->post_set_mode = i830_tv_post_set_mode;
-    output->detect = i830_tv_detect;
-    output->get_modes = i830_tv_get_modes;
-
-    dev_priv = xnfcalloc(1, sizeof(struct i830_tv_priv));
+    if (!output)
+	return;
     
-    if (dev_priv == NULL)
+    intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
+			      sizeof (struct i830_tv_priv), 1);
+    if (!intel_output)
+    {
+	i830xf86OutputDestroy (output);
 	return;
-
-    output->dev_priv = dev_priv;
-    ErrorF ("TV out is output %d\n", pI830->num_outputs);
-    pI830->num_outputs++;
+    }
+    dev_priv = (struct i830_tv_priv *) (intel_output + 1);
+    intel_output->type = I830_OUTPUT_SDVO;
+    intel_output->dev_priv = dev_priv;
+    
+    output->driver_private = intel_output;
 }
diff --git a/src/i830_video.c b/src/i830_video.c
index d84c1c9..5ce2b5d 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -3595,7 +3595,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pSc
    }
 
    /* Check we have an LFP connected */
-   if (i830PipeHasType (pScrn, pPriv->pipe, I830_OUTPUT_LVDS)) 
+   if (i830PipeHasType (pI830->xf86_crtc[pPriv->pipe], I830_OUTPUT_LVDS)) 
    {
       size = pPriv->pipe ? INREG(PIPEBSRC) : INREG(PIPEASRC);
       hsize = (size >> 16) & 0x7FF;
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
new file mode 100644
index 0000000..d0a3119
--- /dev/null
+++ b/src/i830_xf86Crtc.c
@@ -0,0 +1,126 @@
+/*
+ * $Id: $
+ *
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_xf86Modes.h"
+#include "i830_xf86Crtc.h"
+
+/*
+ * Crtc functions
+ */
+I830_xf86CrtcPtr
+i830xf86CrtcCreate (ScrnInfoPtr		    scrn,
+		    I830_xf86CrtcFuncsPtr   funcs)
+{
+    I830_xf86CrtcPtr	xf86_crtc;
+
+    xf86_crtc = xcalloc (sizeof (I830_xf86CrtcRec), 1);
+    if (!xf86_crtc)
+	return NULL;
+    xf86_crtc->scrn = scrn;
+    xf86_crtc->funcs = funcs;
+#ifdef RANDR_12_INTERFACE
+    xf86_crtc->randr_crtc = RRCrtcCreate (xf86_crtc);
+    if (!xf86_crtc->randr_crtc)
+    {
+	xfree (xf86_crtc);
+	return NULL;
+    }
+#endif
+    return xf86_crtc;
+}
+
+void
+i830xf86CrtcDestroy (I830_xf86CrtcPtr xf86_crtc)
+{
+#ifdef RANDR_12_INTERFACE
+    RRCrtcDestroy (xf86_crtc->randr_crtc);
+#endif
+    xfree (xf86_crtc);
+}
+
+/*
+ * Output functions
+ */
+I830_xf86OutputPtr
+i830xf86OutputCreate (ScrnInfoPtr		    scrn,
+		      const I830_xf86OutputFuncsRec *funcs,
+		      const char		    *name)
+{
+    I830_xf86OutputPtr	output;
+    I830Ptr		pI830 = I830PTR(scrn);
+    int			len = strlen (name);
+
+    output = xcalloc (sizeof (I830_xf86OutputRec) + len + 1, 1);
+    if (!output)
+	return NULL;
+    output->scrn = scrn;
+    output->funcs = funcs;
+    output->name = (char *) (output + 1);
+    strcpy (output->name, name);
+#ifdef RANDR_12_INTERFACE
+    output->randr_output = RROutputCreate (name, strlen (name), output);
+    if (!output->randr_output)
+    {
+	xfree (output);
+	return NULL;
+    }
+#endif
+    pI830->xf86_output[pI830->num_outputs++] = output;
+    return output;
+}
+
+void
+i830xf86OutputDestroy (I830_xf86OutputPtr output)
+{
+    ScrnInfoPtr	scrn = output->scrn;
+    I830Ptr	pI830 = I830PTR(scrn);
+    int		o;
+    
+    (*output->funcs->destroy) (output);
+#ifdef RANDR_12_INTERFACE
+    RROutputDestroy (output->randr_output);
+#endif
+    while (output->probed_modes)
+	xf86DeleteMode (&output->probed_modes, output->probed_modes);
+    for (o = 0; o < pI830->num_outputs; o++)
+	if (pI830->xf86_output[o] == output)
+	{
+	    memmove (&pI830->xf86_output[o],
+		     &pI830->xf86_output[o+1],
+		     pI830->num_outputs - (o + 1));
+	    break;
+	}
+    xfree (output);
+}
+
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
new file mode 100644
index 0000000..6a52517
--- /dev/null
+++ b/src/i830_xf86Crtc.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#ifndef _I830_XF86CRTC_H_
+#define _I830_XF86CRTC_H_
+
+#include <edid.h>
+#include "i830_xf86Modes.h"
+
+typedef struct _I830_xf86Crtc I830_xf86CrtcRec, *I830_xf86CrtcPtr;
+
+typedef struct _I830_xf86CrtcFuncs {
+   /**
+    * Turns the crtc on/off, or sets intermediate power levels if available.
+    *
+    * Unsupported intermediate modes drop to the lower power setting.  If the
+    * mode is DPMSModeOff, the crtc must be disabled, as the DPLL may be
+    * disabled afterwards.
+    */
+   void
+    (*dpms)(I830_xf86CrtcPtr		crtc,
+	    int				mode);
+
+   /**
+    * Saves the crtc's state for restoration on VT switch.
+    */
+   void
+    (*save)(I830_xf86CrtcPtr		crtc);
+
+   /**
+    * Restore's the crtc's state at VT switch.
+    */
+   void
+    (*restore)(I830_xf86CrtcPtr		crtc);
+
+    /**
+     * Clean up driver-specific bits of the crtc
+     */
+    void
+    (*destroy) (I830_xf86CrtcPtr	crtc);
+} I830_xf86CrtcFuncsRec, *I830_xf86CrtcFuncsPtr;
+
+struct _I830_xf86Crtc {
+    /**
+     * Associated ScrnInfo
+     */
+    ScrnInfoPtr		scrn;
+    
+    /**
+     * Active state of this CRTC
+     *
+     * Set when this CRTC is driving one or more outputs 
+     */
+    Bool	    enabled;
+    
+    /**
+     * Position on screen
+     *
+     * Locates this CRTC within the frame buffer
+     */
+    int		    x, y;
+    
+    /** Track whether cursor is within CRTC range  */
+    Bool	    cursorInRange;
+    
+    /** Track state of cursor associated with this CRTC */
+    Bool	    cursorShown;
+    
+    /**
+     * Active mode
+     *
+     * This reflects the mode as set in the CRTC currently
+     * It will be cleared when the VT is not active or
+     * during server startup
+     */
+    DisplayModeRec  curMode;
+    
+    /**
+     * Desired mode
+     *
+     * This is set to the requested mode, independent of
+     * whether the VT is active. In particular, it receives
+     * the startup configured mode and saves the active mode
+     * on VT switch.
+     */
+    DisplayModeRec  desiredMode;
+    
+    /** crtc-specific functions */
+    const I830_xf86CrtcFuncsRec *funcs;
+
+    /**
+     * Driver private
+     *
+     * Holds driver-private information
+     */
+    void	    *driver_private;
+
+#ifdef RANDR_12_INTERFACE
+    /**
+     * RandR crtc
+     *
+     * When RandR 1.2 is available, this
+     * points at the associated crtc object
+     */
+    RRCrtcPtr	    randr_crtc;
+#else
+    void	    *randr_crtc;
+#endif
+};
+
+typedef struct _I830_xf86Output I830_xf86OutputRec, *I830_xf86OutputPtr;
+
+typedef struct _I830_xf86OutputFuncs {
+    /**
+     * Turns the output on/off, or sets intermediate power levels if available.
+     *
+     * Unsupported intermediate modes drop to the lower power setting.  If the
+     * mode is DPMSModeOff, the output must be disabled, as the DPLL may be
+     * disabled afterwards.
+     */
+    void
+    (*dpms)(I830_xf86OutputPtr	output,
+	    int			mode);
+
+    /**
+     * Saves the output's state for restoration on VT switch.
+     */
+    void
+    (*save)(I830_xf86OutputPtr		output);
+
+    /**
+     * Restore's the output's state at VT switch.
+     */
+    void
+    (*restore)(I830_xf86OutputPtr	output);
+
+    /**
+     * Callback for testing a video mode for a given output.
+     *
+     * This function should only check for cases where a mode can't be supported
+     * on the pipe specifically, and not represent generic CRTC limitations.
+     *
+     * \return MODE_OK if the mode is valid, or another MODE_* otherwise.
+     */
+    int
+    (*mode_valid)(I830_xf86OutputPtr	output,
+		  DisplayModePtr	pMode);
+
+    /**
+     * Callback for setting up a video mode before any crtc/dpll changes.
+     *
+     * \param pMode the mode that will be set, or NULL if the mode to be set is
+     * unknown (such as the restore path of VT switching).
+     */
+    void
+    (*pre_set_mode)(I830_xf86OutputPtr  output,
+		    DisplayModePtr	pMode);
+
+    /**
+     * Callback for setting up a video mode after the DPLL update but before
+     * the plane is enabled.
+     */
+    void
+    (*post_set_mode)(I830_xf86OutputPtr	output,
+		     DisplayModePtr	pMode);
+
+    /**
+     * Probe for a connected output, and return detect_status.
+     */
+    enum detect_status
+    (*detect)(I830_xf86OutputPtr	output);
+
+    /**
+     * Query the device for the modes it provides.
+     *
+     * This function may also update MonInfo, mm_width, and mm_height.
+     *
+     * \return singly-linked list of modes or NULL if no modes found.
+     */
+    DisplayModePtr
+    (*get_modes)(I830_xf86OutputPtr	output);
+
+    /**
+     * Clean up driver-specific bits of the output
+     */
+    void
+    (*destroy) (I830_xf86OutputPtr	output);
+} I830_xf86OutputFuncsRec, *I830_xf86OutputFuncsPtr;
+
+struct _I830_xf86Output {
+    /**
+     * Associated ScrnInfo
+     */
+    ScrnInfoPtr		scrn;
+    /**
+     * Currently connected crtc (if any)
+     *
+     * If this output is not in use, this field will be NULL.
+     */
+    I830_xf86CrtcPtr	crtc;
+    /**
+     * List of available modes on this output.
+     *
+     * This should be the list from get_modes(), plus perhaps additional
+     * compatible modes added later.
+     */
+    DisplayModePtr	probed_modes;
+
+    /** EDID monitor information */
+    xf86MonPtr		MonInfo;
+
+    /** Physical size of the currently attached output device. */
+    int			mm_width, mm_height;
+
+    /** Output name */
+    char		*name;
+
+    /** output-specific functions */
+    const I830_xf86OutputFuncsRec *funcs;
+
+    /** driver private information */
+    void		*driver_private;
+    
+#ifdef RANDR_12_INTERFACE
+    /**
+     * RandR 1.2 output structure.
+     *
+     * When RandR 1.2 is available, this points at the associated
+     * RandR output structure and is created when this output is created
+     */
+    RROutputPtr		randr_output;
+#else
+    void		*randr_output;
+#endif
+};
+
+/*
+ * Crtc functions
+ */
+I830_xf86CrtcPtr
+i830xf86CrtcCreate (ScrnInfoPtr			scrn,
+		    const I830_xf86CrtcFuncsPtr	funcs);
+
+void
+i830xf86CrtcDestroy (I830_xf86CrtcPtr		xf86_crtc);
+
+
+/**
+ * Allocate a crtc for the specified output
+ *
+ * Find a currently unused CRTC which is suitable for
+ * the specified output
+ */
+
+I830_xf86CrtcPtr 
+i830xf86AllocCrtc (I830_xf86OutputPtr		output);
+
+/**
+ * Free a crtc
+ *
+ * Mark the crtc as unused by any outputs
+ */
+
+void
+i830xf86FreeCrtc (I830_xf86CrtcPtr crtc);
+
+/*
+ * Output functions
+ */
+I830_xf86OutputPtr
+i830xf86OutputCreate (ScrnInfoPtr		    scrn,
+		      const I830_xf86OutputFuncsRec *funcs,
+		      const char		    *name);
+
+void
+i830xf86OutputDestroy (I830_xf86OutputPtr	xf86_output);
+
+#endif /* _I830_XF86CRTC_H_ */
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index 5a26c0e..30b926a 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -25,6 +25,9 @@
  *
  */
 
+#ifndef _I830_XF86MODES_H_
+#define _I830_XF86MODES_H_
+
 double
 i830xf86ModeHSync(DisplayModePtr mode);
 
@@ -77,3 +80,5 @@ void
 PrintModeline(int scrnIndex,DisplayModePtr mode);
 
 extern DisplayModeRec I830xf86DefaultModes[];
+
+#endif /* _I830_XF86MODES_H_ */



More information about the xorg-commit mailing list